问题描述
我正在使用 Draft.js 创建富文本编辑器。
这是家长:
import React from 'react'
import RichTextEditor from './RichTextEditor'
import {useEffect,useState,useCallback} from "react"
import { EditorState,convertToRaw } from 'draft-js';
function AddPage() {
// MY STATE
const [editorState,setEditorState] = useState({editorState: EditorState.createEmpty()});
// MY CALLBACKS ATTEMPTS
function onChangeCallback(editorState) {
const contentState = editorState.getCurrentContent();
console.log(convertToRaw(contentState))
setEditorState({editorState});
}
// const onChangeCallback = useCallback((editorState) => {
// const contentState = editorState.getCurrentContent();
// console.log(convertToRaw(contentState))
// setEditorState({editorState});
// },[]);
// const onChangeCallback = ({editorState}) => {
// setEditorState({editorState});
// }
return (
<div>
<div className="app__body">
{editorState && <RichTextEditor editorState={editorState} onChangeCallback={onChangeCallback} /> }
</div>
</div>
)
}
export default AddPage
这是孩子(我尽可能短)
import React from 'react'
import { Editor,RichUtils,getDefaultKeyBinding } from 'draft-js';
import './RichTextEditor.css'
import 'draft-js/dist/Draft.css';
class RichTextEditor extends React.Component {
constructor(props) {
super(props);
this.state = this.props.editorState; // <----- PASSED STATE
this.onChange = this.props.onChangeCallback; //<----- PASSED CALLBACK
this.focus = () => this.refs.editor.focus();
this.handleKeyCommand = this._handleKeyCommand.bind(this);
this.mapKeyToEditorCommand = this._mapKeyToEditorCommand.bind(this);
this.toggleBlockType = this._toggleBlockType.bind(this);
this.toggleInlinestyle = this._toggleInlinestyle.bind(this);
}
_handleKeyCommand(command,editorState) {
const newState = RichUtils.handleKeyCommand(editorState,command);
if (newState) {
this.onChange(newState);
return true;
}
return false;
}
_mapKeyToEditorCommand(e) {
if (e.keyCode === 9 /* TAB */) {
const newEditorState = RichUtils.onTab(
e,this.state.editorState,4,/* maxDepth */
);
if (newEditorState !== this.state.editorState) {
this.onChange(newEditorState);
}
return;
}
return getDefaultKeyBinding(e);
}
_toggleBlockType(blockType) {
this.onChange(
RichUtils.toggleBlockType(
this.state.editorState,blockType
)
);
}
_toggleInlinestyle(inlinestyle) {
this.onChange(
RichUtils.toggleInlinestyle(
this.state.editorState,inlinestyle
)
);
}
render() {
let className = 'RichEditor-editor';
var contentState = this.state.editorState.getCurrentContent();
if (!contentState.hasText()) {
if (contentState.getBlockMap().first().getType() !== 'unstyled') {
className += ' RichEditor-hidePlaceholder';
}
}
return (
<div className="RichEditor-root">
<button onClick={this.onChange}>aaa</button>
<div className={className} onClick={this.focus}>
<Editor
editorState={this.state.editorState}
handleKeyCommand={this.handleKeyCommand}
keyBindingFn={this.mapKeyToEditorCommand}
onChange={this.onChange}
placeholder="Add your text here"
ref="editor"
spellCheck={true}
/>
</div>
</div>
);
}
}
export default RichTextEditor
我的问题是,当我单击一个键时,父回调中的 editorState
包含该字母,但是当我再次单击时,它看起来像 editorState
是一个带有一个新对象,即最后单击的字母.我从来没有在编辑器中看到任何东西。
editorState
是应该包含很多 blocks
的对象,每个 editorState
对应另一行文本。相反,这是控制台输出:
顺便说一句。我需要将 useState
存储在 Parent 中。当我将或多或少相同的 while (!in_file.eof()) {
in_file.get(c);
out_file.put(c);
}
代码移动到孩子时,它的行为方式应该如此。
解决方法
这似乎是一个隐藏在 Draft.js 中的初学者问题。我不了解基本钩子的功能。每次运行回调时,setEditorState
都会重新渲染组件。使用回调的记忆版本重新渲染它,并且只有在回调中的一个依赖项发生变化时才会改变它(见最后一行):
const onChangeCallback = useCallback((editorState) => {
const contentState = editorState.getCurrentContent();
console.log(convertToRaw(contentState))
setEditorState({editorState});
},[editorState]);
这对我有帮助
How to prevent re-rendering of components that have not changed?