规范1、根据情况使用单个State变量还是多个
useState 的出现,让我们可以使用多个 state 变量来保存 state,比如:
写法一、
const [width, setWidth] = useState(100);
const [height, setHeight] = useState(100);
const [left, setLeft] = useState(0);
const [top, setTop] = useState(0);
写法二、
const [state, setState] = useState({
width: 100,
height: 100,
left: 0,
top: 0
});
如果使用单个 state
变量,每次更新 state
时需要合并之前的 state
。因为 useState 返回的 setState 会替换原来的值。这一点和 Class 组件的 this.setState 不同。this.setState 会把更新的字段自动合并到 this.state 对象中。
const handleMouseMove = (e) => {
setState((prevState) => ({
...prevState,
left: e.pageX,
top: e.pageY,
}))
};
使用多个 state 变量可以让 state 的粒度更细,更易于逻辑的拆分和组合。比如,我们可以将关联的逻辑提取到自定义 Hook 中:
function usePosition() {
const [left, setLeft] = useState(0);
const [top, setTop] = useState(0);
useEffect(() => {
// ...
}, []);
return [left, top, setLeft, setTop];
}
我们发现,每次更新 left
时 top
也会随之更新。因此,把 top
和left
拆分为两个 state
变量显得有点多余。
在使用 state
之前,我们需要考虑状态拆分的「粒度」问题。如果粒度过细,代码就会变得比较冗余。如果粒度过粗,代码的可复用性就会降低。那么,到底哪些 state
应该合并,哪些 state
应该拆分呢?我总结了下面两点:
- 将完全不相关的
state
拆分为多组state
。比如size
和position
。 - 如果某些
state
是相互关联的,或者需要一起发生改变,就可以把它们合并为一组state
。比如left
和top
。
规范2、hooks依赖数组不得超过3个
在 React 中,除了 useEffect 外,接收依赖数组作为参数的 Hook 还有 useMemo、useCallback 和 useImperativeHandle。如果依赖数组依赖了过多东西,可