You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将MUIRichTextEditor用作Redux Form字段时光标跳至开头的问题

解决MUIRichTextEditor结合Redux Form时的重渲染与光标位置问题

核心问题分析

你当前的实现每次按键都会触发Redux Store更新,导致组件重渲染;而通过defaultValue传入RawDraftContentState的方式会重置编辑器状态,无法保留光标位置。要解决这个问题,需要将编辑器改为受控模式,由组件自身维护EditorState,仅在外部值(Redux Store中的值)变化时才同步更新编辑器状态。

修改后的实现代码

import { EditorState, ContentState, convertFromHTML } from 'draft-js';
import { stateToHTML } from 'draft-js-export-html';
import { MuiThemeProvider } from '@material-ui/core/styles';
import MUIRichTextEditor from 'mui-rte';

class MYRichText extends Component {
    lastRichTextHTMLValue = null;

    constructor(props) {
        super(props);
        // 初始化编辑器状态
        const htmlValue = props.input.value || "<p><br></p>";
        const convertedValue = convertFromHTML(htmlValue);
        const contentState = ContentState.createFromBlockArray(
            convertedValue.contentBlocks,
            convertedValue.entityMap
        );
        this.state = {
            editorState: EditorState.createWithContent(contentState)
        };
    }

    componentDidUpdate(prevProps) {
        // 仅当Redux中的值发生变化时,更新编辑器状态
        if (prevProps.input.value !== this.props.input.value) {
            const htmlValue = this.props.input.value || "<p><br></p>";
            const convertedValue = convertFromHTML(htmlValue);
            const contentState = ContentState.createFromBlockArray(
                convertedValue.contentBlocks,
                convertedValue.entityMap
            );
            this.setState({
                editorState: EditorState.createWithContent(contentState)
            });
        }
    }

    onRichTextChange = (editorState) => {
        const currentContent = editorState.getCurrentContent();
        const richTextAsHTML = stateToHTML(currentContent);
        // 避免无意义的Redux更新,仅在内容真正变化时同步
        if (richTextAsHTML !== this.lastRichTextHTMLValue) {
            this.lastRichTextHTMLValue = richTextAsHTML;
            this.props.input.onChange(richTextAsHTML);
        }
        // 更新组件内部的编辑器状态,保留光标位置
        this.setState({ editorState });
    };

    render() {
        return (
            <MuiThemeProvider theme={richEditorTheme}>
                <MUIRichTextEditor
                    controls={["title", "bold", "italic", "underline", "strikethrough"]}
                    label="Description"
                    editorState={this.state.editorState}
                    onChange={this.onRichTextChange}
                />
            </MuiThemeProvider>
        );
    }
}

关键改动说明

  • 组件内部维护EditorState:将编辑器状态存入组件自身的state,不再依赖defaultValue每次重渲染重置状态,光标位置会被自动保留。
  • 监听外部值变化:通过componentDidUpdate对比前后props.input.value,仅当Redux中的值真正改变时,才重新生成EditorState并更新编辑器。
  • 受控模式绑定:给MUIRichTextEditor传入editorState属性替代defaultValue,并在onChange中同步更新内部状态与Redux Store。
  • 优化Redux更新逻辑:仅当内容的HTML格式真正变化时,才调用input.onChange同步到Redux,避免不必要的Store更新与组件重渲染。

内容的提问来源于stack exchange,提问作者Yoram Gronich

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 13:22:49