8

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

 3 years ago
source link: https://segmentfault.com/a/1190000041489001
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

封装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 }]

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK