欢迎参加Redux Essentials教程!本教程将向您介绍Redux,并教您如何使用我们最新推荐的工具和最佳实践正确使用Redux。完成后,您应该能够使用您在这里学到的工具和模式开始构建您自己的Redux应用程序了。
在本教程的第1部分中,我们将介绍使用Redux需要了解的关键概念和术语,而在第2部分中,我们将研究一个基本的Reaction+Redux应用程序,看看这些部分是如何组合在一起的。
从第3部分开始,我们将利用这些知识构建一个具有一些实际功能的小型社交媒体订阅源应用程序,看看这些功能在实践中是如何工作的,并讨论使用Redux的一些重要模式和指导原则。
本页面将重点向您展示如何正确使用Redux,并解释足够的概念,以便您能够理解如何正确构建Redux应用程序。
我们试着让这些解释适合初学者,但我们确实需要对你已经知道的做出一些假设:
如果您对这些主题还不太熟悉,我们鼓励您先花些时间熟悉它们,然后再回来了解Redux。当你准备好的时候,我们会在这里的!
您应该确保在浏览器中安装了Reaction和Redux DevTools扩展:
首先,它有助于理解这件事是什么。是干什么的呢?它帮助我解决了什么问题?我为什么要用它呢?
Redux是用于管理和更新应用程序状态的模式和库,它使用称为";Actions";的事件。它充当需要在整个应用程序中使用的状态的集中存储,其规则确保状态只能以可预测的方式更新。
Redux可帮助您管理应用程序许多部分所需的全局状态。
Redux提供的模式和工具使您更容易理解何时、何地、为什么以及如何更新应用程序中的状态,以及当这些更改发生时应用程序逻辑将如何运行。Redux将引导您编写可预测和可测试的代码,这有助于您确信您的应用程序将按预期工作。
Redux帮助您处理共享状态管理,但与任何工具一样,它也有权衡之处。有更多的概念需要学习,还有更多的代码需要编写。它还向您的代码添加了一些间接性,并要求您遵循某些限制。这是短期和长期生产力之间的权衡。
您在应用程序中的许多位置都需要大量的应用程序状态。
这个应用程序有一个中型或大型代码库,可能会有很多人使用。
并不是所有的应用都需要Redux。花点时间考虑一下你正在开发的应用程序类型,并决定哪些工具最能帮助解决你正在处理的问题。
Redux是一个小型的独立JS库。但是,它通常与其他几个软件包一起使用:
Redux可以与任何UI框架集成,并且最常与Reaction一起使用。Reaction-Redux是我们的官方软件包,它允许您的Reaction组件通过读取状态片段并调度操作来更新存储,从而与Redux存储进行交互。
Redux Toolkit是我们推荐的编写Redux逻辑的方法。它包含我们认为构建Redux应用程序所必需的软件包和函数。Redux Toolkit内置了我们建议的最佳实践,简化了大多数Redux任务,防止了常见错误,并使Redux应用程序的编写变得更容易。
Redux DevTools扩展显示Redux存储中状态随时间的变化历史记录。这允许您有效地调试您的应用程序,包括使用强大的技术,如时间旅行调试。
在我们深入了解一些实际代码之前,让我们先来谈谈使用Redux需要了解的一些术语和概念。
让我们从一个小的Reaction计数器组件开始。它跟踪处于组件状态的数字,并在单击按钮时递增该数字:
操作、基于用户输入在应用程序中发生的事件以及触发状态更新。
当发生某些事情(如用户单击按钮)时,会根据发生的情况更新状态。
但是,当我们有多个组件需要共享和使用相同的状态时,简单性可能会被破坏,特别是当这些组件位于应用程序的不同部分时。有时这可以通过将状态提升到父组件来解决,但这并不总是有帮助的。
解决此问题的一种方法是从组件中提取共享状态,并将其放入组件树外部的集中位置。这样,我们的组件树就变成了一个很大的视图,任何组件都可以访问状态或触发操作,无论它们在树中的什么位置!
通过定义和分离状态管理中涉及的概念,并实施维护视图和状态之间独立性的规则,我们使代码更具结构性和可维护性。
这是Redux背后的基本思想:在您的应用程序中包含全局状态的单个集中位置,以及在更新该状态以使代码可预测时要遵循的特定模式。
默认情况下,JavaScript对象和数组都是可变的。如果我创建一个对象,我可以更改其字段的内容。如果我创建一个数组,我还可以更改内容:
这称为改变对象或数组。它在内存中是相同的对象或数组引用,但现在对象内部的内容已更改。
为了不变地更新值,您的代码必须复制现有的对象/数组,然后修改这些副本。
我们可以使用JavaScript的数组/对象扩散操作符,以及返回数组的新副本而不是改变原始数组的数组方法手动完成此操作:
Redux希望所有状态更新都是一成不变的。稍后,我们将研究这一点在哪里以及如何重要,以及编写不可变的更新逻辑的一些更简单的方法。
在我们继续之前,您需要熟悉一些重要的Redux术语:
操作是具有类型字段的普通JavaScript对象。您可以将操作视为描述应用程序中发生的事情的事件。
类型字段应该是为该操作指定描述性名称的字符串,如";todos/todoAdded";。我们通常编写类似";domain/eventName";的类型字符串,其中第一部分是该操作所属的特性或类别,第二部分是发生的具体事件。
动作对象可以有其他字段,其中包含有关所发生事件的附加信息。按照惯例,我们将该信息放在一个名为Payload的字段中。
动作创建器是创建和返回动作对象的函数。我们通常使用这些,这样我们就不必每次都手动编写操作对象:
减法器是一个函数,它接收当前状态和操作对象,决定如何在必要时更新状态,并返回新状态:(state,action)=>;newstate。
它们应该仅根据state和action参数计算新的状态值。
不允许他们修改现有状态。相反,它们必须通过复制现有状态并更改复制的值来进行不可变的更新。
他们不能做任何异步逻辑,不能计算随机值,也不能引起其他副作用;
我们稍后将更多地讨论减速器的规则,包括为什么它们很重要以及如何正确遵循它们。
检查减少器是否关心此操作如果是,请复制状态,使用新值更新副本,然后将其返回。
这里有一个减速机的小例子,展示了每个减速机应该遵循的步骤:
还原器可以使用内部的任何类型的逻辑来决定新状态应该是什么:IF/ELSE、SWITCH、循环等等。
Array.Reduce()方法允许您获取一个值数组,一次处理数组中的每一项,然后返回一个最终结果。您可以将其视为";将数组减少到一个值";。
Array.duce()接受一个回调函数作为参数,该函数将为数组中的每一项调用一次。它需要两个论点:
回调第一次运行时,没有可用的previousResult,因此我们还需要传入一个初始值,该初始值将用作第一个previousResult。
如果我们想要将一组数字相加,以确定总数是多少,我们可以编写一个如下所示的Reduce回调:
请注意,此addNumber;Reduce回调函数本身不需要跟踪任何内容。它接受previousResult和currentItem参数,对它们执行一些操作,然后返回一个新的结果值。
Redux Reducer函数与这个";Reduce回调函数的概念完全相同!它接受";前一个结果";(状态)和";当前项";(操作对象),根据这些参数决定新的状态值,并返回该新状态。
如果我们要创建Redux操作的数组,调用Reduce(),然后传入一个Reducer函数,我们将以同样的方式获得最终结果:
我们可以说Redux Reducer将一组动作(随着时间的推移)减少到单一状态。不同之处在于,在Array.duce()中,它是一次性发生的,而在Redux中,它是在您运行的应用程序的整个生命周期中发生的。
该存储是通过传入减法器创建的,并且具有一个名为getState的方法,该方法返回当前状态值:
Redux存储有一个名为Dispatch的方法。更新状态的唯一方法是调用Store.Dispatch()并传入一个操作对象。存储将运行其Reducer函数并将新的状态值保存在内部,我们可以调用getState()来检索更新后的值:
您可以将调度操作视为在应用程序中触发事件。发生了一些事情,我们想让商店知道这件事。Reducer的作用类似于事件侦听器,当它们听到感兴趣的操作时,它们会更新状态作为响应。
选择器是知道如何从存储状态值中提取特定信息的函数。随着应用程序变大,这可以帮助避免重复逻辑,因为应用程序的不同部分需要读取相同的数据:
早些时候,我们谈到了单向数据流,它描述了更新应用程序的一系列步骤:
当发生某些事情(如用户单击按钮)时,会根据发生的情况更新状态。
初始设置:存储调用根减法器一次,并将返回值保存为其初始状态。
首次呈现UI时,UI组件将访问Redux存储的当前状态,并使用该数据来决定要呈现的内容。他们还订阅任何未来的商店更新,这样他们就可以知道状态是否发生了变化。
更新:存储使用以前的状态和当前操作再次运行Reducer函数,并将返回值保存为新状态。
存储通知订阅的UI的所有部分存储已更新。
每个需要来自存储区的数据的UI组件都会检查它们需要的状态部分是否已更改。
每个看到其数据已更改的组件都会强制使用新数据重新呈现,这样它就可以更新屏幕上显示的内容。
Redux确实有许多新的术语和概念需要记住。提醒一下,这里是我们刚刚报道的内容:
Redux使用单向数据流应用程序结构状态描述应用程序在某个时间点的状况,并根据该状态呈现UI。
Redux使用几种类型的代码操作是带有类型字段的纯对象,并在应用程序中描述发生了什么。
减法器是基于先前状态+操作计算新状态值的函数。
我们已经看过Redux应用程序的每一个单独部分。接下来,继续第2部分:Redux应用程序结构,在那里我们将查看一个完整的工作示例,看看这些部分是如何组合在一起的。