封装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";
}
然后在我们的自定义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 }]
转载自:https://segmentfault.com/a/1190000041489001