通八洲科技

如何在 React 中正确实现自定义 useState Hook

日期:2026-01-02 00:00 / 作者:花韻仙語

本文详解为何简单闭包无法复现 usestate 行为,并提供符合 react 更新机制的自定义 usecustomstate 实现方案,包含 useref + useeffect 的正确范式、可变状态同步原理及关键注意事项。

React 的 useState 不仅管理值,更核心的是触发组件重渲染。你原始代码的问题在于:value 是一个局部变量,setValue 仅修改了该变量,但未通知 React 触发更新——因此 UI 永远停留在初始值 3。

要真正模拟 useState,必须满足两个条件:

  1. 状态持久化:跨多次渲染保持最新值(不能每次调用 Hook 都重置);
  2. 触发重渲染:状态变更后,必须调用 setState 或等效机制(如 forceUpdate)驱动组件更新。

✅ 正确实现方式是借助 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 的正确实践哲学。