微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Draft.js:对类组件的回调导致父级中的新对象而不是修改

如何解决Draft.js:对类组件的回调导致父级中的新对象而不是修改

我正在使用 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 对应另一行文本。相反,这是控制台输出

The result

顺便说一句。我需要将 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?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。