当前位置: 首页 > 知识库问答 >
问题:

useState钩子设置器错误地覆盖状态

南宫喜
2023-03-14

问题是:我试图通过单击按钮调用两个函数。这两个函数都会更新状态(我正在使用useState钩子)。第一个函数将value1正确更新为“new 1”,但在1s(setTimeout)后,第二个函数启动,它将值2更改为“new 2”,但是!它将值1设置回“1”。为什么会这样?提前谢谢!

import React, { useState } from "react";

const Test = () => {
  const [state, setState] = useState({
    value1: "1",
    value2: "2"
  });

  const changeValue1 = () => {
    setState({ ...state, value1: "new 1" });
  };
  const changeValue2 = () => {
    setState({ ...state, value2: "new 2" });
  };

  return (
    <>
      <button
        onClick={() => {
          changeValue1();
          setTimeout(changeValue2, 1000);
        }}
      >
        CHANGE BOTH
      </button>
      <h1>{state.value1}</h1>
      <h1>{state.value2}</h1>
    </>
  );
};

export default Test;

共有3个答案

鲁景山
2023-03-14

当调用ChangeValue2时,初始状态保持不变,因此状态会返回初始状态,然后写入value e2属性。

之后下次调用changeValue2时,它将保持状态{value1:“1”,value2:“new 2”},因此将覆盖value1属性。

setState参数需要一个箭头函数。

const Test = () => {
  const [state, setState] = React.useState({
    value1: "1",
    value2: "2"
  });

  const changeValue1 = () => {
    setState(prev => ({ ...prev, value1: "new 1" }));
  };
  const changeValue2 = () => {
    setState(prev => ({ ...prev, value2: "new 2" }));
  };

  return (
    <React.Fragment>
      <button
        onClick={() => {
          changeValue1();
          setTimeout(changeValue2, 1000);
        }}
      >
        CHANGE BOTH
      </button>
      <h1>{state.value1}</h1>
      <h1>{state.value2}</h1>
    </React.Fragment>
  );
};

ReactDOM.render(<Test />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
潘辰龙
2023-03-14

你的功能应该是这样的:

const changeValue1 = () => {
    setState((prevState) => ({ ...prevState, value1: "new 1" }));
};
const changeValue2 = () => {
    setState((prevState) => ({ ...prevState, value2: "new 2" }));
};

因此,通过在触发操作时使用前一个状态,可以确保当前状态中没有丢失任何现有属性。因此,您还可以避免管理闭包。

终祯
2023-03-14

欢迎来到关闭地狱。发生此问题是因为每当调用setState时,state都会获得一个新的内存引用,但是由于闭包,函数Change eValue1Change eValue2会保留旧的初始state引用。

确保setStatefromChangeValue1ChangeValue2获得最新状态的解决方案是通过使用回调(将前一个状态作为参数):

import React, { useState } from "react";

const Test = () => {
  const [state, setState] = useState({
    value1: "1",
    value2: "2"
  });

  const changeValue1 = () => {
    setState((prevState) => ({ ...prevState, value1: "new 1" }));
  };
  const changeValue2 = () => {
    setState((prevState) => ({ ...prevState, value2: "new 2" }));
  };

  // ...
};

你可以在这里和这里找到关于这个关闭问题的更广泛的讨论。

 类似资料:
  • 我想用React useState钩子设置多个状态值,这样我就可以用useEffect钩子分别更新它们。我有以下代码: 但是当我用React DevTools检查应用程序时,我会看到钩子的多个“状态”值,而不是“订单”、“支付”、“提交”等。

  • 我有一个对象的状态数组: 我有一个添加按钮,用于将对象添加到数组中,这是onclick事件的主体:

  • 我正在迁移React with TypeScript项目以使用钩子特性(React v16.7.0-alpha),但我不知道如何设置分解结构元素的类型。 以下是一个例子: 我想强制变量类型为。我唯一成功的试验是分两个阶段进行:打字,然后初始化: 但我相信有更好的办法。另外,应该初始化为一个函数,该函数将作为输入,并且不返回任何内容。 另外,值得注意的是,使用

  • 我有一个React函数组件,沿着遗留的JQuery应用程序运行。在JQuery元素上调用事件处理程序时,传递当前React状态默认值为初始状态值,而不是更新后的状态值。 已验证的x状态正在通过useEffect钩子更改,但在调用事件侦听器时,x设置为初始状态值,而不是更新后的状态值。 不会显示任何错误消息。在本文的上述代码中,我希望onXSave方法调用中的x状态为true,但它一直显示为fals

  • 问题内容: 当我用酶测试类组件时,我可以设置状态。当我用钩子测试功能组件时,现在该怎么做? 例如,在我的组件中,我有: 我想在测试中进行更改 问题答案: 使用挂钩状态时,您的测试必须忽略诸如状态之类的实现细节,以便对其进行正确测试。您仍然可以确保组件将正确的状态传递到其子级。 您可以在Kent C. Dodds撰写的这篇博客文章中找到一个很好的例子。 这是摘录的代码示例。 依赖状态执行细节的测试-

  • 我正在React中使用useState钩子,状态将不会在