让set变化的React setStat的奇怪行为

时间:2019-03-15 21:24:53

标签: javascript reactjs

下面的代码将呈现一个<h1>和两个<button>

我期望changeString1 <button>会将letString更改为1,并将<h1>文本更改为{{1 }},最后1 changeString2

  1. <button>文本更改为<h1> 如果我先单击3
  2. changeString2文本更改为<h1> 如果我先单击1

但是实际上

  1. 如果我先单击changeString1 一次,然后单击changeString1,则 changeString2文本将是<h1> !但是为什么?
  2. 更多,如果我先单击3 两次,然后单击changeString1 changeString2文本将为<h1> !但是为什么?

两个事实似乎都是矛盾的...

您可以通过https://codesandbox.io/s/wy4l1y4o8

对此进行测试
1

3 个答案:

答案 0 :(得分:3)

请查看正在发生的流程:-

1st click on changeString1

state changes

component re renders

letString gets re-initialized to 3 because of let letString = "3"

value of letString = 3;
value of statString = 1 (state);

2nd click on changeString1

value of letString gets set to 1 in the function call;

But value of statString(state) is already 1 so no state changes and component never re-renders and letString is not re-initialized

After 2nd click values are:-

letString = 1;
statString = 1(state);

Now, when you click on changeString2 value of letString is 1 and statString is also 1 so state doesn't changes and nothing happens and you just see 1.

答案 1 :(得分:0)

当您点击 changeString2 时,本地变量 letString 的值为3。

如果要在渲染周期之间保留 letString 值,则必须使用 useState 甚至使用全局范围变量(不推荐)

答案 2 :(得分:0)

您应该跟踪在单独的变量中对changeString1的点击:

const {useState} = React

function App() {
  const [statString, setStatString] = useState("2");
  const [clicked, setClicked] = useState(false)

  function changeString1() {
    setClicked(true)
    setStatString("1");
  }

  function changeString2() {
    setStatString(clicked ? "1" : "3");
  }

  return (
    <div>
      <h1>{statString}</h1>
      <button onClick={changeString1}>changeString1</button>
      <button onClick={changeString2}>changeString2</button>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<div id="root" />

您的代码无法按预期运行的原因是,每次调用App都会创建letState变量的新实例,该实例在changeString2函数>已定义。 React优化了不会更改状态的调用,避免了不必要的重新渲染。因此,当您第二次单击时,不会引起回调函数的替换。因此,当您单击changeState2时,它与“上一个”渲染中定义的功能相同。