如果我有一个需要使用和操作多个状态项的功能组件,并且我有多个状态用于不直接相关的不同事物(例如游戏统计数据和 UI 元素状态),那么性能(或实践)会更好吗这样做:
const [state, setState] = React.useState({
username: 'JoeSchmoe200',
points: 200,
isHoveringOverItem: {item1: false, item2: false, item3: false},
selectedItem: {item1: true, item2: false, item3: false}
})
(状态中保存的所有内容都在一个对象中并使用一种方法设置),或者像这样:
const [username, setUsername] = React.useState('JoeSchmoe200')
const [points, setPoints] = React.useState(200)
const [isHoveringOverItem, setIsHoveringOverItem] = React.useState(
{item1: false, item2: false, item3: false}
)
const [selectedItem, setSelectedItem] = React.useState(
{item1: true, item2: false, item3: false}
)
其中每个状态都是单独声明和单独设置的。我只是想在这里引发一场对话,以了解有关 React 的更多信息。
您对这种表现有何看法?可读性方面? 这是偏好问题还是有客观的最佳实践?
在 React 18 之前,建议将预期更改的状态变量分组在一起。 React 用于批处理状态更新,但仅限于那些直接在 React 事件(例如
onClick
、onChange
等)和生命周期方法(例如 useEffect
)中的状态更新。异步方法中的多个状态更新,例如fetch()
未批量处理。
然而,在 React 18 中,所有一起发生的状态更新都会自动批处理到单个渲染中。这意味着可以将状态拆分为任意多个单独的变量。
来源:https://reactjs.org/blog/2022/03/29/react-v18.html#new-feature-automatic-batching
不过,在我看来,将相关部分放在一起以获得更好的代码可读性是一个很好的做法。但状态对象应保持在可管理的大小,否则应使用
useReducer()
。
在 React 18 中,状态更新会自动批处理,因此您实际上不需要将所有内容混合到一个状态对象中。请阅读此处有关自动批处理的部分。了解了这一点,以下是我从本文
中获得的一些提示无论哪种方式都可以。 React 18 通过引入状态更新批处理解决了这个问题。
真正的答案在于你所在州的行为方式。假设您正在构建一个具有多个输入的表单。建议创建一个状态对象,其中每个属性代表一个输入。这样,您只需要 1 个
onChange
事件处理程序即可使用 HTMLInputElement
name
属性(例如 name="objectPropertyName"
)来了解要更新哪个属性。在你所在的州,你会做类似 setState(currentState => ({...currentState, [name]: value}))
的事情。
但是,将每个属性隔离在其自己的状态上还允许您添加严格针对该特定属性的额外逻辑,因为您将为每个状态单独声明
onChange
事件处理程序。例如,验证,某些字段可能需要复杂的验证程序。