理解 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);
}
我正在使用 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);
}