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:
ContentStatekan opprettes fra tekst med den statiske metodenContentState.createFromText.EditorStatekan opprettes fraContentStatemed den statiske metodenEditorState.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>
);
}
