理解 React useState() 钩子

Understanding React useState() hook

我正在使用 useState() 挂钩开发功能性 React 组件。我对这个钩子的使用方式或其背后的设计决策感到有点困惑。

我做了一个代码笔示例来说明我的问题:

https://codepen.io/svenvandescheur/pen/ewwBwR

Class 基于组件

在基于 class 的组件中,this.setState({foo: 'bar'}) 仅使用传递给第一个参数的对象中的键更新了状态。如果状态已经包含不同的值,则这些值将保留在原位。

功能组件

我错误地认为 useState() 提供的 setState() 的语法和行为与 Component 提供的语法和行为非常相似。但是,我注意到 setState({foo: 'bar'}) 会替换整个状态,删除未传递的键。

这个问题可以通过使用扩展运算符在每次调用 setState() 时传递整个状态,然后在之后添加更改来解决,如下所示:setState({...state, foo: 'bar'}).

这感觉非常重复,在我的真实场景中甚至导致新状态被旧状态覆盖的错误。

我的问题是,我是否正确地将 Component 中的 useState() 理解为 useState(),以及为什么选择这种行为。目前在 React 中处理状态的首选方式是什么。

您的理解是正确的。 setState 会将当前状态和新状态合并在一起以创建一个新状态。 useState 将采用给定值并替换旧状态。

这种行为可能看起来不直观,但允许将原始值用作状态,例如字符串、数字和布尔值。

如果您需要更多状态,只需添加更多 useState。如果你的状态更新逻辑变得有点复杂,你应该使用 useReducer.

因此,如果您的状态是一个对象,您将需要创建一个新对象并使用它进行设置。这可能涉及传播旧状态。例如:

const [person, setPerson] = useState({ name: 'alice', age: 30 });

const onClick = () => {
  // Do this:
  setPerson(prevPerson => {
    return { 
      ...prevPerson, 
      age: prevPerson.age + 1 
    }
  })

}

也就是说,使用钩子后,您通常不再需要将状态设为对象,而是可以多次使用 useState。如果您不使用对象或数组,则不需要复制,因此也不需要传播。

const [name, setName] = useState('alice');
const [age, setAge] = useState(30);

const onClick = () => {
  setAge(prevAge => prevAge + 1);
}