本文详解为何简单闭包无法复现 usestate 行为,并提供符合 react 更新机制的自定义 usecustomstate 实现方案,包含 useref + useeffect 的正确范式、可变状态同步原理及关键注意事项。
React 的 useState 不仅管理值,更核心的是触发组件重渲染。你原始代码的问题在于:value 是一个局部变量,setValue 仅修改了该变量,但未通知 React 触发更新——因此 UI 永远停留在初始值 3。
要真正模拟 useState,必须满足两个条件:
✅ 正确实现方式是借助 useRef 存储当前值 + useState(或 useReducer)驱动更新:
import React, { useState, useRef, useCallback } from 'react';
const useCustomState = (initialState) => {
// 使用 useRef 持久化最新值(不触发渲染)
const valueRef = useRef(initialState);
// 使用 useState 控制渲染(真正的“驱动器”)
const [, forceUpdate] = useState({});
const setValue = useCallback((newVal) => {
// 同步更新 ref 值(供后续读取)
valueRef.current = typeof newVal === 'function'
? newVal(valueRef.current)
: newVal;
// 触发重渲染(关键!)
forceUpdate({});
}, []);
// 返回当前 ref 值
(始终是最新的)
return [valueRef.current, setValue];
};? 使用示例(与原生 useState 完全一致):
function App() {
const [count, setCount] = useCustomState(3);
return (
<>
{count}
>
);
}⚠️ 关键注意事项:
? 延伸建议:
实际项目中,无需重复造轮子。useState 本身已高度优化且支持所有场景(对象、数组、函数更新等)。若需封装逻辑(如表单状态、防抖 setState),应基于 useState 构建「带业务语义的 custom Hook」(例如 useFormState, useDebouncedState),而非试图“重写” useState 内核。
掌握其原理是为了深入理解 React 的状态模型,而非替代它——这才是自定义 Hook 的正确实践哲学。