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

无法将@uiw/react-codemirror组件值同步到useState状态

@uiw/react-codemirror 无法同步值到 useState 的问题解析与修复

问题根源

你的代码里onChange回调用了useCallback但依赖数组为空,这导致了闭包陷阱:

  • 初始渲染时,useCallback创建的onChange函数捕获了当时的value初始状态值。
  • 后续每次调用setValue(val)更新状态后,组件会重新渲染,但因为useCallback的依赖没有包含value,所以onChange函数的引用不会更新,内部始终保留着对初始value的闭包引用。
  • 这就是为什么你在onChange里console.log("value:", value)永远显示初始值——并非状态没更新,而是回调里的value是旧的闭包值。

另外,如果CodeMirror组件依赖onChange的引用变化来同步内部状态,还可能导致受控模式下的异常,进一步让你误以为状态没同步。

修复方案

方案1:修正useCallback的依赖数组

把value加入useCallback的依赖列表,这样每次value更新时,onChange都会生成新的函数,捕获最新的状态:

import React from "react";
import CodeMirror from '@uiw/react-codemirror';
import { javascript } from '@codemirror/lang-javascript';

export default function Test() {
  const [value, setValue] = React.useState("console.log('hello world!');");
  const onChange = React.useCallback((val: string) => {
    setValue(val);
    console.log("val:", val);
    console.log("value:", value); // 下次触发时会显示最新状态
  }, [value]); // 加入value依赖
  return <CodeMirror value={value} height="200px" extensions={[javascript({ jsx: true })]} onChange={onChange} />;
}

方案2:移除useCallback(简单直接)

如果不需要缓存onChange函数的引用,直接去掉useCallback,让每次渲染都生成新的回调函数,自然能捕获最新的value:

import React from "react";
import CodeMirror from '@uiw/react-codemirror';
import { javascript } from '@codemirror/lang-javascript';

export default function Test() {
  const [value, setValue] = React.useState("console.log('hello world!');");
  const onChange = (val: string) => {
    setValue(val);
    console.log("val:", val);
  };
  return <CodeMirror value={value} height="200px" extensions={[javascript({ jsx: true })]} onChange={onChange} />;
}

针对Ctrl+S保存需求的优化

你不需要额外的codeText变量,直接使用value状态即可,逻辑更简洁:

import React from "react";
import CodeMirror from '@uiw/react-codemirror';
import { javascript } from '@codemirror/lang-javascript';

export default function Test() {
  const [value, setValue] = React.useState("console.log('hello world!');");
  
  const onChange = (val: string) => {
    setValue(val);
  };

  const handleSave = (ev: KeyboardEvent) => {
    if ((ev.ctrlKey || ev.metaKey) && ev.key === "s") {
      ev.preventDefault(); // 阻止浏览器默认保存行为
      console.log("Code:", value);
      // 调用API发送value到后端
    }
  };

  React.useEffect(() => {
    window.addEventListener("keydown", handleSave);
    return () => {
      window.removeEventListener("keydown", handleSave);
    };
  }, [value]); // 依赖value,确保保存时拿到最新状态

  return <CodeMirror value={value} height="200px" extensions={[javascript({ jsx: true })]} onChange={onChange} />;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 20:03:20