Как получить доступ к EditorState из декорированного компонента
Я начинаю работать с декораторами в draft-js и могу отображать свои компоненты, определенные в CompositeDecorator. Документированное поведение прекрасно работает.
Тем не менее, я пытаюсь выяснить, как я могу получить доступ к editorState из этих компонентов. ContentState - единственная полезная пропущенная информация, но, насколько я могу судить, я не могу разрешить editorState из contentState.
В первую очередь я пытаюсь редактировать или удалять, взаимодействуя с самим отображаемым компонентом. т.е. открытие диалога для изменения данных объекта. В onSave() dialogForm мне нужно было бы нажать новый editorState, но на данный момент он не находится в области видимости.
Есть ли способ получить доступ к editorState в рамках компонента декоратора или есть более разумное решение?
4 ответа
У меня нет четкого ответа (хотя это кажется хорошим вопросом!), Но я копался в примерах DraftJs, и пример TexEditor кажется, что он может быть полезен (если вы еще не обращались к нему). Он использует пользовательский блок, а затем передает реквизиты, которые обрабатывают обновление состояния редактора в ответ на изменения в компоненте блока.
Дайте мне знать, если вы найдете решение, я хотел бы знать, как вы подошли к нему в конце.
редактировать: я знаю, что вы ссылались на CompositeDecorator, но не смогли найти пример того, что вы описываете
Вы можете использовать фабричный метод при создании с вашим декоратором, т.е. вместо того, чтобы писать что-то вроде этого:
const compositeDecorator = new CompositeDecorator([
{
strategy,
component: DecoratedComponent,
}
])
class YourSuperEditor {
state = {
editorState: createWithContent(initialValue, compositeDecorator),
}
...
render = () => <Editor ... />
}
вы могли бы сделать это:
const compositeDecorator = getters => new CompositeDecorator([
{
strategy,
component: DecoratedComponent,
props: ...getters,
}
])
class YourSuperEditor {
state = {
editorState: createWithContent(
initialValue,
compositeDecorator({
getState: () => this.state,
getInitialValueFromProps: () => this.props.value,
})
),
}
...
render = () => <Editor ... />
}
Компоненты, украшенные PS, будут повторно визуализироваться только в том случае, если они были изменены, поэтому, если вы хотите повторно визуализировать их на основе состояния / свойств за пределами
EditorState
вам нужно будет запустить повторную визуализацию редактора, выполнив
setState(() => ({ editorState: newEditorState }))
- это довольно некрасиво, но мы мало что можем сделать, пока этот вопрос не будет решен.
Поэтому я просто столкнулся с этой проблемой и решил ее с помощью свойств декоратора.
{
strategy: handleSentenceStrategy,
component: SentenceComponent,
props: {
setSentenceFocus,
},
},
А также setSentenceFocus
это просто обработчик обратного вызова реакции (или статическая функция) на все, что создает редактор.
Основная проблема заключается в том, что всякий раз, когда реквизит изменяется, он повторно отображает компоненты (что правильно), поэтому, если вы передадите в редактор, укажите свои проблемы с производительностью (и визуальным рендерингом).
Я обошел это с помощью слегка хакерского подхода useRef.
const editorStateRef = useRef<EditorState>(editorState)
editorStateRef.current = editorState
const updateSentenceFocus = useCallback((focusedSentence: string) => {
const editorState = editorStateRef.current
const newEditorState = doSomething()
setEditorState(newEditorState)
}, [])
Главное здесь то, что сам обратный вызов никогда не изменяется и использует статическую ссылку. Это делает его более оптимальным.
Это может (скорее всего, вызовет) проблемы с порядком рендеринга, если вы делаете что-то нажатием клавиши, однако для моих сценариев использования это сработало нормально. Если вы делаете что-то большее, чем просто небольшую настройку, я бы рекомендовал использовать blockRendererFn, который дает вам максимальную гибкость (с более сложным компромиссом).
Обратное тоже работает (хотя лично я не рекомендую обновлять editorState в декораторах).
{
strategy: handleSentenceStrategy,
component: SentenceComponent,
props: {
getEditorState,
},
},
const getEditorState = useCallback((): EditorState => {
return editorStateRef.current
}, [])
Надеюсь, это имеет смысл!
Вы можете попробовать установить новый декоратор: https://draftjs.org/docs/advanced-topics-decorators/#setting-new-decorators
getDecorators = (props) => {
return compositeDecorators([
{
strategy: YourDecoratorStrategy,
component: YourDecoratorComponent,
props: {
// your props here
},
},
]);
};
const { editorState } = this.state;
const forcedState = EditorState.set(editorState, { decorator: this.getDecorators(this.props) });
this.setState({ editorState: forcedState });