我如何使用其余 API 中的内容创建 Draft.js 编辑器?

How do I create a Draft.js editor with content from a rest API?

我正在尝试使用 Draft.js 创建一个文本编辑器,我希望它以一些内容启动。内容来自我也创建的休息 API,但我在让它工作时遇到了一些麻烦。编辑器本身工作正常,但当我尝试用内容启动它时它不再工作。

我尝试实现此目的的方法是使用 createWithContent() 创建 editorState,但出现错误:

TypeError: Cannot read property 'getSelection' of undefined.

我认为可能是使用 'getSelection' 函数的函数在 editorState 创建之前试图访问它,但是,我不确定如何修复它。

这是我的编辑Class:

import React, {useState, Component} from 'react';
import {Editor, EditorState, RichUtils, ContentState, convertFromHTML} from 'draft-js';
import axios from "axios";

class MyEditor extends Component {
    constructor(props) {
        super(props);
        this.state = {}
    }

    componentDidMount() {
        axios.get(`http://localhost:8080/BackendWiki/api/brands/Rolex`)
            .then(res => {
                    const brand = res.data;
                    console.log(res.data)
                    if (brand) {
                        const blocksFromHTML = convertFromHTML(brand.description);
                        const state = ContentState.createFromBlockArray(
                            blocksFromHTML.contentBlocks,
                            blocksFromHTML.entityMap,
                        );
                        this.setState({editorState: EditorState.createWithContent(state)})
                    } else {
                        this.setState({editorState: EditorState.createEmpty()});

                    }
                }
            )
    }


    handleKeyCommand(command, editorState) {
        const newState = RichUtils.handleKeyCommand(editorState, command);

        if (newState) {
            this.onChange(newState);
            return 'handled';
        }

        return 'not-handled';
    }

    _onBoldClick(e) {
        e.preventDefault();
        this.onChange(RichUtils.toggleInlineStyle(this.state.editorState, 'BOLD'));
    }

    _isActive(style) {
        const currentFocus = this.state.editorState.getSelection().getFocusKey()
        //currentStyle is a map of currently applied style to selected text
        const currentStyle = this.state.editorState.getCurrentInlineStyle(currentFocus);
        //check if current style is among the style map.
        return currentStyle.has(style);
    };

    render() {
        return (
            <div>
                <button
                    className={this._isActive("BOLD") ? "bg-blue-700 text-white font-bold py-2 px-4 rounded" : 'bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded'}
                    onMouseDown={this._onBoldClick.bind(this)}
                    isActive={"BOLD"}>Bold
                </button>
                <Editor
                    editorState={this.state.editorState}
                    handleKeyCommand={this.handleKeyCommand}
                    onChange={this.onChange}
                />
            </div>
        );
    }
}

export default MyEditor;

这是错误:

Uncaught TypeError: Cannot read property 'getSelection' of undefined
    at MyEditor._isActive (editor.js:52)
    at MyEditor.render (editor.js:63)
    at finishClassComponent (react-dom.development.js:17160)
    at updateClassComponent (react-dom.development.js:17110)
    at beginWork (react-dom.development.js:18620)
    at HTMLUnknownElement.callCallback (react-dom.development.js:188)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:237)
    at invokeGuardedCallback (react-dom.development.js:292)
    at beginWork (react-dom.development.js:23203)
    at performUnitOfWork (react-dom.development.js:22154)
    at workLoopSync (react-dom.development.js:22130)
    at performSyncWorkOnRoot (react-dom.development.js:21756)
    at scheduleUpdateOnFiber (react-dom.development.js:21188)
    at updateContainer (react-dom.development.js:24373)
    at react-dom.development.js:24758
    at unbatchedUpdates (react-dom.development.js:21903)
    at legacyRenderSubtreeIntoContainer (react-dom.development.js:24757)
    at Object.render (react-dom.development.js:24840)
    at Module../src/index.js (index.js:12)
    at __webpack_require__ (bootstrap:784)
    at fn (bootstrap:150)
    at Object.1 (tailwind.output.css?5033:45)
    at __webpack_require__ (bootstrap:784)
    at checkDeferredModules (bootstrap:45)
    at Array.webpackJsonpCallback [as push] (bootstrap:32)
    at main.chunk.js:1
