【问题标题】:React useState variable doesn't get copied by valueReact useState 变量不会被值复制
【发布时间】:2021-10-28 10:56:53
【问题描述】:

我有一个非常基本的示例,但我无法弄清楚我做错了什么。我有一个非常简单的计数器,我想将其初始状态复制到另一个没有反应性的变量,但不能这样做。

import { useState } from "react";
import "./styles.css";

export default function App() {
  const [number, setNumber] = useState({ val: 10 });
  const numberAssign = Object.assign({}, number);
  const numberJSON = { ...number };
  const numberSpread = JSON.parse(JSON.stringify(number));
  const clicked = () => {
    setNumber({ val: number.val + 1 });
  };

  return (
    <div className="App">
      <button onClick={clicked}>Inc</button>
      <p>{number.val}</p>
      <p>{numberAssign.val}</p>
      <p>{numberJSON.val}</p>
      <p>{numberSpread.val}</p>
    </div>
  );
}

单击按钮时所有变量都会递增,但我只希望 number 变量递增。

【问题讨论】:

  • useState 将始终返回“最新”状态值——这就是重点。因此,如果您不希望这些变量也获得更新的值,请不要将该值分配给其他变量。
  • 所以没有办法从中检索值(没有反应部分)?
  • 每次调用 setNumber 时,都会使用更新后的数字值再次调用整个 App 函数。因此,所有代码都使用更新后的值再次评估。如果要复制 initialState ,则需要使用另一个钩子来保持值不变。例如,您可以查看 useMemo 挂钩
  • 好的,我去看看,谢谢
  • 或者你可以在组件外部初始化数值并在useState中使用它作为初始值。

标签: javascript reactjs typescript use-state


【解决方案1】:

变量没有异常行为。您正在将变量设置为状态变量的值,在这种情况下,状态变量会不断更新。 尝试在状态之外声明 val 变量

`const val = 10;
const [number, setNumber] = useState({ val });`

然后使用 val 代替数字状态。

【讨论】:

    【解决方案2】:

    我不知道这是否会对你有很大帮助,但你可以使用另一个 useState 挂钩来存储当前状态的 prev 值。代码:

    import { useState } from "react";
    
    export default function App() {
      const [currNum, setCurrNum] = useState(10);
      const [prevNum, setPrevNum] = useState(0);
      const clicked = () => {
        setPrevNum(prevNum);
        setCurrNum(prevNum+=1);
      };
      return (
        <div className="App">
          <button onClick={clicked}>Inc</button>
          <p>{currNum}</p>
          <p>{prevNum}</p>
        </div>
      );
    }
    

    【讨论】:

      【解决方案3】:

      我不确定我是否理解您问题的全部范围,但我假设您正在寻找 useRef 钩子

      https://reactjs.org/docs/hooks-reference.html#useref

      在您的代码中,它会像这样工作:

      import { useState, useRef } from "react";
      import "./styles.css";
      
      export default function App() {
        const currNumber = useRef({ val: 10 });
        const [number, setNumber] = useState(currNumber.current);
        const clicked = () => {
          setNumber({ val: number.val + 1 });
        };
      
        return (
          <div className="App">
            <button onClick={clicked}>Inc</button>
            <p>{number.val}</p>
            <p>{numberAssign.val}</p>
            <p>{numberJSON.val}</p>
            <p>{numberSpread.val}</p>
          </div>
        );
      }
      

      这样,currentNumber.current 将始终保持 10,除非您更改它...

      【讨论】:

        【解决方案4】:

        在每个 setState(useState) 操作上,组件都会重新渲染其中的所有内容。它只会保留使用诸如 useState 之类的反应钩子创建的值(这就是 useState 想要做的)

        在所有 useStates 之前放置一个console.log('rerender') 你会看到它会触发它的动作,这意味着在功能组件中它不会保留任何变量或值,除非它是使用反应钩子创建的,即使它是 const变量

        在您的情况下,此 const 变量会再次创建并为其分配新的数字对象,这就是它每次都更新的原因。但是你可以在不同的 useStates 中使用它,或者你可以在 useEffect 中定义它,它只会在特定时间触发调用 从“反应”导入 { useState };

        export default function App() {
          console.log('rerender')
          const [number, setNumber] = useState({ val: 10 });
          const [numberAssign, setN] = useState(Object.assign({}, number));
          const [numberJSON, setJSON] = useState({ ...number });
          const [numberSpread,setSpread] = useState(JSON.parse(JSON.stringify(number)));
          const clicked = () => {
            setNumber({ val: number.val + 1 });
          };
        
          return (
            <div className="App">
              <button onClick={clicked}>Inc</button>
              <p>{number.val}</p>
              <p>{numberAssign.val}</p>
              <p>{numberJSON.val}</p>
              <p>{numberSpread.val}</p>
            </div>
          );
        }
        

        【讨论】:

          猜你喜欢
          • 2020-08-31
          • 2021-07-02
          • 1970-01-01
          • 1970-01-01
          • 2021-10-10
          • 2019-10-19
          • 2020-08-17
          • 2022-11-25
          • 1970-01-01
          相关资源
          最近更新 更多