实现useToggle

1,021 阅读1分钟

自定义hooks

作为react的使用者,自定义hooks是常见的业务需求,小弟技术水平有限,只能先借花献佛聊下公司里大佬们封装的自定义hooks了

import { useState, useMemo } from 'react';

export interface Actions<T> {
  setLeft: () => void;
  setRight: () => void;
  toggle: () => void;
  set: (value: T) => void;
}

export function useToggle<T = boolean>(): [boolean, Actions<T>];

export function useToggle<T>(defaultValue: T): [T, Actions<T>];

export function useToggle<T, U>(defaultValue: T, reverseValue: U): [T | U, Actions<T | U>];

/**
 * 用于在两个状态值间切换的 Hook
 * @param defaultValue 默认的状态值
 * @param reverseValue 取反的状态值
 * @returns
 */
export function useToggle<D, R>(
  defaultValue: D = false as unknown as D,
  reverseValue?: R
) {
  const [state, setState] = useState<D | R>(defaultValue);

  const actions = useMemo(
    () => {
      // 取反的状态值
      const reverseValueOrigin = (reverseValue === undefined ? !defaultValue : reverseValue) as D | R;

      const toggle = () => setState((s) => (s === defaultValue ? reverseValueOrigin : defaultValue));
      const set = (value: D | R) => setState(value);
      // 设置默认状态值
      const setLeft = () => setState(defaultValue);
      // 设置取反状态值
      const setRight = () => setState(reverseValueOrigin);

      return {
        toggle,
        set,
        setLeft,
        setRight,
      };
    },
    []
  );

  return [state, actions];
}

实现思路也比较简单,就是通过useMemo的缓存,将每次改动的最新状态值储存下来,然后将值与修改值的setState方法抛出,主要用于储存两个相关值。

用法如下

export default () => {
  const [state, { toggle, set, setLeft, setRight }] = useToggle('Hello', 'World');


  return (
    <div>
      <p>状态值: {state}</p>
      <Space>
        <Button onClick={toggle}>
          Toggle
        </Button>
        <Button onClick={() => set('Hello')}>
          Toggle Hello
        </Button>
        <Button onClick={() => set('World')}>
          Toggle World
        </Button>
        <Button onClick={setLeft}>
          Set Hello
        </Button>
        <Button onClick={setRight}>
          Set World
        </Button>
      </Space>
    </div>
  );
};

个人的分享记录,不喜勿喷。