自定义 React Hooks:useBoolean

2025-05-28

自定义 React Hooks:useBoolean

React Hooks 最初允许你“钩住” React 的状态和生命周期功能,就像我们以前使用基于类的组件时使用componentDidMount或方法一样。在本文中,我们将发现,我们可以使用 React 提供的几个基本 Hooks(例如)来实现我们自己的自定义 Hooks。这样,你可以将一些逻辑转移到函数中,以便在 React 应用程序的其他组件中重用它们,从而大幅降低组件的认知复杂性。你的代码将看起来更简洁,并且遵循单一职责原则 (SRP),该原则规定每个类或函数(或在我们的例子中是组件)应该负责程序功能的单一部分,并且应该封装该部分。componentWillUnmountuseStateuseEffect

说得够多了,让我们开始工作并实现我们的第一个自定义钩子:useBoolean!😎

动机

首先,我们为什么要实现这样一个钩子?我们先来看看这个简单的组件:



const Spoil = ({ content }) => {
  const [showSpoil, setShowSpoil] = useState(false);

  return (
    <div className="spoil">
      <button onClick={() => setShowSpoil((visible) => !visible)}>
        {showSpoil ? "Hide" : "Show"}
      </button>
      {showSpoil && <div className="spoil-content">{content}</div>}
    </div>
  );
};


Enter fullscreen mode Exit fullscreen mode

该组件接收一个contentprop,该 prop 仅在按钮被点击时出现,用于显示损坏内容。当然,再次点击按钮会将其隐藏,依此类推。

这里的组件非常简单,很容易阅读,但是我们可以通过将按钮onClick监听器提取到单独的函数来提高它的可读性:



const Spoil = ({ content }) => {
  const [showSpoil, setShowSpoil] = useState(false);

  const toggle = () => setShowSpoil((visible) => !visible)

  return (
    <div className="spoil">
      <button onClick={toggle}>
        {showSpoil ? "Hide" : "Show"}
      </button>
      {showSpoil && <div className="spoil-content">{content}</div>}
    </div>
  );
};


Enter fullscreen mode Exit fullscreen mode

这样就好多了。我们简化了函数的返回值,但在状态初始化和返回语句之间添加了一行。当然,这在我们的例子中不是什么大问题,但在处理更复杂的组件时,这可能会导致函数声明冗余。

事实上,如果我们有一个useBoolean钩子,我们的组件可以进一步简化,我们可以像这样使用:



const Spoil = ({ content }) => {
  const [showSpoil, setShowSpoil] = useBoolean(false);

  return (
    <div className="spoil">
      <button onClick={setShowSpoil.toggle}>
        {showSpoil ? "Hide" : "Show"}
      </button>
      {showSpoil && <div className="spoil-content">{content}</div>}
    </div>
  );
};


Enter fullscreen mode Exit fullscreen mode

看到了吗?我们没有添加任何额外的函数,onClick监听器也更容易阅读了。现在,我们开始实现这个简单的钩子吧?😎

执行

首先,我们定义一个可以使用useState钩子的函数。



const useBoolean = (initialValue) => {
    const [value, setValue] = useState(initialValue)

    return [value, setValue]
}


Enter fullscreen mode Exit fullscreen mode

⚠️ 注意:您只能useBoolean在 React 组件中使用该函数(或者我应该说钩子),因为它使用了useState钩子。

到目前为止,我们刚刚为useState钩子创建了一个别名。

不太有用...😅

现在有趣的部分来了:我们不会在返回数组中使用函数,而是setValue使用包含 3 种方法的对象:

  • toggle()切换值
  • on()将值设置为true
  • off()将值设置为false

我们的钩子现在看起来像这样:



const useBoolean = (initialValue) => {
    const [value, setValue] = useState(initialValue)

    const updateValue = useRef({
        toggle: () => setValue(oldValue => !oldValue),
        on: () => setValue(true),
        off: () => setValue(false)
    })

    return [value, updateValue.current]
}


Enter fullscreen mode Exit fullscreen mode

就这样,你刚刚创建了你的第一个自定义钩子,恭喜!🥳

用法



const Articles = () => {
  const [articles, setArticles] = useState([])
    const [isLoading, setIsLoading] = useBoolean(false)
    const [isError, setIsError] = useBoolean(false)

    useEffect(() => {
        setIsLoading.on()
        fetch(...)
            .then(res => res.json())
            .then(setArticles)
            .catch(setIsError.on)
            .finally(setIsLoading.off)
  }, [])

    return ...
}


Enter fullscreen mode Exit fullscreen mode

⚠️ 注意:您不能使用,setIsLoading(true)因为我们不再导出函数而是导出对象。

看看上面的代码片段,是不是非常容易阅读?😎

结论

感谢阅读。希望你喜欢这篇文章,如果喜欢的话,欢迎看看我的其他文章。另外,如果你有任何问题,或者只是想打个招呼,也欢迎留言评论。👋


支持我

如果您希望支持我,您可以通过以下链接给我买杯咖啡(然后我可能会将那杯咖啡变成一个新的自定义钩子……☕)

给我买杯咖啡


参考

https://reactjs.org/docs/hooks-overview.html

https://en.wikipedia.org/wiki/Single-responsibility_principle

文章来源:https://dev.to/iamludal/react-custom-hooks-useboolean-3m6c
PREV
使用 React Testing Library 和 Jest 开始测试 React Apps 的 8 个简单步骤
NEXT
理解回调 理解回调