为什么在更新之前更改对象是错误的?

问题描述 投票:0回答:2

我们已经知道,为了触发新的渲染,React 会根据类型和值比较状态变量 (

===
)。然而,当我们想要更新对象时,我们必须克隆内部的任何嵌套对象以避免改变实际对象,因此每次都在一个新副本上工作。

例如,假设我们有以下对象:

const [object, setObject] = useState({a: {b: {c: {a: 'a'}}}})
setObject(prev=>{...prev, {b: {...prev.b, c: {...prev.b.c, a: 'new value'}}}}

这意味着在这一点之前我必须克隆所有内容,因为任何对象在内存中都有自己的实际表示。

但是,如果执行以下操作:

object.b.c.a = 'new value'
setObject({...object})

它将触发渲染,因为对象的主要引用已更改。这有什么问题,使用它会发生什么?

我唯一能想到的是我不使用对象的前一个状态,如果我使用计时器,它可能会导致一些问题,因为它无法获取最近的状态。但总的来说,如果我不在这里使用定时器,有什么问题吗?

reactjs
2个回答
0
投票

不修改状态:

state
中的
App
的变化不会影响
value
中的
Child

import { useState } from "react";

export default function App() {
  const [state, setState] = useState({ user: { name: "Alex" } });

  const handleClick = () => {
    setState({ ...state, user: { ...state.user, name: "Tom" } });
  };

  return (
    <div className="App">
      <button onClick={handleClick}>Click me</button>
      <p>Your current name is: {state.user.name}</p>
      <Child user={state.user} />
    </div>
  );
}

function Child({ user }) {
  // assign props once
  const [value, setValue] = useState(user);

  // state doesn't change
  return <p>Your previous name is: {value.name}</p>;
}

Edit peaceful-stallman-13ymdi

修改状态

state
App
的变化会影响
value
中的
Child
,尽管它不应该

import { useState } from "react";

export default function App() {
  const [state, setState] = useState({ user: { name: "Alex" } });

  const handleClick = () => {
    state.user.name = "Tom";
    setState({ ...state });
  };

  return (
    <div className="App">
      <button onClick={handleClick}>Click me</button>
      <p>Your current name is: {state.user.name}</p>
      <Child user={state.user} />
    </div>
  );
}

function Child({ user }) {
  // assign props once
  const [value, setValue] = useState(user);

  // state changes although it shouldn't
  return <p>Your previous name is: {value.name}</p>;
}

Edit kind-cdn-wp0gdo


0
投票

好吧,这是一个例子,说明在 React 状态下直接改变对象如何导致一些错误:

const [state, setState] = useState({count: 0, message: ''})

function handleClick() {
// Directly mutate the state object
state.count++
state.message = `Clicked ${state.count} times`

// Call setState with the mutated object
setState(state)
}

在这里,我们直接改变状态对象,然后用改变后的对象调用 setState()。

这可能会导致细微的错误,因为 React 出于性能原因将状态更新一起批处理。如果您直接更新一个状态变量,然后使用其他变量调用 setState(),React 可能不会按照您期望的顺序应用更新。 在这种情况下,React 可能会应用计数更新而不是消息更新。这可能会导致消息不反映当前计数的不一致状态。

为避免这些问题,最好始终使用 setState() 的函数形式并将先前状态作为参数传递。这可确保您始终使用最新状态,并确保以正确的顺序应用更新。

希望这对你有帮助,这适用于数组和对象。

© www.soinside.com 2019 - 2024. All rights reserved.