小程序 redux
This article is about how to think in Redux. We’ll try to understand how we can utilise this wonderful library to make our application more stable, robust, and maintainable. It is language agnostic, however we will keep our scope to Redux with React.
本文是关于在Redux中的思考方式。 我们将尝试了解如何利用这个奇妙的库来使我们的应用程序更加稳定,健壮和可维护。 它与语言无关,但是我们将使用React将我们的范围限制在Redux上。
For those who haven’t used Redux before, I will quote from the docs:
对于以前从未使用过Redux的人,我将引用docs中的内容 :
Redux is a predictable state container for JavaScript apps.
Redux是JavaScript应用程序的可预测状态容器。
It is only a 2kb library that solves one of the biggest problems in maintaining large JavaScript apps: state management.
它只是一个2kb的库,可以解决维护大型JavaScript应用程序时遇到的最大问题之一:状态管理。
This article is not about Redux, as there are plenty of articles about it already. Rather, it is about how we should visualise a Redux app and use it effectively.
本文与Redux无关,因为已经有很多关于Redux的文章。 而是关于我们如何可视化Redux应用并有效使用它。
Let’s say we are building an e-commerce application where it has some basic pages like catalog, product details, and payment success.
假设我们正在构建一个电子商务应用程序,其中包含一些基本页面,例如目录,产品详细信息和付款成功。
Below are the wireframes of how the app would look:
以下是该应用外观的线框图:
So architecting in Redux means that we have to visualise the application as one entity, and each page is a sub-entity.
因此,在Redux中进行架构设计意味着我们必须将应用程序可视化为一个实体,并且每个页面都是一个子实体。
There are four stages to building a Redux app:
构建Redux应用程序分为四个阶段:
- Visualise the state tree 可视化状态树
- Design your reducers 设计减速机
- Implement Actions 实施行动
- Implement Presentation 实施演示
步骤1:可视化状态树 (Step 1: Visualise state tree)
From the wireframes above, let’s design our state tree.
从上面的线框开始,让我们设计状态树。
This is the most important step. After we are done visualising our state tree, implementing Redux techniques becomes really easy! Dotted circles are states that will be shared by the application, solid circles are page-specific states.
这是最重要的步骤。 完成状态树的可视化之后,实现Redux技术变得非常容易! 虚线圆圈是应用程序将共享的状态,实心圆圈是页面特定的状态。
步骤2:设计减速机 (Step 2: Design your reducers)
In case you are wondering what exactly a reducer is, I will quote directly from the docs:
如果您想知道什么是reducer,我将直接从文档中引用:
Reducers specify how the application’s state changes in response to actions sent to the store. Remember that actions only describe what happened, but don’t describe how the application’s state changes.
精简器指定应用程序的状态如何响应发送到商店的操作而改变。 请记住,动作仅描述发生了什么 ,而没有描述应用程序状态如何变化。
Each of the states that are important can have their own reducers. Later, we can combine them in one root reducer which will eventually define the store (the single source of truth of the application). This is where the real power comes in: you have total control over your states and their behaviour. Nothing goes unwatched by the store. The silent observer keeps watch.
每个重要的州都可以拥有自己的减速器。 稍后,我们可以将它们组合到一个根缩减器中,该缩减器最终将定义存储(应用程序真相的唯一来源)。 这才是真正的力量所在:您可以完全控制自己的州及其行为。 商店没有什么不注意的。 沉默的观察者一直在监视。
Let’s check out an example of how to design a reducer with the help of the application state tree that we designed above.
让我们看一下如何借助上面设计的应用程序状态树设计减速器的示例。
The root reducer says it all. It contains everything the store needs to know about the application.
根减速器说明了一切。 它包含商店需要了解的有关应用程序的所有信息。
Now let’s look at how a sub entity headerReducer looks.
现在让我们看一下子实体headerReducer的外观。
Remember how we designed our header state?
还记得我们如何设计标题状态吗?
// Header Reducer
const headerReducer = combineReducer({
menu: menuReducer,
search: searchReducer,
location: locationReducer
});
Our reducer is a replica of what we designed earlier in our state tree. This is the power of visualisation.
减速器是我们先前在状态树中设计的副本。 这就是可视化的力量。
Notice how a reducer contains more reducers. We don’t need to create one huge reducer. It can be easily broken into smaller reducers, as each holds its individual identities and has its own specific operations. This helps us create separation of logic, which is very important for maintaining large apps.
注意减速器如何包含更多的减速器。 我们不需要创建一个巨大的减速器。 它可以很容易地分解成较小的减速器,因为每个减速器都具有自己的身份并具有自己的特定操作。 这有助于我们创建逻辑分离,这对于维护大型应用程序非常重要。
Now let’s understand how a typical reducer file should be set up, for example searchReducer.
现在,让我们了解如何设置典型的reducer文件,例如searchReducer。
// Search Reducer
const initialState = { payload: [], isLoading: false, error: {}};
export function searchReducer( state=initialState, action ) {
switch(action.type) {
case FETCH_SEARCH_DATA:
return {
...state,
isLoading: true
};
case FETCH_SEARCH_SUCCESS:
return {
...state,
payload: action.payload,
isLoading: false
};
case FETCH_SEARCH_FAILURE:
return {
...state,
error: action.error,
isLoading: false
};
case RESET_SEARCH_DATA:
return { ...state, ...initialState }
default: return state;
}
}
This reducer pattern defines the changes possible in its search state when the search API is called.
减速器模式定义了在调用搜索API时其搜索状态可能发生的变化。
FETCH_SEARCH_DATA, FETCH_SEARCH_SUCCESS, FETCH_SEARCH_FAILURE, RESET_SEARCH_DATA
All the above are possible constants that define what possible actions can be performed.
以上所有都是可能的常数,它们定义了可以执行的可能动作 。
Note: It is important to maintain a RESET_SEARCH_DATA action, in case we need to reset data during the unmounting of a component.
注意:保持RESET_SEARCH_DATA操作非常重要,以防在卸载组件期间需要重置数据。
步骤3:执行动作 (Step 3: Implement Actions)
Every action that has API calls usually goes through three stages in an app.
具有API调用的每个操作通常在应用程序中经历三个阶段。
- Loading state -> FETCH_SEARCH_DATA 加载状态-> FETCH_SEARCH_DATA
- Success -> FETCH_SEARCH_SUCCESS 成功-> FETCH_SEARCH_SUCCESS
- Failure -> FETCH_SEARCH_FAILURE 失败-> FETCH_SEARCH_FAILURE
Maintaining these action types helps us check the data flow when an API is called in our app.
维护这些操作类型有助于我们在应用中调用API时检查数据流。
Let’s dive into the code to understand what a typical action will look like.
让我们深入研究代码以了解典型动作的外观。
export function fetchSearchData(args) {
return async (dispatch) => {
// Initiate loading state
dispatch({
type: FETCH_SEARCH_DATA
});
try {
// Call the API
const result = await fetchSearchData(
args.pageCount,
args.itemsPerPage
);
// Update payload in reducer on success
dispatch({
type: FETCH_SEARCH_SUCCESS,
payload: result,
currentPage: args.pageCount
});
} catch (err) {
// Update error in reducer on failure
dispatch({
type: FETCH_SEARCH_FAILURE,
error: err
});
}
};
}
Notice how the data flow is tracked by the store through actions. This holds each and every change in the app accountable.
注意商店如何通过动作来跟踪数据流。 这使应用程序中的每项更改都负责。
Thus similar actions are written for each change in reducers of various states.
因此,针对各种状态的减速器中的每次更改,将编写类似的动作。
One of the biggest benefits of Redux is the abstraction of each and every action.
Redux最大的好处之一就是每个动作的抽象。
步骤4:实施演示 (Step 4: Implement Presentation)
import React, { Component } from 'react';
import { connect } from 'react-redux';;
import fetchSearchData from './action/fetchSearchData';
import SearchData from './SearchData';
const Search = (props) => (
<SearchData
search={props.search}
fetchSearchData={props.fetchSearchData}
/>
);
const mapStateToProps = (state) => ({
search: state.header.search.payload
});
const mapDispatchToProps = { fetchSearchData};
export default connect(mapStateToProps, mapDispatchToProps)(Search)
As you can see, the presentation component is very simple and easy to understand.
如您所见,演示组件非常简单易懂。
结论 (Conclusion)
I would like to mention some of the biggest benefits that I found using Redux:
我想提一下使用Redux时发现的一些最大好处:
- It certainly reduces code smell. 它肯定会减少代码的气味。
- Abstraction of code is easier to achieve. 代码抽象更容易实现。
- Redux also introduces us to other principles like immutability, functional programming, and many others. Redux还向我们介绍了其他原理,例如不变性,函数式编程等。
- It allows you to visualise each and every action and track them with “time traveling.” 它使您可以可视化每个动作并通过“时间旅行”对其进行跟踪。
I hope this article helps you get a clearer picture of why Redux is truly awesome, and how we can utilise the power of visualisation to make maintainable applications.
我希望本文能帮助您更清晰地了解Redux为何如此出色,以及我们如何利用可视化功能来制作可维护的应用程序。
Follow me on twitter to get more updates regarding new articles and to stay updated in latest frontend developments. Also share this article on twitter to help others know about it. Sharing is caring ^_^.
在推特上关注我,以获取有关新文章的更多更新,并随时了解最新的前端开发。 也可以在Twitter上分享此文章,以帮助其他人了解它。 分享是关怀^ _ ^。
一些有用的资源 (Some helpful resources)
https://medium.com/@rajaraodv/a-guide-for-building-a-react-redux-crud-app-7fe0b8943d0f#.c4yhhvk0d
https://medium.com/@rajaraodv/a-guide-for-building-a-react-redux-crud-app-7fe0b8943d0f#.c4yhhvk0d
我以前的文章 (My previous articles)
https://medium.freecodecamp.org/how-to-use-redux-persist-when-migrating-your-states-a5dee16b5ead
https://medium.freecodecamp.org/how-to-use-redux-persist-when-migrating-your-states-a5dee16b5ead
https://codeburst.io/redux-observable-to-the-rescue-b27f07406cf2
https://codeburst.io/redux-observable-to-the-rescue-b27f07406cf2
https://codeburst.io/building-webapp-for-the-future-68d69054cbbd
https://codeburst.io/building-webapp-for-the-future-68d69054cbbd
https://codeburst.io/cors-story-of-requesting-twice-85219da7172d
https://codeburst.io/cors-story-of-requesting-twice-85219da7172d
翻译自: https://www.freecodecamp.org/news/the-best-way-to-architect-your-redux-app-ad9bd16c8e2d/
小程序 redux