#javascript #reactjs #immutable.js #draftjs
#javascript #reactjs #immutable.js #draftjs
Вопрос:
Когда я создаю новое состояние содержимого из неизменяемой упорядоченной карты в массив, я получаю block.getKey is not a function
от Draftjs, даже если ключ предоставлен…
Я нашел поток на github draftjs, предполагающий, что это может быть ошибкой, однако это с 2016 года, интересно, есть ли у кого-нибудь решение или обходной путь, который они могли бы предложить…
Вот ссылка на воспроизведение codesandbox 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"));
Ответ №1:
Это начало происходить, когда я установил immutable сам по себе, и он обновился до 4.0
Сработало, когда я удалил его и позволил draft-js установить версию «3.7.6»
Ответ №2:
Я решил проблему, я оставлю свой рабочий код здесь в надежде, что он может кому-то помочь,
Я использовал неизменяемые мутации, чтобы попытаться создать новую карту блоков, однако, похоже, она не создается так, как может понять draftjs. вместо использования цикла, который я использовал blockMap.toSeq().takeUntil((v)
amp; blockMap.toSeq().skipUntil((v)
для разделения текущего состояния синхронизации, добавьте новый блок и соберите его заново.
Я также меняю contnetState.createFromArray()
contnetState.merge()
, какой способ чище! поскольку это позволяет объединить неизменяемый объект карты без преобразования.
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,
});