Skip to content

useBoolean

优雅的管理 boolean 状态的 Hook。

基础用法

切换 boolean,可以接收默认值。

tsx
import React from "react";
import { useBoolean } from "ahooks"; 

export default () => {
  const [state, { toggle, setTrue, setFalse }] = useBoolean(true);

  return (
    <div>
      <p>Effects:{JSON.stringify(state)}</p>
      <p>
        <button type="button" onClick={toggle}>
          Toggle
        </button>
        <button type="button" onClick={setFalse} style={{ margin: "0 16px" }}>
          Set false
        </button>
        <button type="button" onClick={setTrue}>
          Set true
        </button>
      </p>
    </div>
  );
};

使用场景

  • 弹窗
  • 抽屉
  • 开关
  • 蒙层

实际场景

antd-mobile中的Mask组件是通过visible的值进行控制的,因此我们最基础的会使用useState设置一个布尔值,然后通过setState去切换true/false,具体代码如下

tsx
import React, { useState } from "react";
import type { FC } from "react";
import { Button, Mask } from "antd-mobile";

// 基础用法
const Simple: FC = () => {
  const [visible, setVisible] = useState(false);
  return (
    <>
      <Button onClick={() => setVisible(true)}>显示背景蒙层</Button>
      <Mask visible={visible} onMaskClick={() => setVisible(false)} />
    </>
  );
};

一个蒙层编写固然可以这么写,且没有这么繁杂,但如果是多个蒙层的情况下,不是得重复编写多次() => setVisible(true)() => setVisible(false),这样会显得代码十分杂乱不堪(不够优雅)。

因此就可以使用useBoolean进行替代,将上述代码用useBoolean修改为

tsx
import React, { useState } from "react";
import type { FC } from "react";
import { Button, Mask } from "antd-mobile";
import { useBoolean } from "ahooks";

// 基础用法
const Simple: FC = () => {
  const [visible, { setTrue, setFalse }] = useBoolean(false);
  return (
    <>
      <Button onClick={setTrue}>显示背景蒙层</Button>
      <Mask visible={visible} onMaskClick={setFalse} />
    </>
  );
};

ahooks 源代码

tsx
import { useMemo } from "react";
import useToggle from "../useToggle";

export interface Actions {
  setTrue: () => void;
  setFalse: () => void;
  set: (value: boolean) => void;
  toggle: () => void;
}

export default function useBoolean(defaultValue = false): [boolean, Actions] {
  const [state, { toggle, set }] = useToggle(!!defaultValue);

  const actions: Actions = useMemo(() => {
    const setTrue = () => set(true);
    const setFalse = () => set(false);
    return {
      toggle,
      set: (v) => set(!!v),
      setTrue,
      setFalse,
    };
  }, []);

  return [state, actions];
}

在源代码中,useToggleahooks中的一个hook,用于切换状态,详情参考上一章useToggle

使用!!来保证传入的值能够准确转换为bool类型,设置一个actions变量使用useMemo包起来,在hook初次加载时便缓存下来,以防多次rerender,来保证hook的质量。

最后将stateactions放在数组内返回。

简易封装

在下面代码中,去掉了useToggle函数的调用封装,直接转换为useState,在toggle中写成setState((state) => !state)而不是setState((!state)是为了保证每次拿到的state变量都为最新的,而不是缓存时的state变量。

tsx
import { useMemo, useState } from "react";

export interface Actions {
  setFalse: () => void;
  setTrue: () => void;
  toggle: () => void;
}

export const useBoolean = (defaultValue = false): [boolean, Actions] => {
  const [state, setState] = useState(!!defaultValue);

  const actions = useMemo(() => {
    const setFalse = () => setState(false);
    const setTrue = () => setState(true);
    const toggle = () => setState((state) => !state);

    return {
      setFalse,
      setTrue,
      toggle,
    };
  }, []);

  return [state, actions];
};