reactjs - Draft.js (react-draft-wysiwyg): tekstoppdatering fra utsiden av Editor-komponenten fungerer ikke


Jeg prøver å oppdatere teksten fra en kallende komponent til Editor-komponenten. Jeg bruker props for å sende teksten fra den kallende komponenten, men når teksten endres (props oppdateres i ContentEditor) oppdateres ikke teksten i Editor-komponenten:

Her er koden til den kallende komponenten:

<ControlledEditor htmlContent={this.state.validationResultContent}/>

Her er koden til den kontrollerte redigereren:

    export class ControlledEditor extends Component {
    constructor(props) {
        super(props);
        this.state = {editorState: EditorState.createWithText(this.props.htmlContent)};
    }


    onEditorStateChange = (editorState) => {
        this.setState({ editorState })
    };

    render() {

        const { editorState } = this.state;

        return (
            <>
                <Container className="mt-5">
                    <Row>
                        <Editor
                            editorState= {editorState}
                            onEditorStateChange={this.onEditorStateChange}
                            wrapperClassName="demo-wrapper"
                            editorClassName="demo-editor"

                        />
                    </Row>
                </Container>
            </>
        );
    }
}

ControlledEditor.propTypes = {
    htmlContent: PropTypes.string
}

takk for hjelpen

------- OPPDATERING 1 -------

  • Jeg bruker react-draft-wysiwyg bygget på Draft.js
  • Teksten som skal vises er HTML, så jeg oppdaterte koden
  • svar fra Linda Paiste med componentDidUpdate løser hovedproblemet link

Følgende fungerende kode (for meg):

export class ControlledEditor extends Component {
    constructor(props) {
        super(props);
        this.state = {editorState: EditorState.createEmpty()}
    }

    componentDidUpdate(prevProps) {
        if (this.props.htmlContent !== prevProps.htmlContent) {
            this.setState({
                    editorState: EditorState.createWithContent(ContentState.createFromBlockArray(convertFromHTML(this.props.htmlContent)))
            });
        }
    }

    onEditorStateChange = (editorState) => {
        this.setState({editorState})
    };

    render() {
        const {editorState} = this.state;
        return (
            <>
                <Container className="mt-5">
                    <Row>
                        <Editor
                            editorState={editorState}
                            wrapperClassName="demo-wrapper"
                            editorClassName="demo-editor"
                            onEditorStateChange={this.onEditorStateChange}
                        />
                    </Row>
                </Container>
                <Container className="mt-5">
                    <Row>
                        <div dangerouslySetInnerHTML={{__html: this.props.htmlContent}}/>
                    </Row>
                </Container>
              
            </>
        );
    }
}

ControlledEditor.propTypes = {
    htmlContent: PropTypes.string
}

Svar #1

Valgfritt: Oppdatering av Draft.js-versjon

Noen av egenskapene du bruker ser ikke ut til å være dokumentert. Kanskje de er fra en tidligere versjon av draft-js? Men jeg vil skrive dette svaret basert på den nåværende dokumentasjonen.

Rekvisitten onEditorStateChange til Editor bør endres til onChange.

Det finnes ingen createFromText på EditorState. Denne erstatningen innebærer to trinn:

  1. ContentState kan opprettes fra tekst med den statiske metoden ContentState.createFromText.
  2. EditorState kan opprettes fra ContentState med den statiske metoden EditorState.createWithContent

Så den opprinnelige tilstanden bør være:

this.state = {
  editorState: EditorState.createWithContent(
    ContentState.createFromText(this.props.htmlContent)
  )
};

Kjerneproblemet

Med det ute av veien, kan jeg kjøre koden din og gjenskape problemet ditt:

Jeg bruker props for å sende teksten fra kaller, men når teksten endres (props oppdateres i ContentEditor) blir ikke teksten i Editor-komponenten oppdatert.

Du oppretter this.state.editorState basert på verdien av this.props.htmlContent i konstruktøren. Den delen av koden kjører bare én gang når ControlledEditor-komponenten først monteres. Den kjører ikke på nytt når props endres, så den kan ikke reagere på endringer i this.props.

Du må legge til en componentDidUpdate livssyklusmetode for det.

componentDidUpdate(prevProps) {
  if (this.props.htmlContent !== prevProps.htmlContent) {
    this.setState({
      editorState: EditorState.createWithContent(
        ContentState.createFromText(this.props.htmlContent)
      )
    });
  }
}

Etter min mening er det enklere å konvertere dette til en funksjonskomponent og bruke hooks.

import { useEffect, useState } from "react";
import { Editor, EditorState, ContentState } from "draft-js";
import "draft-js/dist/Draft.css";

// helper function
const createState = (text) => {
  return EditorState.createWithContent(ContentState.createFromText(text));
};

const ControlledEditor = ({ htmlContent }) => {
  // define the local state, using the createState callback to create the initial value
  const [editorState, setEditorState] = useState(createState(htmlContent));

  // override the local state any time that the props change
  useEffect(() => {
    setEditorState(createState(htmlContent));
  }, [htmlContent]);

  return (
    <Editor
      editorState={editorState}
      onChange={setEditorState}
    />
  );
};

export default function App() {
  const [text, setText] = useState("Hello World");
  return (
    <div>
      <h2>Source Text</h2>
      <textarea value={text} onChange={(e) => setText(e.target.value)} />
      <h2>Editor</h2>
      <ControlledEditor htmlContent={text} />
    </div>
  );
}

Relaterte artikler