React-ahooks 源码解析 useSetState篇

608 阅读1分钟

ahooks - 阿里开源的一款 react hooks 库

API

管理 object 类型 state 的 Hooks,用法与 class 组件的 this.setState 基本一致。

代码演示

er91h-fl66w.gif

import React from 'react';
import { useSetState } from 'ahooks';


interface State {
  hello: string;
  [key: string]: any;
}


export default () => {
  const [state, setState] = useSetState<State>({
    hello: '',
  });


  return (
    <div>
      <pre>{JSON.stringify(state, null, 2)}</pre>
      <p>
        <button type="button" onClick={() => setState({ hello: 'world' })}>
          set hello
        </button>
        <button type="button" onClick={() => setState({ foo: 'bar' })} style={{ margin: '0 8px' }}>
          set foo
        </button>
      </p>
    </div>
  );
};

解析

主要基于 useCallback or useState 2个 hooks API

在初始化的 时候 创建了一个泛型 用于声明类型

Record - 将第一个类型的属性映射到另一个类型并创造一个新的类型

Pick - 从类型定义的属性中,选取指定一组属性,返回一个新的类型定义。

export type SetState<S extends Record<string, any>> = <K extends keyof S>( state: Pick<S, K> | null | ((prevState: Readonly<S>) => Pick<S, K> | S | null), ) => void;

先创建一个类型 并声明一个泛型S继承于映射类型

类型为: 一个 指定继承于 S 的类型 或 一个 函数方式的类型 参数为 上一层的State 返回 void

创建 useSetState 函数 接受 initialState 初始值

主要 通过 useState 创建一个 响应式状态并赋予 S 泛型 - 默认值为 initialState

再声明一个 useCallback 创建的函数 用于缓存函数 主要用于监听值变换后改变 state

最后返回 当前模块内部的 State对象 和 更新State方法

import { useCallback, useState } from 'react';
import { isFunction } from '../utils';

export type SetState<S extends Record<string, any>> = <K extends keyof S>(
  state: Pick<S, K> | null | ((prevState: Readonly<S>) => Pick<S, K> | S | null),
) => void;

const useSetState = <S extends Record<string, any>>(
  initialState: S | (() => S),
): [S, SetState<S>] => {
  const [state, setState] = useState<S>(initialState);

  const setMergeState = useCallback((patch) => {
    setState((prevState) => {
      const newState = isFunction(patch) ? patch(prevState) : patch;
      return newState ? { ...prevState, ...newState } : prevState;
    });
  }, []);

  return [state, setMergeState];
};

export default useSetState;