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

原生JS/Node复刻React useState:状态变量无法同步更新求解

复刻React useState:解决状态更新后变量不同步问题

我尝试在原生JavaScript/Node中复刻React的useState函数,当前实现代码如下:

let callIndex = -1

const stateValues = []

const useState = (initialValue) => {
    callIndex++ // 0

    const currentCallIndex = Number(callIndex) // 0

    if (stateValues[currentCallIndex] === undefined){
        stateValues[currentCallIndex] = initialValue
    }

    const setValue = (newValue) => {
        stateValues[currentCallIndex] = newValue
    }

    return [stateValues[currentCallIndex], setValue]
}

const [countA, setCountA] = useState(1)
const [countB, setCountB] = useState(-1)

这个实现的问题是:解构得到的countA、countB只是初始值的副本,并没有和stateValues数组的对应位置形成动态关联。调用setValue更新状态后,stateValues里的值确实更新了,但countA、countB始终是初始值:

setCountA(3)
// LOGs->   stateValues[0]:  3, stateValues[1]:  -1,  countA:  1,  countB:  -1
setCountA(5)
setCountB(9)
// LOGs->    stateValues[0]:  5, stateValues[1]:  9,  countA:  1,  countB:  -1
setCountA(2)
setCountB(5)
// LOGs->   stateValues[0]:  2, stateValues[1]:  5,  countA:  1,  countB:  -1

我可以让useState返回箭头函数来获取最新状态,但每次取值都要调用函数。有没有更贴近React风格的方式,不用调用函数,直接通过countA这类变量获取更新后的值?


解决方案:模拟React的组件渲染周期

React的核心逻辑是状态更新后重新执行组件函数,重新执行useState时会从状态存储中读取最新值,解构得到的变量自然就是最新状态。我们可以复刻这个机制:

let callIndex = -1
const stateValues = []

// 模拟React的渲染调度:每次渲染重置callIndex,重新执行组件函数
function render(component) {
  callIndex = -1
  component()
}

const useState = (initialValue) => {
  callIndex++
  const currentCallIndex = callIndex

  if (stateValues[currentCallIndex] === undefined) {
    stateValues[currentCallIndex] = initialValue
  }

  const setValue = (newValue) => {
    stateValues[currentCallIndex] = newValue
    // 状态更新后触发重新渲染
    render(component)
  }

  return [stateValues[currentCallIndex], setValue]
}

// 把所有状态相关逻辑放在"组件"函数中
function component() {
  const [countA, setCountA] = useState(1)
  const [countB, setCountB] = useState(-1)

  // 这里的countA、countB每次渲染都是最新值
  console.log(`countA: ${countA}, countB: ${countB}, stateValues: ${JSON.stringify(stateValues)}`)

  // 暴露setter方便测试(实际场景中可在组件内部处理更新逻辑)
  window.setCountA = setCountA
  window.setCountB = setCountB
}

// 首次渲染组件
render(component)

测试效果

调用setter时会自动触发重新渲染,此时解构得到的变量就是最新状态:

setCountA(3)
// 输出:countA: 3, countB: -1, stateValues: [3,-1]
setCountB(9)
// 输出:countA: 3, countB: 9, stateValues: [3,9]
setCountA(2)
// 输出:countA: 2, countB: 9, stateValues: [2,9]

原理说明

  • 每次调用setValue更新状态后,会触发render函数重置callIndex并重新执行组件函数
  • 组件函数重新执行时,会再次调用useState,此时callIndex从0开始计数,对应stateValues中的最新值,解构得到的countA、countB自然就是最新状态
  • 这完全贴合React的运行逻辑:状态更新驱动组件重新渲染,保证状态变量始终是最新值

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 03:00:59