likes
comments
collection
share

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

作者站长头像
站长
· 阅读数 32

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
评论
请登录