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

React自定义usePrevious钩子获取Context历史值始终返回最新值问题求助

问题排查与修复方案

核心错误点

  • 自定义Hook usePrevious 定义在组件内部:函数组件每次重渲染都会重新执行整个函数体,内部定义的Hook会被反复初始化,对应的ref引用无法跨渲染周期存储历史值
  • 自定义Hook usePrevious 定义在组件内部:函数组件每次重渲染都会重新执行整个函数体,内部定义的Hook会被反复初始化,对应的ref引用无法跨渲染周期存储历史值
  • Context更新逻辑错误:代码中所有的setMyPref调用都直接传入了原有myPref对象,没有生成新的对象引用,React基于引用比对判断状态是否变化,此时既不会触发Context订阅组件重渲染,也无法区分新旧值
  • (非核心但需要优化点)usePrevious内部的useEffect没有指定依赖数组,存在性能隐患

修复步骤

  1. 将usePrevious移到组件外部定义,明确指定依赖项:
import React, { useRef, useEffect, useContext } from 'react'

// 自定义Hook必须定义在组件外部
function usePrevious(value) {
    const ref = useRef();
    // 仅当value变化时更新ref存储的值
    useEffect(() => {
        ref.current = value;
    }, [value]);
    // 渲染阶段返回的是更新前的ref值,即上一次传入的value
    return ref.current;
}

function MyHeaderComponent(props) {
    // 原有组件逻辑
}
  1. 修正Context更新逻辑,所有状态更新必须传入新的对象引用:
// 错误写法,引用不变不会触发更新
setMyPref(myPref); 

// 正确写法,基于原有值生成新对象
setMyPref(prevPref => {
    return {
        ...prevPref,
        // 这里写你要修改的属性,比如修改preferences
        preferences: {
            ...prevPref.preferences,
            // 要更新的配置项示例
            theme: 'dark'
        }
    }
})
  1. 调整组件内useEffect逻辑,补充依赖项和边界判断:
const [myPref, setMyPref] = React.useContext(MyContext);
const prevPreferences = usePrevious(myPref.preferences);

useEffect(() => {
    // 跳过首次渲染的undefined判断,可根据业务需求调整
    if (prevPreferences && prevPreferences !== myPref.preferences) {
        console.log("prevPreferences : ", prevPreferences);
        // 执行你的业务逻辑
        myInfo();
    }
}, [myPref, prevPreferences]);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 11:18:00