改变 React JS 状态的好方法

good way to change React JS state

{
 "user":{
  "auth":true,
  "sub_sq":[
   "1":{
    "createdAt":"2021-08-28"
   }
  ]
 },
 "sub":{
  "name":"123"
  "sub_sq":[
   "1":{
    "createdAt":"2021-08-21"
   }
  ]
 }
}

你好 当像上面那样改变状态对象时

将更改应用于用户对象时

  1. 深度复制后是否需要更改整个对象?

  2. 还是仅在对用户对象进行深度复制后应用更改?

我喜欢 two(2) 方法,所以我正在应用第一个(deepcopy 仅更改对象)

但我不确定这是否是正确的方法,所以我寻求建议。

谢谢

确实,这是状态管理的一个棘手问题。为此使用展开运算符或建议的 immer library is a good option. I myself have created the @rimbu/deep library。它有一个名为 patch 的方法,允许您编写如下内容:

import { patch } from '@rimbu/deep';

const person = {
  name: "Alice",
  age: 34,
  address: {
    street: "Random street",
    number: 45
  },
  friends: ["Bob", "Carol"]
};

const updatedPerson = patch(person)({
  age: v => v + 1,
  address: {
    street: "Other street"
  },
  friends: v => [...v, "Anne"]
})

// updatedPerson is now:
// {
//   name: "Alice",
//   age: 35,
//   address: {
//     street: "Other street",
//     number: 45
//   },
//   friends: ["Bob", "Carol", "Anne"]
// }

它很新,需要更多文档,但只是想分享一下。

您可以尝试使用此 CodeSandbox:

简而言之,您应该只复制您在新状态值中不更改的内容。例如:

const newState = {
  ...oldState,
  user: {
    ...oldState.user,
    auth: false,
  }
}

更一般地说,将深度嵌套的状态对象拆分为多个状态被认为是一种更好的做法。这允许您在状态更新和稍后的状态侦听器(即 useEffect)中更加具体。例如,您可以将原始状态值拆分为两个变量:

const [user, setUser] = useState({
  "auth": true,
  "sub_sq": [
    "1": {
      "createdAt":"2021-08-28"
    }
  ]
});
const [sub, setSub] = useState({
  "name": "123"
  "sub_sq": [
    "1": {
      "createdAt":"2021-08-21"
    }
  ]
});

如果您坚持使用复合状态,最好使用缩减器以更可控的方式更新每个状态“部分”。来自 React's useReducer documentation:

useReducer is usually preferable to useState when you have complex state logic that involves multiple sub-values or when the next state depends on the previous one