React Hook实现支持prevData与内置深比较的setData纯函数方案
解决方案
问题原因
你原有改造逻辑存在三个核心问题:
- 没有处理
setData入参为更新函数的场景,直接将函数和当前状态值做深比较,逻辑完全不成立 - 自定义
setData内部误调用了自身,会触发递归死循环,应该调用原始的_setData - 外层直接拿闭包捕获的
data做比较,无法拿到最新的状态值,会出现比较逻辑错误
正确实现
直接修改CurrentUserProvider的自定义setData逻辑即可:
import { useState } from 'react'; import { isEqual } from 'lodash'; export function CurrentUserProvider({ children }) { const [data, _setData] = useState(undefined); const setData = (update) => { _setData(prevData => { // 兼容两种入参:直接传值 / 传函数获取prevData计算新值 const newData = typeof update === 'function' ? update(prevData) : update; // 深比较新老值一致则返回旧值,React会自动跳过重渲染 if (isEqual(newData, prevData)) return prevData; // 不一致返回新值触发更新 return newData; }) } return ( <CurrentUserContext.Provider value={{ data, setData }} > {children} </CurrentUserContext.Provider> ); }
方案说明
- 完全兼容原生
useState更新语法,原有调用setData传入更新函数的写法不需要做任何修改 - 利用React内置的状态更新逻辑:如果状态setter返回的值和旧值引用完全一致,React会跳过后续的重渲染,不需要额外在外层做条件判断
- 深比较逻辑放在
_setData的回调函数中执行,获取的prevData永远是最新的状态值,不会出现闭包捕获旧值的问题
内容的提问来源于stack exchange,提问作者Raul
相关产品推荐
相关产品推荐

