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

React中useCallback回调访问Hooks状态为undefined如何解决?

问题解答

可以在useCallback包裹的回调中访问Hooks定义的状态变量吗?

完全可以。你现在拿到undefined是两个问题叠加导致的:

  • 首先是事件名拼写错误:你给输入框绑定的是onChnage,React输入框的变更事件正确写法是onChange,字母顺序写反会导致输入时的setState逻辑根本不触发,状态从一开始就没被正确赋值。
  • 其次是踩了useCallback的闭包陷阱:你给useCallback传的依赖数组是空的,意味着这个回调只会在组件第一次挂载的时候生成一次,生成时捕获的是当时上下文里的test1、test2值,后续哪怕状态更新了,这个回调也不会重新创建,永远拿不到最新值。要是你写useState的时候没显式传空字符串当初始值,初始值默认就是undefined,刚好就会出现你现在打印结果全是undefined的情况。

修复步骤

先改对事件绑定

把输入框上拼错的事件名改成正确的onChange,保证输入时能正常更新状态:

<input placeholder="输入test1" onChange={(e)=>setTest1(e.target.value)} />
<input placeholder="输入test2" onChange={(e)=>setTest2(e.target.value)} />

再修复useCallback的取值问题,三种方案选一个即可

  1. 按官方规范补全依赖数组(优先推荐)
    把回调里用到的所有外部状态、函数都加到useCallback的依赖数组里,只要依赖项变化,回调就会重新生成,自然能拿到最新的状态值:
    const onHandleSubmit = useCallback( (event) => {
        event.preventDefault(); // 一定要加,阻止浏览器默认表单刷新行为
        console.log(test1)
        console.log(test2)
        const data = {
           test1,
           test2
        }
        dispatch({type: 'send/data', data});
    },[test1, test2, dispatch]); // 用到的test1、test2、dispatch都加入依赖
    
  2. 简单场景直接去掉useCallback
    要是你这个提交函数只在当前组件里用,没有传给memo包裹的优化子组件当props,完全没必要套useCallback,直接写普通函数就行,每次组件渲染都会生成新的函数,闭包捕获的永远是当次渲染的最新状态:
    const onHandleSubmit = (event) => {
        event.preventDefault();
        console.log(test1)
        console.log(test2)
        const data = {
           test1,
           test2
        }
        dispatch({type: 'send/data', data});
    };
    
  3. 特殊场景用useRef存最新值(不推荐常规使用)
    如果你确实不想让回调函数因为状态变化重新生成,可以用useRef同步存一份最新的状态,回调里读ref的current属性就能拿到最新值,绕开闭包限制:
    const [test1, setTest1] = useState('')
    const [test2, setTest2] = useState('')
    // 创建ref存储状态
    const test1Ref = useRef(test1)
    const test2Ref = useRef(test2)
    // 每次状态更新同步给ref
    useEffect(() => {
        test1Ref.current = test1
        test2Ref.current = test2
    }, [test1, test2])
    
    const onHandleSubmit = useCallback( (event) => {
        event.preventDefault();
        // 从ref上取最新值
        const data = {
           test1: test1Ref.current,
           test2: test2Ref.current
        }
        dispatch({type: 'send/data', data});
    },[dispatch]);
    

踩坑提示:不要为了应付eslint的依赖告警随便把依赖数组置空,90%的Hooks闭包问题都是这么来的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 08:48:30