React useState挂钩似乎无法在显式调用setter函数的情况下更新状态

时间:2020-03-24 19:23:17

标签: javascript reactjs react-hooks

这是编写的代码

function App() {

  const [number, setNumber] = useState(1);
  const mapper = {
    1: 'One',
    2: 'two',
    3: 'three'
  }
  const setFirst = () => {
    setNumber(1);
    console.log(number);
    console.log(mapper[number]);
  }
  const setSecond = () => {
    setNumber(2);
    console.log(number);
    console.log(mapper[number]);
  }
  const setThird = () => {
    setNumber(3);
    console.log(number);
    console.log(mapper[number]);
  }
  return (
    <div>
      <button onClick={() => { setFirst(); }}>One</button>

      <button onClick={() => { setSecond() }} >Two</button>

      <button onClick={() => { setThird(); }} >Three</button>
    </div>
  );
}

预期: 单击setFirst()时,数字应设置为1。 单击setSecond()时,数字应设置为2。 单击setThird()时,数字应设置为3。

发生了什么

按顺序单击时 setFirst() -> setSecond() -> setThird() 以重复的方式

输出:

1
One
1
One
2
Two
3
Three
1
One

预期输出:

1
One
2
Two
3
Three
1
One
2
Two

有人可以帮我吗?我需要帮助找出错误的位置。

2 个答案:

答案 0 :(得分:1)

正如克里斯在评论中所说,setNumber是一个异步函数,因此执行后立即看不到它的更新。

此外,您应该知道,在每次渲染时,组件内部的每个方法都“堆叠”在其当前闭包内部。让我详细说明:

  1. 您呈现该组件,该组件返回button(假设只是第一个)。渲染button时,由于setFirst已链接到它,因此可以想象创建了一种房间,其中复制了setFirst中使用的所有外部变量。因此,由于setFirst使用变量numbermapper,因此将在此“房间”内创建它们的副本;
  2. 当您最终单击setFirst时,您将运行setNumbersetNumber不会更新number房间内的setFirst,但是会更新将在下一个渲染阶段使用的number

此示例旨在使您理解为什么单击setSecond时会记录 1一个:为该渲染初始化setSecond方法时,{ {1}}仍为number

答案 1 :(得分:0)

在事件循环中使用setter函数时。有一个异步功能。您可以设为sync函数。但是大多数情况下我们不建议这样做,所以我更喜欢使用回调来做到这一点。

setNumber(2, () => {
  console.log('');
})

反模式同步方式

Promise.resolve().then(() => {
  setNumber(2);
  console.log(2);
})