Redux流程分析 传统流程和redux-toolkit的使用

Posted 我是真的不会前端

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redux流程分析 传统流程和redux-toolkit的使用相关的知识,希望对你有一定的参考价值。

redux官方给的两种库

传统Redux流程写法

react-redux

Redux框架主要由Action、Reducer和Store三大元素组成。

action

Action是一个普通对象,其中存在的type属性是必须的,用来表示Action的名称,type一般被定义为普通的字符串常量。为了方便管理,一般通过action creator来创建action,action creator是一个返回action的函数。
在Redux中,State的变化会导致View的变化,而State状态的改变是通过接触View来触发具体的Action动作的,根据View触发产生的Action动作的不同,就会产生不同的State结果。可以定义一个函数来生成不同的Action,这个函数就被称为action creator。

Reducer

当Store收到action以后,必须返回一个新的State才能触发View的变化,State计算的过程即被称为Reducer。Reducer本质上是一个函数,它接受Action和当前State作为参数,并返回一个新的State。

  • 在子reducer中,一定要抛出一个reducer(实际上是一个由switch语句构成的函数)

Store

Store就是数据保存的地方,可以把它看成一个容器,整个应用中只能有一个Store。同时,Store还具有将Action和Reducers联系在一起的作用。Store具有以下的一些功能:
• 维持应用的 state;
• 提供getState()方法获取state;
• 提供dispatch(action)方法更新state;
• 通过subscribe(listener)注册监听器;
• 通过subscribe(listener)返回的函数注销监听器。
创建子store的方法

function reducer(initState,aciton)

流程(文字叙述)

createStore创建根store 一个store管理不同子store 合并子reducer使用方法combineReducers(),使用applyMiddleware可以处理中间件.想要多个中间件就可以使用compose
reducer 其本质上可以写成swith case 语句.
根据不同的case分支来修改子store(action=type,payload是信号,像一封邮件)
里面核心对原来state数据进行一次深复制 方法有很多种.
Object.assign jsonparse(jsonstringify)或者用immer等方法.

组件中 再app.jsx中安装react-redux库,使用<provider store></ provider>全局注入store上下文
如果在react16.8以前 只能使用connect(mapstate,mapdispatch)(component),然后在props上就能访问这些store数据\\以及修改store的action的内部方法.
在16.8以后 更推荐useDispatch useSelector

异步问题

使用compose(applyMiddleWare(thunk), applyMiddleWare(logger))使用中间件,尤其是解决redux不支持异步action的问题。

import  createStore, combineReducers, applyMiddleware, compose  from 'redux'
import thunk from 'redux-thunk'
import logger from 'redux-logger'
export default createStore(
  combineReducers(
    test,
    counter,
  ),
  // 当有多个中间件时
  compose(applyMiddleware(thunk), applyMiddleware(logger))
)

建议封装的地方

type字典

例如这种

封装action生成器方法

@reduxjs/toolkit的流程

toolkit比较好的支持typestript

  • 安装@reduxjs/toolkit这个库,使用configureStore(reducer,middleware)创建store。

  • createreducer创建初始值.其中参数是个build对象 .addcase就是你可以理解等同于添加case语句,每个case根据不同的action和不同的state 做不同事 抛出的reducer在store中使用

  • (1)name
    命名空间,可以自动的把每一个action进行独立,解决了action的type出现同名的文件。在使用的时候默认会把使用name/actionName

  • (2)initialState
    state数据的初始值

  • (3)reducers
    定义的action。由于内置了immutable插件,可以直接使用赋值的方式进行数据的改变,不需要每一次都返回一个新的state数据。

背后的深复制

createSlice方法创建一个slice。每一个slice里面包含了reducer和actions,可以实现模块化的封装。所有的相关操作都独立在一个文件中完成。
先看看源码 其是里面导入了immer

