使用Formik控制react-draft-wysiwyg编辑器时光标定位异常问题
我明白你遇到的这个光标跳转问题了,这其实是因为你每次渲染编辑器时都从HTML字符串重新创建了EditorState,导致编辑器丢失了光标位置、选区这类关键状态。咱们来一步步解决它:
问题根源分析
你当前的写法是在render函数里直接用setEditorState(this.props.field.value)生成EditorState传给组件,这意味着每次组件渲染(哪怕只是输入一个字符),都会生成一个全新的EditorState实例。react-draft-wysiwyg会把这个全新的状态当作完全新的内容,自然会把光标重置到内容开头,就出现了你看到的“从右往左输入”的异常效果。
解决方案:本地维护编辑器状态,仅在Formik值变化时同步
核心思路是让组件内部维护EditorState的本地状态,只在Formik的字段值真正变化时(比如初始化、表单重置),才从HTML字符串同步编辑器状态;而编辑器自身的输入变化,先更新本地状态,再同步HTML到Formik。这样既能保留Formik控制表单状态的优势,又能让编辑器正常维护光标、选区等交互状态。
修改后的组件代码
import React from 'react'; import { Editor } from 'react-draft-wysiwyg'; import { convertFromHTML, EditorState, ContentState } from 'draft-js'; import { stateToHTML } from 'draft-js-export-html'; class XXX extends React.Component { // 组件内部维护编辑器状态 state = { editorState: EditorState.createEmpty() }; componentDidMount() { // 初始化时从Formik的初始值加载编辑器状态 this.syncEditorStateFromFormik(this.props.field.value); } componentDidUpdate(prevProps) { // 仅当Formik的字段值发生变化时(比如表单重置),才同步编辑器状态 if (prevProps.field.value !== this.props.field.value) { this.syncEditorStateFromFormik(this.props.field.value); } } // 从Formik的HTML字符串同步到编辑器状态的工具方法 syncEditorStateFromFormik = (html) => { if (!html) { this.setState({ editorState: EditorState.createEmpty() }); return; } const blocksFromHTML = convertFromHTML(html); if (blocksFromHTML.contentBlocks) { const contentState = ContentState.createFromBlockArray( blocksFromHTML.contentBlocks, blocksFromHTML.entityMap ); this.setState({ editorState: EditorState.createWithContent(contentState) }); } else { this.setState({ editorState: EditorState.createEmpty() }); } }; onEditorStateChange = (editorState) => { // 先更新本地状态,保留光标、选区等交互状态 this.setState({ editorState }); // 再把编辑器内容转为HTML同步到Formik const contentState = editorState.getCurrentContent(); this.props.form.setFieldValue(this.props.field.name, stateToHTML(contentState)); }; render() { return ( <Editor editorState={this.state.editorState} onEditorStateChange={this.onEditorStateChange} // 这里保留你原来的其他编辑器配置项... /> ); } }
关键改动说明
- 本地状态维护:用组件自身的
state保存editorState,确保编辑器能持续跟踪光标、选区、撤销历史等状态。 - 按需同步Formik值:只在组件初始化或Formik字段值真正变化时,才从HTML字符串生成新的EditorState,避免不必要的状态重置。
- 先更新本地再同步Formik:编辑器内容变化时,先更新本地状态保证交互正常,再同步HTML到Formik,兼顾表单状态控制和编辑器体验。
这样修改后,你既能继续使用Formik的表单重置、验证等功能,编辑器的输入交互也会完全正常,不会再出现光标跳转到开头的问题。
内容的提问来源于stack exchange,提问作者Dune
相关产品推荐
相关产品推荐

