在DraftJS中执行异步装饰?

问题描述 投票:2回答:1

我正在尝试在WYSIWYG编辑器中执行实时命名实体识别突出显示,这需要我在每次击键之间向我的后端发出请求。

在ProseMirror上花了大约一个星期后,我放弃了它并决定尝试DraftJS。我搜索了存储库和文档,但没有找到使用Decorations的任何异步示例。 (Entities有一些例子,但它们似乎不适合我的问题。)

这是我要解决的问题的stripped down Codepen

归结为我想要做这样的事情:

const handleStrategy = (contentBlock, callback, contentState) => {
  const text = contentBlock.getText();
  let matchArr, start;
  while ((matchArr = properNouns.exec(text)) !== null) {
    start = matchArr.index;
    setTimeout(() => {
//    THROWS ERROR: Cannot read property '0' of null
      callback(start, start + matchArr[0].length);
    }, 200) // to simulate API request
  }
};

我希望它在超时解决时异步调用回调,但是matchArr是空的,这只会让我感到困惑。

任何帮助表示赞赏!

reactjs asynchronous draftjs
1个回答
1
投票

好的,一个可能的解决方案,一个例子,简单的版本(可能不是100%可靠):

  1. 写一个函数拿编辑器的字符串,发送到服务器,并解析从服务器获取的数据,你需要弄清楚发送整个编辑器字符串或只是一个字
getServerResult = data => new Promise((resolve, reject) => {
      ...

      fetch(link, {
        method: 'POST',
        headers: {
          ...
        },
        // figure what to send here
        body: this.state.editorState.getCurrentContent().getPlainText(),
      })
        .then(res => resolve(res))
        .catch(reject);
    });
  1. 确定何时调用getServerResult函数(即何时将字符串发送到服务器并获取实体数据),从我的评论中理解,当用户点击空格键时,将该字发送到服务器,这可以通过draftjs Key Bindings或者做出反应SyntheticEvent。如果用户连续多次点击空格键,您将需要处理案例。
function myKeyBindingFn(e: SyntheticKeyboardEvent): string {
  if (e.keyCode === 32) {
    return 'send-server';
  }
  return getDefaultKeyBinding(e);
}

async handleKeyCommand(command: string): DraftHandleValue {
  if (command === 'send-server') {
    // you need to manually add a space char to the editorState
    // and get result from server

    ...

    // entity data get from server
    const result = await getServerResult()

    return 'handled';
  }
  return 'not-handled';
}
  1. 使用ContentState.createEntity()将实体数据从服务器添加到特定单词
  async handleKeyCommand(command: string): DraftHandleValue {
    if (command === 'send-server') {
      // you need to manually add a space char to the editorState
      // and get result from server

      ...

      // entity data get from server
      const result = await getServerResult()

      const newContentState = ContentState.createEntity(
        type: 'string',
        mutability: ...
        data: result
      )

      const entityKey = contentStateWithEntity.getLastCreatedEntityKey();

      // you need to figure out the selectionState, selectionState mean add 
      // the entity data to where

      const contentStateWithEntity = Modifier.applyEntity(
         newContentState,
         selectionState,
         entityKey
      );

      // create a new EditorState and use this.setState()
      const newEditorState = EditorState.push(
        ...
        contentState: contentStateWithEntity
      )

      this.setState({
        editorState: newEditorState
      })

      return 'handled';
    }
    return 'not-handled';
  }
  1. 创建不同的装饰器查找具有特定实体数据的单词,并返回不同的样式或您需要返回的任何内容
...
const compositeDecorator = new CompositeDecorator([
  strategy: findSubjStrategy,
  component: HandleSubjSpan,
])
function findSubjStrategy(contentBlock, callback, contentState) {
  // search whole editor content find words with subj entity data
  // if the word's entity data === 'Subj'
  // pass the start index & end index of the word to callback

  ...
  if(...) {
   ... 
   callback(startIndex, endIndex);
  }
}

// this function handle what if findSubjStrategy() find any word with subj
// entity data
const HandleSubjSpan = (props) => {

  // if the word with subj entity data, it font color become red
  return <span {...props} style={{ color: 'red' }}>{props.children}</span>;
};

© www.soinside.com 2019 - 2024. All rights reserved.