Redux 入门级教学文档

mac2026-09-22  12

Redux 入门级教学文档

Redux 入门级教程文档一、概念说明1、什么是 Redux, 为什么要使用 Redux2、为什么要使用 Redux 二、环境搭建1、安装2、概念简单说明3、目录结构 三、搭建数据源四、编写页面1、创建仓库2、展示页面3、修改仓库数据 五、编写 action六、中间件-异步1、代码操作(第2点是知识点讲解,小伙伴们要看哈)2、知识点3、补充 记得双击么么哒~

Redux 入门级教程文档

在这里我将用最浅显易懂的语言给小伙伴们解释一下 Redux, 并且一步步的教大家如何使用 Redux。

一、概念说明

1、什么是 Redux, 为什么要使用 Redux

官网说明:Redux 是 JavaScript 状态容器,提供可预测化的状态管理。

什么意思呢?就是说随着页面复杂化,页面上的很多数据需要保存,若路由跳转后,前一个页面的数据被销毁会导致数据的丢失。

若通过 url 传递,十分的麻烦,且要将每个数据传入组件中,写起来也是十分的无脑浪费时间。

2、为什么要使用 Redux

如果有个仓库用来保存整个项目中需要被保留的数据,且组件中可以直接拿到仓库的数据。那么这些数据将时刻保持一致,且清晰。

二、环境搭建

1、安装

首先我们先用 create-react-app 创建一个 react 项目。

create-react-app redux-text,

安装 redux:

npm install --save redux 或者 yarn add redux

npm install --save react-redux 或者 yarn add react-redux

2、概念简单说明

这里有几个概念需要大家先稍微知道以下:

store: 我们存放整个项目的一个仓库,一个项目只能有一个仓库,用来存放需要保存的数据。

state: store 中保存的数据。

action: 用户在页面上的操作是修改不到 store 里的 state。页面上的 view 要发生变化,就要在页面上通过 action,去告诉 state 你要变化了。注意:这里的 action 只是告诉仓库的数据要变化了,而不是去变化数据!!

reducer: 接收 action 的请求,执行修改 store 里的 state 的变化。

3、目录结构

接下来我们来创建几个项目中需要用到的文件夹和文件,以下是目录结构:

. ├── .gitignore ├── README.md ├── src │ └── action │ ├── oneAction.js │ ├── twoAction.js │ └── components │ └── container │ ├── pageOne | ├──index.js │ └── reducer │ ├── oneReducer.js │ ├── twoReducer.js │ ├── index.js │ └── App.css │ └── App.js │ └── ..... ├── node_modules ├── package.json ├── public

三、搭建数据源

创建两个数据源:

src/reducer/oneReducer.js 和 src/reducer/twoReducer.js

const oneReducer = ( state = { name: '航航', address: '福州' }, action ) => { switch(action.type) { case 'setName': return { ...state, name: action.payload.name } default: return state; } } export default oneReducer;

这里的纯函数 oneReducer(state, action) 的两个参数,分别代表了 store 下, 名为 oneReducer 的 state 和 action。

state: 存放了 oneReducer 下的所有数据源和初始值。

action: 通过不同的 action.type 去执行不同的操作,修改 state 数据

注意:每次修改 state, redux 并不是去修改原来的 state,而是返回一个新的 state, 用新的 state, 去替换旧的 state。

当 action.type 为 setName 时,我们先将原先的 state 解构出来,并给 name 附上新值。

twoReducer.js 也是如此:

const twoReducer = ( state = { age: 10, }, action ) => { switch(action.type) { case 'setAge': return { ...state, age: 11, } default: return state; } } export default twoReducer;

最后一步,整合所有的 reducer

import { combineReducers } from 'redux'; import OneReducer from './oneReducer'; import TwoReducer from './twoReducer'; export default combineReducers({ OneReducer, TwoReducer, })

combineReducers: 将所有的子 reducer 函数组成对象,提供一个新的 Reducer 函数

四、编写页面

我们写一个简单的页面,将两个数据源的数据都展示出来。

1、创建仓库

打开 src/index.js

import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import * as serviceWorker from './serviceWorker'; import PageOne from './container/pageOne'; import { createStore } from 'redux'; import { Provider } from 'react-redux'; import Reducer from './reducer'; const store = createStore(Reducer); ReactDOM.render( <Provider store={store}> <PageOne/> </Provider> , document.getElementById('root')); serviceWorker.unregister();

createStore: 创建仓库,用来存放 recuder 下的所有数据源。

Provider: redux 提供的一个组件,将 store 传递给其自组件。简单说就是在整个项目的最外层包上一个组件,放进一个 store, 这样就将 store 绑定进了项目中。

2、展示页面

那么现在我们来专注于页面 /src/container/pageOne/index.js 的编写:

import React from 'react'; import { connect } from 'react-redux'; class PageOne extends React.Component { render() { const { oneReducer, twoReducer } = this.props; const { name = '', address = '' } = oneReducer; const { age = 0 } = twoReducer; console.log(oneReducer, twoReducer); return ( <div> <div>name: {name}</div> <div>address: {address}</div> <div>age: {age}</div> </div> ) } } const mapStateToProps = state => { const { oneReducer, twoReducer } = state; return { oneReducer, twoReducer, } } export default connect(mapStateToProps)(PageOne);

