Выполнять асинхронные декорации в DraftJS? - PullRequest
0 голосов
/ 14 февраля 2019

Я пытаюсь в режиме WYSIWYG выделять распознавание именованных объектов в режиме реального времени, что требует от меня выполнения запроса к моему бэкэнду между каждым нажатием клавиши.

Потратив около недели наProseMirror Я отказался от него и решил попробовать DraftJS.Я искал репозиторий и документы и не нашел асинхронных примеров, использующих Decorations.(Есть некоторые примеры с Entities, но они кажутся мне неподходящими для моей проблемы.)

Вот урезанный 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 пусто, что просто смущает меня.

Любая помощь приветствуется!

1 Ответ

0 голосов
/ 15 февраля 2019

хорошо, одно возможное решение, пример, простая версия (не может быть на 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);
    });
определить, когда вызывать функцию getServerResult (т. Е. Когда отправлять строку на сервер и получать данные сущности), из того, что я понимаю из вашего комментария, когда пользователь нажимает клавишу пробела, отправляет слово перед сервером, это можно сделать с помощью draftjs Связывание клавиш или реакция 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';
}
добавить данные сущности, полученные с сервера, к определенному слову, используя 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';
  }
создавать разные декораторы, находить слова с конкретными данными сущностей и возвращать другой стиль или все, что вам нужно, чтобы вернуть
...
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>;
};

...