我认为您首先需要了解的是 Redux 循环,它是这样的:
Action Creator->Action->dispatch->Reducers->State
Action Creator 是一个函数,它将返回一个称为 Action 的纯 JavaScript 对象。该操作将有一个type
和payload
,它提供了它正在做什么的上下文,例如,创建一个保险单,它看起来像这样:
// People dropping off a form (Action Creator)
const createPolicy = (name, amount) => {
return { // Action(a form in this analogy)
type: 'CREATE_POLICY',
payload: {
name: name,
amount: amount
}
};
};
所有动作创建者看起来都与您在此处看到的相同,但有一些小的变化。
但我知道问题在于理解循环及其目的,而不是语法。
所以你想了解你的动作创建者需要在你的 React 应用程序中扮演什么角色,然后到你的 Reducer 并弄清楚他们的角色,但真正在你弄清楚了最难的部分之后,动作创建者,其余的开始下降到位。
接收动作并将其dispatch
分派给所有不同的Reducers
. dispatch 是 Redux 库本身的一部分,所以你不需要把它写出来,你的问题是mapStateToProps
如果你使用 helper 将它与更高阶的组件联系起来connect()
,整个过程就像手动覆盖调度过程。
Reducers 背后的想法是我们写出函数,每个函数都在应用程序内部建模不同的行为。每个reducer 都被一个Action 调用,reducer 检查该action 并根据该action 确定是否修改行为。
因此,行动创建者就像是提出保险索赔的人,而行动就是实际索赔。这些索赔转到这些不同的部门,称为减速器。
因此,按照保险索赔的类比,我可能想要创建的减速器将是一个索赔历史减速器,如下所示:
// Reducers (Departments)
const claimsHistory = (oldListOfClaims, action) => {
};
因此,reducers 的工作是确定它是否关心它正在接收的操作类型。如果是,type
createClaim
那么我们要确保函数内的代码提取有效负载属性并将其添加到声明列表中,如果不是,则返回声明列表不变,看起来像这样:
// Reducers (Departments)
const claimsHistory = (oldListOfClaims, action) => {
if(action.type === 'CREATE_CLAIM') {
// we care about the action (claim)
return [...oldListOfClaims, action.payload]
}
// we dont care about the action (form)
};
所以我只是使用 ES2015 语法,它接受一个数组,获取所有记录并将它们添加到一个全新的数组中,然后添加action.payload
.
它相当于做const numbers = [1,2,3]
然后[...numbers, 4]
输出:
(4) [1, 2, 3, 4]
或者相当于,oldListOfClaims.push(action.payload);
但这个和我使用的有明显的区别。
在我用于 reducer 的语法中,我正在创建一个全新的数组并向其中添加记录,而该push()
方法正在修改现有数组。
我们总是希望避免修改 reducer 中现有的数据结构。你永远不会看到push()
减速器的内部。
然后是我们不关心动作的情况:
// Reducers (Departments)
const claimsHistory = (oldListOfClaims, action) => {
if(action.type === 'CREATE_CLAIM') {
// we care about the action (claim)
return [...oldListOfClaims, action.payload]
}
// we dont care about the action (form)
return oldListOfClaims;
};
接下来,您需要处理第一次调用 reducer 时没有数据传递给它的情况。我们基本上会收到 的值undefined
。我们需要默认第一个参数的值。
// Reducers (Departments)
const claimsHistory = (oldListOfClaims = [], action) => {
if(action.type === 'CREATE_CLAIM') {
// we care about the action (claim)
return [...oldListOfClaims, action.payload]
}
// we dont care about the action (form)
return oldListOfClaims;
};
所以undefined
被一个空数组替换。
因此,在实现 Redux 以及随之而来的细粒度规则(例如确保不修改传入的数组并确保始终返回一些值)时,弄清楚你的操作和 reducer 是困难的部分。
reducer 的总体目标是将一些现有数据作为操作传递给它,并根据操作的内容查找并返回现有数据。
所以这是让你开始的所有基线内容。在所有这些中,您想要返回一个 Redux 存储的新实例。
根据您的项目,您可能有 1 到 3 个或更多动作创建者和缩减者。然后,您将所有这些连接到一个名为 store 的对象中,该对象只是不同 action 和 reducer 的组合。
因此,在您的组件中的某个地方,您将添加如下内容:const { createStore, combineReducer } = Redux;
这是你的combineReducers
样子:
const ourDepartments = combineReducers({
accounting: accounting,
claimsHistory: claimsHistory,
policies: policies
});
然后您完成创建商店,如下所示:
const store = createStore(ourDepartments);
store;
store
代表整个 Redux 应用程序。它包含对所有不同减速器的引用以及对这些减速器或数据产生的所有状态的引用。
该store
对象具有一些有用的功能,例如dispatch
函数。为了调用dispatch()
,我们必须传入由动作创建者创建的动作,然后将其传递给store.dispatch()
.
const store = createStore(ourDepartments);
const action = createPolicy('Alejandra', 35);
console.log(action);
store.dispatch();
当您控制台注销时,action
您应该看到您具有操作类型和有效负载:
{type: "CREATE_POLICY", payload: {…}}
然后您采取该行动并将其传递给store.dispatch()
这样的:
到目前为止,您可能看到了一个错误,指出 Action 必须是一个普通的 JavaScript 对象等等,一旦您像这样传递 action,这个错误就会消失:
store.dispatch(action);
您可以检查以查看应用程序的打印状态,如下所示:
console.log(store.getState());
{accounting: 135, claimHistory: Array(0), policies: Array(1)} accounting: 135 claimHistory: [] policies: ["Alejandra"]
proto : Object
现在您可以开始传递如下操作:
store.dispatch(createPolicy('Alejandra', 35));
store.dispatch(createPolicy('Ben', 20));
store.dispatch(createPolicy('Daniel', 78));
store.dispatch(createClaim('Alejandra', 120));
store.dispatch(createClaim('Ben', 50));
store.dispatch(deletePolicy('Daniel'));
console.log(store.getState());
控制台输出:
{accounting: 63, claimHistory: Array(2), policies: Array(2)} accounting: 63 claimHistory: Array(2) 0: {name: "Alejandra", amountOfMoneyToCollect: 120} 1: {name: "Ben", amountOfMoneyToCollect:50} 长度:2
proto:Array(0) 策略:Array(2) 0:“Alejandra”1:“Ben”长度:2
proto:Array(0)
proto:对象
这就是 Redux 库的工作方式
好的,所以我向您展示了它是如何独立工作的,但是 Redux 和 React 这两个库如何相互交互?
所以是的,随着 Redux 的实现,我们使用组件级状态的频率要低得多。我们通常将所有数据存储在 Redux 中。
在某些情况下,我们希望在 Redux 和 React 组件中都有状态,但一般来说,你在 React 应用程序中的所有状态现在都在 Redux 中,这样可以转化为更简单的 React 应用程序。
假设你有一些 iTunes 类型的应用程序,我们如何将它与 Reactjs 组合在一起?
所以这将是你没有 redux 的应用程序:

所以在这里你SongDetail
只需要知道你当前选择的歌曲是什么。因此,您的App
组件将其SongDetail
作为道具传递给它,然后SongDetail
将其渲染到屏幕上。
单独使用 React,这将是一个简单直接的应用程序。
那么您的应用程序如何使用 Redux 进行更改?

所以就像之前一样,我们将有一个App
组件 a SongList
and SongDetail
,但是该App
组件将传递很少的信息到SongList
and SongDetail
。
相反,我们将把这些创建歌曲列表和选择歌曲以及当前选择的歌曲是什么的想法抽象到 redux 应用程序中。
因此,您将拥有一个生成歌曲列表的reducer 和一个记录当前选定歌曲的reducer。这些是您的应用程序中的两个状态。
最后,我们将确保我们有一个动作创建者来以某种方式改变你的状态。这是您在 redux 应用程序中更改状态的唯一方法。
所以你的动作创建者可能被称为选择歌曲,它将调度一个动作并告诉选定的歌曲reducer更新它的数据并反映新的当前选择的歌曲。
这就是你使用 Redux 的应用程序。