细细讲解以下上面的知识点哈:

mapStateToProps: 获取 store 仓库下的数据源,这里可以打印以下 state, 看下输出。

connect: 由 React Redux 库提供的方法,将当前 Redux store state 映射到展示组件 props 中。

connect 做了性能优化,可以避免很多不必要的重复渲染,比如,当 state 数据变动时,不必编写 shouldComponentUpdate 方法来更新展示数据。

那么至此,仓库中的数据我们就可以通过 this.props 获取到。

3、修改仓库数据

store 的数据是无法被修改的,这个保证了数据的稳定性。所以 redux 抛出一个 store.dispatch(action) 的事件,提供用户修改 store 数据。

所以我们继续修改上面的 pageOne/index.js 页面(简写):

class PageOne extends React.Component { changeName = (val) => { this.props.dispatch({ type: 'setName', payload: { name: val } }) } render() { return ( <div> <div>name: {name}</div> <div>address: {address}</div> <div>age: {age}</div> <button onClick={ () => { this.changeName('change_name') }}>修改名字</button> </div> ) } }

现在去尝试以下执行按钮点击事件吧。

好了,那么至此一个状态管理的操作就完成了。细心的小伙伴会发现 action 好像没有用到?

那么这个 action 到底是做什么的?

在我理解,就是把 dispatch 中的内容放到 action 中。

五、编写 action

编写 src/action/oneAction.js

export const setName = (name) => ({ type: 'setName', payload: { name, } }) export const setAge = (age) => ({ type: 'setAge', age })

修改下 pageOne/index.js 页面(简写):

import { setName } from '../../action/oneAction'; class PageOne extends React.Component { changeName = (val) => { this.props.dispatch(setName(val)) } ... }

执行以下操作是不是发现也可以呢?那么为什么我们还要来编写 action 呢?

在我理解:是为了更加注重 MVC 的模式,View 就应该注重 View 的展示逻辑,所以与 UI 无关的逻辑操作就交给 redux 来处理,体现代码分层、职责分离的编程思想。

六、中间件-异步

1、代码操作(第2点是知识点讲解,小伙伴们要看哈)

由于很多时候执行dispatch并不仅仅是立即去更新reducer,这时需要执行其他函数来满足项目需求,这些函数就是中间件,最后执行过一系列中间件后再去执行reducer

如果我们调取服务端的接口,存在时间的延迟;或者说我想在 reducer 中也去调取其他 reducer 的操作,行不行?

我们来实验一下:

我们 oneAction.js 文件中再增加一个方法:

export const allChange = () => dispatch => { dispatch(setName('all_hang')); dispatch(setAge(10010)); }

pageOne.js 页面上增加一个点击事件(简写):

import { setName, allChange } from '../../action/oneAction'; class PageOne extends React.Component { changeAll = () => { this.props.dispatch(allChange()) } render() { return ( ... <div> <button onClick={ () => { this.changeAll() }}>修改全部</button> </div> ... ) } }

当我们点击按钮就发现报错了。看下 console 的报错信息: Use custom middleware for async actions. 翻译过来的意思是:使用自定义中间件进行异步操作。

说明在 reducer 中调用别的 reducer 的方法是可以的,但是因为我们缺少中间件,所以执行报错,现在我们来把中间件加上:

修改代码前我们要编辑 cli,新增一条命令

yarn add redux-thunk 或 npm install --save redux-thunk 导入 redux-thunk 库。

编辑 src/index.js(简写):

以下为简写代码,页面上原先的内容不删除,只是新增了几行代码和修改了 createStore

import { createStore, applyMiddleware } from 'redux'; import thunkMiddleware from 'redux-thunk'; const store = createStore( Reducer, applyMiddleware( thunkMiddleware ) ); ... ...

那么现在去执行以下 allChange() 事件看看效果,是不是发现页面不报错了,且 name 和 age 的数据也已经做了修改。

2、知识点

那么我们来讲解以下 applyMiddleware 和 thunkMiddleware

什么是 middleware:

在 redux 中 middleware 是 发送 action 和 action 到达 reducer 之间的第三方扩展,middleware 是架在 action 和 store 之间的一座桥梁。

applyMiddleware 可以看看官网的解释。

Middleware 可以让你包装 store 的 dispatch() 方法来达到你想要的目的。

3、补充

最后来一个补充:

如果你想每次 dispatch 都能够在 console 打印日志的话,手写会非常的繁琐。

那么 redux 也提供了这样一个中间件,帮助我们打印日志。

键入 yarn add redux-logger 或者 npm install --save redux-logger 来导入 redux-logger 库。

在 src/index.js 下加入以下代码:

import { createLogger } from 'redux-logger' const loggerMiddleware = createLogger() const store = createStore( Reducer, applyMiddleware( thunkMiddleware, loggerMiddleware ) );

好了,去尝试一下吧~

记得双击么么哒~

最新回复(0)