_isActive @ editor.js:52
render @ editor.js:63
finishClassComponent @ react-dom.development.js:17160
updateClassComponent @ react-dom.development.js:17110
beginWork @ react-dom.development.js:18620
callCallback @ react-dom.development.js:188
invokeGuardedCallbackDev @ react-dom.development.js:237
invokeGuardedCallback @ react-dom.development.js:292
beginWork @ react-dom.development.js:23203
performUnitOfWork @ react-dom.development.js:22154
workLoopSync @ react-dom.development.js:22130
performSyncWorkOnRoot @ react-dom.development.js:21756
scheduleUpdateOnFiber @ react-dom.development.js:21188
updateContainer @ react-dom.development.js:24373
(anonymous) @ react-dom.development.js:24758
unbatchedUpdates @ react-dom.development.js:21903
legacyRenderSubtreeIntoContainer @ react-dom.development.js:24757
render @ react-dom.development.js:24840
./src/index.js @ index.js:12
__webpack_require__ @ bootstrap:784
fn @ bootstrap:150
1 @ tailwind.output.css?5033:45
__webpack_require__ @ bootstrap:784
checkDeferredModules @ bootstrap:45
webpackJsonpCallback @ bootstrap:32
(anonymous) @ main.chunk.js:1
index.js:1 The above error occurred in the <MyEditor> component:
    in MyEditor (at Brand.js:41)
    in div (at Brand.js:36)
    in Brand (created by Context.Consumer)
    in Route (at App.js:16)
    in div (at App.js:13)
    in App (at src/index.js:14)
    in Router (created by BrowserRouter)
    in BrowserRouter (at src/index.js:13)

Consider adding an error boundary to your tree to customize error handling behavior.
console.<computed> @ index.js:1
logCapturedError @ react-dom.development.js:19527
logError @ react-dom.development.js:19564
update.callback @ react-dom.development.js:20708
callCallback @ react-dom.development.js:12490
commitUpdateQueue @ react-dom.development.js:12511
commitLifeCycles @ react-dom.development.js:19883
commitLayoutEffects @ react-dom.development.js:22803
callCallback @ react-dom.development.js:188
invokeGuardedCallbackDev @ react-dom.development.js:237
invokeGuardedCallback @ react-dom.development.js:292
commitRootImpl @ react-dom.development.js:22541
unstable_runWithPriority @ scheduler.development.js:653
runWithPriority @ react-dom.development.js:11039
commitRoot @ react-dom.development.js:22381
finishSyncRender @ react-dom.development.js:21807
performSyncWorkOnRoot @ react-dom.development.js:21793
scheduleUpdateOnFiber @ react-dom.development.js:21188
updateContainer @ react-dom.development.js:24373
(anonymous) @ react-dom.development.js:24758
unbatchedUpdates @ react-dom.development.js:21903
legacyRenderSubtreeIntoContainer @ react-dom.development.js:24757
render @ react-dom.development.js:24840
./src/index.js @ index.js:12
__webpack_require__ @ bootstrap:784
fn @ bootstrap:150
1 @ tailwind.output.css?5033:45
__webpack_require__ @ bootstrap:784
checkDeferredModules @ bootstrap:45
webpackJsonpCallback @ bootstrap:32
(anonymous) @ main.chunk.js:1
react-dom.development.js:22665 Uncaught TypeError: Cannot read property 'getSelection' of undefined
    at MyEditor._isActive (editor.js:52)
    at MyEditor.render (editor.js:63)
    at finishClassComponent (react-dom.development.js:17160)
    at updateClassComponent (react-dom.development.js:17110)
    at beginWork (react-dom.development.js:18620)
    at HTMLUnknownElement.callCallback (react-dom.development.js:188)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:237)
    at invokeGuardedCallback (react-dom.development.js:292)
    at beginWork (react-dom.development.js:23203)
    at performUnitOfWork (react-dom.development.js:22154)
    at workLoopSync (react-dom.development.js:22130)
    at performSyncWorkOnRoot (react-dom.development.js:21756)
    at scheduleUpdateOnFiber (react-dom.development.js:21188)
    at updateContainer (react-dom.development.js:24373)
    at react-dom.development.js:24758
    at unbatchedUpdates (react-dom.development.js:21903)
    at legacyRenderSubtreeIntoContainer (react-dom.development.js:24757)
    at Object.render (react-dom.development.js:24840)
    at Module../src/index.js (index.js:12)
    at __webpack_require__ (bootstrap:784)
    at fn (bootstrap:150)
    at Object.1 (tailwind.output.css?5033:45)
    at __webpack_require__ (bootstrap:784)
    at checkDeferredModules (bootstrap:45)
    at Array.webpackJsonpCallback [as push] (bootstrap:32)
    at main.chunk.js:1

我是不是遗漏了什么或者有更好的方法来实现这个目标吗? 谢谢!

这背后的原因是基于你的堆栈跟踪,调用了 _isActive() 函数,一旦 this.state.editorState 仍然是 undefined,就会调用 this.state.editorState.getSelection()

我会在 this.state.editorState.

的渲染中添加 nullundefined 检查
render() {
   return this.state.editorState ?
       <div>
           <button className={this._isActive("BOLD") ? "bg-blue-700 text-white font-bold py-2 px-4 rounded" : 'bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded'}
                   onMouseDown={this._onBoldClick.bind(this)}
                   isActive={"BOLD"}>Bold
           </button>
           <Editor editorState={this.state.editorState}
                   handleKeyCommand={this.handleKeyCommand}
                   onChange={this.onChange} />
       </div> : null
}

此外,您可以在三元运算符中添加某种加载组件而不是 null,这看起来更好,直到 API 调用仍在进行中,如:

this.state.editorState ?
     <div> {/* your editor */} </div> :
     <span>Loading...</span>