译 - React Native 教程 13 - React Hook状态管理 -无需Redux和Context
之前的教程 12 篇
今天,我们将对它进行探索,并开发一个自定义的Hook来管理全局状态--这是一个比Redux更容易使用的方法,而且比Context API更有性能。
钩子的基础知识
如果你已经熟悉React Hooks,你可以跳过这部分。
useState()
在Hooks之前,功能组件没有状态。现在,有了 "useState()",我们可以做到这一点。
它的工作原理是返回一个数组。上述数组的第一项是一个变量,它提供了对状态值的访问。第二项是一个函数,它更新组件的状态以反映DOM上的新值。
useEffect()
类组件使用生命周期方法管理副作用,如componentDidMount()
。useEffect()
函数可以让你在函数组件中执行副作用。
默认情况下,效果会在每次完成渲染后运行。但是,你可以选择只在某些值发生变化时才启动它,传递一个变量数组作为第二个可选参数。
为了得到和componentDidMount()
一样的结果,我们可以发送一个空数组。知道空数组永远不会改变,所以效果只会运行一次。
分享国家
我们可以看到,Hooks状态的工作原理和类组件状态完全一样。组件的每个实例都有自己的状态。
为了工作在组件之间共享状态的解决方案,我们将创建一个自定义的Hook。
我们的想法是创建一个监听器数组和唯一一个状态对象。每当一个组件改变状态时,所有被订阅的组件都会被触发setState()
函数并得到更新。
我们可以通过在我们的自定义Hook里面调用useState()
来实现。但是,我们不返回setState()
函数,而是将其添加到一个监听器数组中,并返回一个更新状态对象和运行所有监听器函数的函数。
等等,这不是应该让我的生活更轻松吗?
是的,我创建了一个NPM包,封装了所有这些逻辑。
[
use-global-hook
在不到1kb的范围内使用钩子对react进行简单的状态管理。
www.npmjs.com
你不需要在每个项目中重写这个自定义钩子。如果你只是想跳过并使用最终的解决方案,你可以通过运行以下命令轻松地将其添加到你的项目中。
npm install -s use-global-hook。
你可以通过软件包文档中的例子来学习如何使用它。但是,从现在开始,我们将重点介绍它的工作原理。
第一版 要在一个组件上使用它。
第一个版本已经可以共享状态。你可以在你的应用程序中添加任意多的Counter组件,并且它将拥有相同的全局状态。
但我们可以做得更好。在第一个版本中我不喜欢的地方。
- 我想在组件卸载时从数组中移除监听器。
- 我想让它更通用,这样我们就可以在其他项目中使用。
- 我想通过参数设置一个 "initialState"。
- 我想使用更多面向功能的编程。
在组件卸载前调用一个函数。
我们了解到,用空数组调用 "useEffect(function,[])",与 "componentDidMount() "有相同的用途。但是,如果在第一个参数中使用的函数返回另一个函数,那么这个第二个函数将在组件被卸载之前被启动。和componentWillUnmount()
完全一样。
这是将组件从监听器数组中移除的最佳位置。
第二版
除了这最后的修改,我们还将。
- 将React设置为参数,不再导入它。
- 不导出customHook,而是导出一个函数,根据
initialState
参数返回一个新的customHook。 - 创建一个 "store "对象,其中包含 "state "值和 "setState() "函数。
- 替换
setState()
和useCustom()
中的箭头函数为常规函数,这样我们就可以有一个上下文来将store
绑定到this
。
因为我们现在有了一个比较通用的Hook,所以我们要在store文件中设置它。
将行动与组件分开
如果你曾经使用过复杂的状态管理库,你就会知道直接从组件中操作全局状态不是最好的主意。
最好的方法是通过创建操纵状态的动作来分离业务逻辑。出于这个原因,我希望我们解决方案的最后一个版本不给组件访问setState()
函数,而是给一组动作。
为了解决这个问题,我们的useGlobalHook(React, initialState, actions)
函数将接收一个action
对象作为第三个参数。关于这一点,我想补充一些东西。
- Actions将可以访问
store
对象。因此,动作可以通过store.state
读取状态,通过store.setState()
写入状态,甚至使用state.actions
调用其他动作。 - 对于组织,动作对象可以包含其他动作的子对象。因此,你可能有一个
actions.addToCounter(a amount)
或者一个包含所有计数器动作的子对象,用actions.counter.add(a amount)
调用。
最终版本
以下文件是NPM包use-global-hook
中的实际文件。
使用实例
你再也不需要去碰 "useGlobalHook.js "了。你现在可以专注于你的应用程序了。这里有两个例子说明如何在实际生活中使用它。
几个计数器,一个值
只要你想添加多少个计数器,它都会共享同一个全局值。每当一个计数器在全局值上加1时,所有的计数器都会呈现。父组件将不需要再次渲染。
点击 "在编辑器中打开",在新的标签页中查看代码。
异步ajax请求
通过用户名搜索GitHub仓库。用async/await异步处理ajax请求。在每次搜索时更新请求计数器。
点击 "在编辑器中打开",在新标签页中查看代码。
这就是我们的成果
我们自己的状态管理库与React Hooks!
更新--2019年9月
在0.1.10版本中,我们在库中增加了一个重要的功能。现在我们可以在使用全局状态之前映射一个子集。这将避免每次全局状态变化时不必要的渲染。
在下面的例子中,我们在全局状态上有2个计数器:计数器A和计数器B。当你向counterA添加值时,counterB组件将不会重新渲染,反之亦然。
试试添加10.000个counterB组件的按钮。这将使更新counterB的值变得非常慢,但更新counterA会继续快速。
以上是 译 - React Native 教程 13 - React Hook状态管理 -无需Redux和Context 的全部内容, 来源链接: utcz.com/a/40457.html