创建新块+复制时不可变/ Draftjs错误“ block.getKey不是函数”

问题描述

当我从Immutable OrderedMap到Array创建新的contentState时,即使提供了密钥,我也会从Draftjs获得block.getKey is not a function ...

我在draftjs github上发现了一个线程,暗示这可能是一个错误,但这是从2016年开始的, 想知道是否有人有解决方案或解决方法,他们会建议...

此处是指向codeandBox复制的链接 https://codesandbox.io/s/blockgetkey-error-reproduction-h75mf?file=/src/index.js

import React from "react";
import ReactDOM from "react-dom";
import {
  List as ImmutableList,Repeat as ImmutableRepeat,Map as ImmutableMap,OrderedMap
} from "immutable";
import {
  Editor,EditorState,ContentBlock,ContentState,genKey,CharacterMetadata
} from "draft-js";
function MyEditor() {
  const [editorState,setEditorState] = React.useState(
    EditorState.createEmpty()
  );
  const editor = React.useRef(null);
  function focusEditor() {
    editor.current.focus();
  }
  React.useEffect(() => {
    focusEditor();
  },[]);
  return (
    <div onClick={focusEditor}>
      <Editor
        ref={editor}
        editorState={editorState}
        onChange={(editorState) => setEditorState(editorState)}
      />
      <button
        onClick={() => {
          // const newBlockMap = contentState.getBlockMap().set(newBlock.key,newBlock)
          const charData = CharacterMetadata.create();
          const text1 = "This was the test value";
          const contentState = editorState.getCurrentContent();
          const blockMap = contentState.getBlockMap();
          const newBlock = new ContentBlock({
            key: genKey(),type: "Img",text: text1,characterList: ImmutableList(
              ImmutableRepeat(charData,text1.length)
            ),data: ImmutableMap({ content: "foo bear" })
          });

          const insertBefore = OrderedMap().withMutations((r) => {
            blockMap.forEach((k,v) => {
              console.log("k  ",k);
              console.log("v  ",v);
              if (3 === k) {
                r.set(newBlock.key,newBlock);
              }
              r.set(k,v);
            });
          });

          let newcontentState = ContentState.createFromBlockArray(
            insertBefore.toArray()
          ).set("selectionAfter",contentState.getSelectionAfter());

          const newEditorState = EditorState.push(
            editorState,newcontentState,"insert-fragment"
          );

          setEditorState({
            ...editorState,editorState: newEditorState
          });
        }}
      >
        Add New Block
      </button>
    </div>
  );
}

function App() {
  return (
    <div>
      <h3>Test</h3>
      <MyEditor />
    </div>
  );
}
ReactDOM.render(<App />,document.getElementById("root"));

解决方法

我已经解决了这个问题,我将我的工作代码留在这里,希望它可以对某人有所帮助,

我当时正在使用Immutebale突变来尝试创建一个新的BlockMap,但是似乎并没有以draftjs可以理解的方式构造它。我没有使用循环,而是使用blockMap.toSeq().takeUntil((v)blockMap.toSeq().skipUntil((v)来拆分当前时钟状态,而是添加了新块并重新组装。

我还将contnetState.createFromArray()更改为contnetState.merge(),这更干净!因为它使您无需转换即可合并不变的Map对象。

                    e.preventDefault();
                    e.stopPropagation();

                    const getCurrentBlock = () => {
                        const selectionState = editorState.getSelection();
                        const contentState = editorState.getCurrentContent();
                        const block = contentState.getBlockForKey(selectionState.getStartKey());
                        return block;
                    };

                    let pivotBlockKey = getCurrentBlock().key
                    const contnetState = editorState.getCurrentContent();
                    const blockMap = contnetState.getBlockMap();
                    const block = blockMap.get(pivotBlockKey);
                    const blocksBefore = blockMap.toSeq().takeUntil((v) => (v === block));
                    const blocksAfter = blockMap.toSeq().skipUntil((v) => (v === block)).rest();

                    const charData = CharacterMetadata.create()
                    const text1 = "This was the test value"
                    const newBlockKey = genKey()
                    const newBlock = new ContentBlock({
                        key: newBlockKey,type: "header-one",text: text1,characterList: ImmutableList(ImmutableRepeat(charData,text1.length)),data: ImmutableMap({ content: "foo bear" })
                    })

                    const newBlockMap = blocksBefore.concat(
                        [[pivotBlockKey,block],[newBlockKey,newBlock]],blocksAfter
                    ).toOrderedMap();

                    let newContnetState = contnetState.merge({
                        blockMap: newBlockMap,selectionBefore: contentState.getSelectionBefore()
                    })
                    
                    const newEditorState = EditorState.push(
                        editorState,newContnetState,'insert-fragment'
                    );
                    
                    setState({ 
                        ...state,editorState: newEditorState,});
,

当我自己安装 immutable 并更新到 4.0 时,这种情况开始发生

当我删除它并让draft-js安装版本“3.7.6”时工作