封装React|封装React Hook函数useState实现更优雅的setValue

react hooks确实很好用,代码相比class组件也会简洁一些,但有时候也会觉得对useState的数据更新时有不太方便的地方,比如声明数组或者对象的时候,在设置的时候就得传一个函数回去,并且使用扩展运算符合并对象

setValue((oldValue) => ({ ...oldValue, ...newValue, }));

感觉在组件里这样看着不是太美观,并且如果组件代码多一点的时候,更新一下数据需要占用三行,尤其在if/for或者回调里面使用的时候看着更是难受,于是决定对useState做一下简单的封装,让组件里更新数据时更优雅一些。
首先写几个工具函数isArray、isObject、isNotObject
function isArray(value) { return value instanceof Array; }function isObject(value) { return value instanceof Object && !(value instanceof Array); }function isNotObject(value) { return typeof value !== "object"; }

【封装React|封装React Hook函数useState实现更优雅的setValue】然后在我们的自定义hook函数useSetState中,用原声的useState声明变量,变量可以直接返回,只需对_setValue做一些操作返回一个新的setValue。
在setValue中,如果initValue为数组,那新的setValue在传入单个值时进行push,传入数组时进行合并;如果initValue为对象,传入对象合并,传入其他类型则抛出错误。
import { useState } from "react"; export default function useSetState(initValue) { const [_value, _setValue] = useState(initValue); function setValue(newValue) { // 初始数据为 数组 if (isArray(initValue)) { if (isArray(newValue)) { _setValue((oldValue) => [...oldValue, ...newValue]); } else { _setValue((oldValue) => [...oldValue, newValue]); } } // 初始数据为 对象 else if (isObject(initValue)) { if (isObject(newValue)) { _setValue((oldValue) => ({ ...oldValue, ...newValue, })); } else { throw new Error(`${JSON.stringify(newValue)} 与初始数据类型不符!`); } } else if (isNotObject(initValue)) { _setValue(newValue); } } return [_value, setValue]; }

实际使用效果
const [obj, setObj] = useSetState({ a: 1, b: 2, }); const [arr, setArr] = useSetState([{ id: 1 }, { id: 2 }]); setObj({ c: 3 }); // {a: 1, b: 2, c: 3} setArr({ id: 3 }); // [{ id: 1 }, { id: 2 },{ id: 3 }]

    推荐阅读