自定义 React Hooks:useBoolean
React Hooks 最初允许你“钩住” React 的状态和生命周期功能,就像我们以前使用基于类的组件时使用componentDidMount
或方法一样。在本文中,我们将发现,我们可以使用 React 提供的几个基本 Hooks(例如和)来实现我们自己的自定义 Hooks。这样,你可以将一些逻辑转移到函数中,以便在 React 应用程序的其他组件中重用它们,从而大幅降低组件的认知复杂性。你的代码将看起来更简洁,并且遵循单一职责原则 (SRP),该原则规定每个类或函数(或在我们的例子中是组件)应该负责程序功能的单一部分,并且应该封装该部分。componentWillUnmount
useState
useEffect
说得够多了,让我们开始工作并实现我们的第一个自定义钩子: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>
);
};
该组件接收一个content
prop,该 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>
);
};
这样就好多了。我们简化了函数的返回值,但在状态初始化和返回语句之间添加了一行。当然,这在我们的例子中不是什么大问题,但在处理更复杂的组件时,这可能会导致函数声明冗余。
事实上,如果我们有一个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>
);
};
看到了吗?我们没有添加任何额外的函数,onClick
监听器也更容易阅读了。现在,我们开始实现这个简单的钩子吧?😎
执行
首先,我们定义一个可以使用useState
钩子的函数。
const useBoolean = (initialValue) => {
const [value, setValue] = useState(initialValue)
return [value, setValue]
}
⚠️ 注意:您只能
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]
}
就这样,你刚刚创建了你的第一个自定义钩子,恭喜!🥳
用法
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 ...
}
⚠️ 注意:您不能使用,
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