const testSlice = createSlice(
	name:"tset"  // 理解为命名空房间
	initialState,
	reducers: //里面放同步方法
	extraReducers:(builder)=>
		builder.addCase('',(state,action))                 //相当于添加了异步行为的switch语句,当达到状态后就执行回调,直接修改state.背后做了深复制操作
	 //放置由createAsyncThunk创建的异步行为 
)
.addCase('',(state))//链式语法回调函数

抛出举例

// 在子reducer中,一定要抛出一个reducer(实际上是一个由switch语句构成的函数)
export default userSlice.reducer  // 给根store进行合并reducer
export  login, getUserInfo, addUser, getUserList, changeUserStatus      // 给业务逻辑用的

createslice方法实际上是对createReducer方法的封装,并且实际解决了immer的深复制过程

  • 使用createSlice(name,initialState,reducers,extraReducers)创建子reducer,最后抛出子reducer给根store合并。

异步方法的添加

为啥能支持异步 先看看源码

背后其实还是用来thunk中间件

语法举例

const login:any = createAsyncThunk(
  'user/login',  // 其实就是action中的type(可以说是user子store中的login行为 写法不强制,但是讲究一点)
  async (data) =>   //异步行为 接收一个函数 
    const res:any = await fetchLogin(data) //等待异步行为的成功
    console.log('登录成功', res)
    localStorage.setItem('token', res.token)
    return res.token  // payload
  
)

使用该action

 extraReducers: (builder)=>
    // 监听异步action成功,当异步action成功时,把结果直接更新到state上
    builder
    .addCase(login.fulfilled, (state:any, action)=> //只监听成功 
      console.log('---login', action)
      state.token = action.payload
    )

builder:可以理解为构建一个case
fulfilled表示fetch行为监听成功时的状态 在acition中拿到token

  • 使用createAsyncThunk(‘user/login’, async (入参)=>(await fetchLogin())),给到createSlice.extraReducers中addCase添加异步成功状态,在成功状态中直接修改子store。这些由createAsyncThunk创建action方法,也要抛出,给React组件进行触发使用 dispatch(login(入参))。创建异步action

createAsyncThunk方法可以创建一个异步的action,这个方法被执行的时候会有三个( pending(进行中) fulfilled(成功) rejected(失败))状态。这可以监听状态的改变执行不同的操作。以下代码示例中使用到了extraReducers创建额外的action对数据获取的状态信息进行监听。

hooksAPI

在ts环境下要做一些小调整
在src文件下新建hook文件夹 下面添加index.ts

import  TypedUseSelectorHook, useDispatch, useSelector  from 'react-redux'
import type  RootState, AppDispatch  from '@/store'

export const useAppDispatch = () => useDispatch<AppDispatch>()
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector

对hooksAPI进行进出口处理

使用

  • 在App中,安装react-redux,使用注入上下文。
  • 在React组件中,只能使用 @reduxjs/toolkit官方推荐的 useAppSelector来使用store数据、只能使用useAppDispatch来触那些子store中抛出的action。

redux-toolkit是目前来说比较好的一个redux使用的解决方案,通过一些内置的插件和代码封装让redux的使用更加的方便顺手,而且条理更清晰。

create-react-app脚手架两种的区别

 ES6环境(只能使用ES6语法、默认不支持TS,使用redux、react-redux)
 定义redux时,参考store_backup代码
 使用redux数据时,可以用connect、useSelector、useDispatch
create-react-app my-app1

 TS环境(TS和ES6都可以使用、在这个环境使用redux、react-redux传统流程)
create-react-app my-app2 --template typescript

TS环境(只使用TS,不使用ES6,在这个环境中使用 @reduxjs/toolkit、react-redux)
create-react-app my-app3 --template redux-typescript

以上是关于Redux流程分析 传统流程和redux-toolkit的使用的主要内容,如果未能解决你的问题,请参考以下文章

Redux流程分析 传统流程和redux-toolkit的使用

[Redux/Mobx] 说说Redux的实现流程

数据流程redux

Redux数据流

Redux-介绍&工作流程

移动app传统测试流程优化