用 30 行代码编写自己的 Redux 版本,学习 Redux 基础知识
Redux 完成了什么?
Redux 的基本原理
哎呀,我应该理解这一切吗?
打造我们自己的 Redux
试运行
差不多就是这样
我最喜欢的学习某样东西工作原理的方法之一就是重新创建它。在这篇文章中,我们将通过创建一个简化版的 Redux 来学习它的基础知识。
如果您喜欢本教程,请给予💓、🦄或🔖并考虑:
📬 注册我的免费每周开发者简报
🎥 订阅我的免费 YouTube 开发者频道
Redux 完成了什么?
在深入探讨之前,了解 Redux 的功能至关重要。Redux 是一个状态管理库,它可以帮助您管理应用程序中的状态信息。“状态信息”只是对那些需要在应用程序使用过程中持久化并可用的信息的一种更贴切的说法。这些信息包括用户名,或者应用程序处于“浅色”模式还是“深色”模式。
当你的应用程序规模变大时,像 Redux 这样的状态管理库就变得尤为有用。很多人认为 Redux 是 React 的一部分,或者与 React 明确关联,但实际上它是一个独立的库,可以与 React 一起使用,也可以单独使用。
Redux 的基本原理
Redux 背后的基本理念是,将状态信息集中存放在一个位置,并可预测地更新状态。为了实现这一点,Redux 具有以下基本结构:
- 状态对象- 状态对象包含应用程序的状态信息。这些信息可能包括登录用户的姓名以及他们处于“亮”模式还是“暗”模式。
- Actions - Actions 是向 Redux 提供更新状态所需信息的对象。按照惯例,一个 action 对象可能包含一个
type
属性和一个payload
属性。如果你想将用户的名字设置为“Frankie”,你的 action 可能如下所示:{ action: "SET_USER_NAME", payload: "Frankie" }
- Reducer - Reducer 是函数。它们接受两个参数:1) 当前状态,2) 一个 action 对象(如上所述)。Reducer 使用 action 对象提供的信息以及当前版本的状态,返回一个新版本的状态。
- Store - Store 是一个对象,它允许你访问当前状态,并允许你分发操作来更新该状态。因此,Store 对象有两个属性,它们都是函数:
getState
和dispatch
。
哎呀,我应该理解这一切吗?
Redux 最大的诟病之一就是学习难度高,所以即使你完全没理解也完全没必要担心。随着我们实现自己的 Redux 精简版,这些概念应该会逐渐被理解。真正有帮助的是在实际环境中使用 Redux!
打造我们自己的 Redux
让我们开始编写自己的 Redux 吧!如果你之前用过 Redux,你就会知道,通常情况下,你需要store
使用createStore
库提供的函数来创建它。我们自己来写吧!
state
正如我上面提到的,我们的 store 需要允许我们使用函数访问对象getState
。它还必须允许我们执行dispatch
操作。让我们createStore
基于这些知识创建一个骨架函数。
function createStore() {
let state = {}; // Don't know what this is yet
function getState() {
return state;
}
function dispatch(action) {
// Set state based on the action
}
return { getState, dispatch };
}
这是一个很好的开始!让我们做一些改进。首先,我们并不总是希望我们的初始值state
是一个空对象{}
。相反,我们将createStore
接受一个名为的参数initialState
。
接下来,我们的dispatch
函数需要对action
传入的 进行一些处理,以便更新状态。reducer
如上所述, 满足了这一需求:
Reducer 是函数。它们接受两个参数:1)当前状态,2)一个 action 对象(如上所述)。Reducer 使用 action 对象中提供的信息以及当前版本的状态,返回一个新版本的状态。
因此,让我们将当前state
对象传递给 reducer,并将action
状态变量设置为等于返回值。
以下是我们实施的两项增强功能:
function createStore(reducer, initialState) {
let state = initialState;
function getState() {
return state;
}
function dispatch(action) {
state = reducer(state, action);
}
return { getState, dispatch };
}
这就是我们简化createStore
函数的全部内容!经验丰富的 Redux 用户可能会注意到,我们省略了 中的第三个参数createStore
。随着 Redux 的高级发展,这个参数会变得越来越重要,但出于核心原则,我们还是坚持使用前两个参数!
在使用我们的createStore
函数之前,我们需要一个reducer
。让我们创建一个可以设置用户名或设置显示模式(亮/暗)的 Reducer。
正如我们所讨论的,我们的reducer
函数采用当前state
和一个action
作为参数并返回状态的新版本。
function reducer(state, action) {
switch (action.type) {
case 'SET_USER_NAME':
return {
...state,
name: action.payload,
};
case 'SET_DISPLAY_MODE':
return {
...state,
displayMode: action.payload,
};
default:
return state;
}
}
让我们分析一下我们在这里所做的事情。
我们的函数reducer
接受一个state
参数和一个action
参数。我们有一个switch
语句,它会根据 的值返回不同的值action.type
(记得我们之前讨论过,按照惯例,我们的action
对象有一个type
和一个payload
)。
如果action.type
是"SET_USER_NAME"
,则返回状态的副本,但会name
用提供的 覆盖状态的键action.payload
。相反,如果action.type
是"SET_DISPLAY_MODE"
,则返回状态的副本,但会覆盖displayMode
键。如果action.type
不是这两个字符串之一,则直接返回未修改的状态。
这几乎就是我们所需要的一切,现在我们可以对我们自制的 Redux 进行测试运行了!
试运行
以下是我们自制 Redux 库的测试运行。详情请见内联注释。
// The createStore function we already wrote
function createStore(reducer, initialState) {
let state = initialState;
function getState() {
return state;
}
function dispatch(action) {
state = reducer(state, action);
}
return { getState, dispatch };
}
// The reducer we already wrote
function reducer(state, action) {
switch (action.type) {
case 'SET_USER_NAME':
return {
...state,
name: action.payload,
};
case 'SET_DISPLAY_MODE':
return {
...state,
displayMode: action.payload,
};
default:
return state;
}
}
// Create a new store! This will take our reducer
// and also an initial version of our state.
const initialState = { name: 'Guest', displayMode: 'light' };
const store = createStore(reducer, initialState);
// Change our user's name to "Frankie"
store.dispatch({
type: 'SET_USER_NAME',
payload: 'Frankie',
});
console.log(store.getState());
//{ name: "Frankie", displayMode: "light" }
// Change our display mode to "dark"
store.dispatch({
type: 'SET_DISPLAY_MODE',
payload: 'dark',
});
console.log(store.getState());
//{ name: "Frankie", displayMode: "dark" }
差不多就是这样
现在我们有了这个非常漂亮的store
对象,它可以完成我们想要的一切:
- 我们有一个集中的方式来访问我们的状态信息(通过调用
store.getState()
) - 我们有一种可重复、可预测的方式来通过分派动作(通过调用
store.dispatch(action)
)来更新我们的状态信息。
我希望你喜欢这篇关于 Redux 的介绍!
文章来源:https://dev.to/nas5w/learn-the-basics-of-redux-by-writing-your-own-version-in-30-lines-1if3