React全家桶系列|【React 系列 01】?? 在工作中对于 Custom React Hooks 一些思考

当我刚接手 React 项目的时候,就对整体项目代码看了一遍,其中就有一个命名为 customer-hooks,打开一看,全都是命名为 usexxx 的 jsx 文件,后面了解到这是大佬们封装的自定义 hook。
于是,今天就自己来总结一下对于 Custom React Hooks 一些思考。
React全家桶系列|【React 系列 01】?? 在工作中对于 Custom React Hooks 一些思考
文章图片

自定义 Hook
以下来自 React 官网 关于自定义 Hook 的介绍:

与 React 组件不同的是,自定义 Hook 不需要具有特殊的标识。我们可以自由的决定它的参数是什么,以及它应该返回什么(如果需要的话)。换句话说,它就像一个正常的函数。但是它的名字应该始终以 use 开头,这样可以一眼看出其符合 Hook 的规则。
而对于 Hook 的规则:
  • 不要在循环,条件或嵌套函数中调用 Hook, 确保总是在你的 React 函数的最顶层以及任何 return 之前调用他们。
  • 只在 React 函数中调用 Hook
自定义 Hook 封装了一些逻辑代码,并能够把数据向下传递到渲染树的操作。
启动一个 react 项目
可以通过如下命令快速创建简单 react 应用,详细步骤可以参考官网。
npx create-react-app react-demo

简单的例子
下面编写我们自定义的 Hook,本人还是比较菜鸡,所以就拿阿里的 ahooks 官方文档 学习了,在 src 文件目录下创建如下目录结构,用来存放我们的自定义 hook。
React全家桶系列|【React 系列 01】?? 在工作中对于 Custom React Hooks 一些思考
文章图片

代码是来自于 ahooks github 仓库地址
PS:这里就不粘贴源码了,大家可以在上述地址拿到。
我们的父组件代码如下:
import SubApp from './subApp'; import useBoolean from './custom-hooks/useBoolean/index'; function App() {const [state, { toggle, setTrue, setFalse }] = useBoolean(true); return (
Effects:{ JSON.stringify(state)}

/>
) }export default App;

通过 npm start 启动项目,可以看到如下界面:
React全家桶系列|【React 系列 01】?? 在工作中对于 Custom React Hooks 一些思考
文章图片

可以看到,使用了自定义 Hook,我们会省去很多重复性的逻辑代码,在父子组件我们都可以使用自定义的 hook。
思考一
但是,我就有问题了,虽然自定义 hook 很香,但发现没有,当我们重新渲染的时候,这一整块逻辑代码也会跟着运行,如果它的运行可以忽略不计倒还好,但还是要考虑一下万一情况,比如你运行了很多个 hook 呢?
想了想,既然这个 useBoolean 是依赖于返回的 state,那么是不是可以通过 useMemo 来解决问题。
查看 ahooks 源码,果然,就有通过 useMemo 来处理的:
const actions = useMemo(() => {const reverseValueOrigin = (reverseValue =https://www.it610.com/article/== undefined ? !defaultValue : reverseValue) as D | R; // 切换返回值 const toggle = (value?: D | R) => {// 强制返回状态值,适用于点击操作 if (value !== undefined) {setState(value); return; } setState((s) => (s === defaultValue ? reverseValueOrigin : defaultValue)); }; // 设置默认值 const setLeft = () => setState(defaultValue); // 设置取反值 const setRight = () => setState(reverseValueOrigin); return {toggle, setLeft, setRight, }; }, [defaultValue, reverseValue]);

思考二
上述我是有父子组件,它们都调用了自定义 Hook ,那么我想的是它们会共享状态嘛,毕竟都是返回 state,那么假设我改了父组件的 state,那么子组件也会跟着变吗?
带着好奇心,我操作了一下界面,将父组件调用一下 toggle 方法,结果如下:
React全家桶系列|【React 系列 01】?? 在工作中对于 Custom React Hooks 一些思考
文章图片

在此基础上,我再调用一下父组件的 setTrue 方法试试,结果如下:
React全家桶系列|【React 系列 01】?? 在工作中对于 Custom React Hooks 一些思考
文章图片

发现,并不会因为多个组件调用同一个自定义 Hook 而共享状态。
来自 React 官网 的表述:
自定义 Hook 是一种重用状态逻辑的机制(例如设置为订阅并存储当前值),所以每次使用自定义 Hook 时,其中的所有 state 和副作用都是 完全隔离 的。
那么自定义 Hook 如何获取独立的 state?
每次调用 Hook,它都会获取独立的 state。由于我们直接调用了 useBoolean,从 React 的角度来看,我们的组件只是调用了 useState 和 useMemo。
我们可以在一个组件中多次调用 useState 和 useEffect等,它们是完全独立的。
那么,结合官方的说法,理解起来就容易多了,其实我们可以这样想,每次调用会返回一个新的实例,如下述我们使用 useBoolean 代码:
const [state, { toggle, setTrue, setFalse }] = useBoolean(true);

其实可以想象成返回新的实例,每个实例都会开一个新的空间存放,那么每个组件引用的那个实例都是完全独立开的,所以就不存在状态共享了,放心使用。
思考三
既然状态隔离了,我在想有啥办法能够共享状态呢?
我想有时候也得需要在组件之间共享状态的。
于是,我又翻了翻公司代码以及问了我导师,我发现居然使用了 context,那么,就得研究一下 context 的一些用法。
结尾
为了让文章少点废话,让大家在简短的时间内能够吸收知识,本篇内容就先到此了,下一篇我们将讲解 React Context 的一些使用方法,来解决上文的思考。
关于本文内容,也欢迎和大家交流讨论。
【React全家桶系列|【React 系列 01】?? 在工作中对于 Custom React Hooks 一些思考】我是【一百个Chocolate】,如果喜欢的话,可以给本文点个赞,我们下期再见啦~

    推荐阅读