我在 draft-js 和 draft-js-plugins-editor
中遇到此错误奇怪的行为:只有当我在编写后重新聚焦到编辑器的第一行时,当尝试设置例如时,才会发生这种情况。第一行的标题到 H1 它改变了之前聚焦的行
错误:
Uncaught TypeError: Cannot read property 'getIn' of undefined
完全错误:
Uncaught TypeError: Cannot read property 'getIn' of undefined
at getUpdatedSelectionState (getUpdatedSelectionState.js?a009439:34)
at getDraftEditorSelectionWithNodes (getDraftEditorSelectionWithNodes.js?a009439:37)
at getDraftEditorSelection (getDraftEditorSelection.js?a7f8e9b:35)
at editOnSelect (editOnSelect.js?a7f8e9b:32)
at DraftEditor.react.js?f8ee1ff:148
at HTMLUnknownElement.callCallback (react-dom.development.js?5f39724:542)
at Object.invokeGuardedCallbackDev (react-dom.development.js?5f39724:581)
at Object.invokeGuardedCallback (react-dom.development.js?5f39724:438)
at Object.invokeGuardedCallbackAndCatchFirstError (react-dom.development.js?5f39724:452)
at executeDispatch (react-dom.development.js?5f39724:836)
这是我的组件:
/* eslint-disable react/no-multi-comp */
import React, {Component} from 'react';
import sv from '../../config/styleVariables'
import Editor from 'draft-js-plugins-editor';
import {EditorState,convertToRaw} from 'draft-js'
import createToolbarPlugin from 'draft-js-static-toolbar-plugin';
import {
ItalicButton,
BoldButton,
UnderlineButton,
HeadlineOneButton,
HeadlineTwoButton,
HeadlineThreeButton,
UnorderedListButton,
OrderedListButton,
BlockquoteButton,
} from 'draft-js-buttons'
export default class TextArea extends Component {
constructor(props){
super(props)
this.state = {
editorState: EditorState.createEmpty(),
}
const toolbarPlugin = createToolbarPlugin({
structure: [
BoldButton,
ItalicButton,
UnderlineButton,
HeadlineOneButton, ,
HeadlineTwoButton,
HeadlineThreeButton,
UnorderedListButton,
OrderedListButton,
// BlockquoteButton,
]
})
const { Toolbar } = toolbarPlugin;
this.Toolbar = Toolbar
this.plugins = [toolbarPlugin];
}
onChange(editorState){
this.setState({
editorState,
})
this.props.update(JSON.stringify(convertToRaw(editorState.getCurrentContent())))
}
focus(){
this.editor.focus();
}
render() {
const {Toolbar, plugins} = this
const {name} = this.props
return (
<div className="TextArea">
{/*language=SCSS*/}
<style jsx global>{`
.TextArea .headlineButtonWrapper {
display: inline-block;
}
.TextArea {
background: ${sv.white};
}
.TextArea > div>div:first-child {
display: flex;
padding: 0 0 .25em 0;
border-bottom: 1px solid ${sv.border};
}
.TextArea > div>div:first-child>div button{
background: transparent;
cursor: pointer;
border: none;
display: flex;
align-items: center;
justify-content: center;
width: 3em;
height: 2.5em;
font-size: .8em;
margin-right: .2em;
}
.TextArea > div>div:first-child>div button:hover {
background: ${sv.extraLight};
color: ${sv.primary};
}
.TextArea .DraftEditor-root {
padding: 0 .5em;
cursor: text;
}
.TextArea .headlineButton {
background: #fbfbfb;
color: #888;
font-size: 18px;
border: 0;
padding-top: 5px;
vertical-align: bottom;
height: 34px;
width: 36px;
}
.TextArea .headlineButton:hover,
.TextArea .headlineButton:focus {
background: #f3f3f3;
}
`}
</style>
<div onClick={this.focus.bind(this)}>
<Toolbar key={name} />
<Editor
editorState={this.state.editorState}
onChange={this.onChange.bind(this)}
plugins={plugins}
ref={(element) => {
this.editor = element
}}
/>
</div>
</div>
);
}
}
我的组件如下所示:
我也遇到同样的问题。看起来是因为在
editorState.getBlockTree(anchorBlockKey).getIn(...)
中调用 getUpdatedSelectionState.js
,每当块类型为 editorState.getBlockTree(anchorBlockKey)
时,undefined
就是 unstyled
。
我不知道如何解决它,所以请像这样解决解决方案:
const headerOne = '<h1>Title</h1>';
const blocksFromHTML = convertFromHTML(headerOne);
const state = ContentState.createFromBlockArray(
blocksFromHTML.contentBlocks,
blocksFromHTML.entityMap
);
this.state = {
editorState: EditorState.createWithContent(state)
}
但是还有一个问题,当你按回车换行时也会是
H1
。
这里他们说组件在服务器和客户端之间呈现不同,这导致了问题:https://github.com/facebookarchive/draft-js/issues/2332
这个解决方案似乎对我有用。它强制组件仅在客户端上呈现。这对我来说很有效,因为我不需要文本编辑器中的任何 SEO。
"use client";
import { useState, useEffect } from "react";
import { Editor, EditorState } from "draft-js";
import "draft-js/dist/Draft.css";
function Composer() {
const [editorState, setEditorState] = useState<EditorState>();
useEffect(() => {
setEditorState(EditorState.createEmpty());
}, []);
return (
<div>
{editorState && (
<Editor editorState={editorState} onChange={setEditorState} />
)}
</div>
);
}
export default Composer;