Redux-toolkit 傻瓜式使用教程(TS)(demo)

3,097 阅读4分钟

官网:Redux-toolkit

api

configureStore(): 包装createStore以提供简化的配置选项和良好的默认值。它可以自动组合你的 slice reducer,添加你提供的任何 Redux 中间件,thunk中间件默认包含,并启用 Redux DevTools Extension。

createReducer():这使您可以为 case reducer 函数提供操作类型的查找表,而不是编写 switch 语句。此外,它自动使用该immer库让您使用普通的可变代码编写更简单的不可变更新,例如state.todos[3].completed = true.

createAction():为给定的动作类型字符串生成动作创建函数。该函数本身已toString()定义,因此可以使用它来代替类型常量。

createSlice():接受reducer函数的对象、切片名称和初始状态值,并自动生成切片reducer,并带有相应的动作创建者和动作类型。

createAsyncThunk: 接受一个动作类型字符串和一个返回承诺的函数,并生成一个pending/fulfilled/rejected基于该承诺分派动作类型的 thunk

createEntityAdapter: 生成一组可重用的 reducer 和 selector 来管理 store 中的规范化数据\

使用方法

安装redux-toolkit

npm install @reduxjs/toolkit
yarn add @reduxjs/toolkit

目录结构

image.png

image.png

话不多说直接来个demo

store.ts文件

import { configureStore } from '@reduxjs/toolkit'
import StuReducer from './reducer'


const store = configureStore({
    reducer:StuReducer
})

export type RootState = ReturnType<typeof store.getState>
export type AppDispatch = typeof store.dispatch

export default store

reducer.ts文件

//在这个文件里你可以声明状态来为将来需要接收的状态做准备(状态在此文件中汇总)
import stu from './slice/stuSlice' //引入之前写好的slice(读取状态)
import { combineReducers } from '@reduxjs/toolkit'


const reducers = {
//声明状态在此处
  stu: stu
}

const rootReducer = combineReducers(reducers)

export type RootState = ReturnType<typeof rootReducer>

export default rootReducer

slice文件夹中可以存放一些做数据处理的文件

stuSlice.ts

import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import { myApi } from '../action' //将一个异步的操作入进来
import { RootState } from '../store' //引入类型

//声明状态进行接收
interface stuState {
    id: number,
    name: string,
    classes: string[],
}

const initialState:stuState = {
    id: 1,
    name: '老王',
    classes: [],
}

export const stuSlice = createSlice({
    name:'goodjob', //类似于命名空间,(取个名字)
    initialState, //引用你写的状态
    //reducers 里面包裹的是同步的方法
    reducers:{
        changeName:(state,action:PayloadAction<string>) => {
            state.name = action.payload
        },
        changeId:(state,action:PayloadAction<number>) => {
            state.id = action.payload
        },
    },
		
    //我们在extraReducers中放入的是异步的方法,我们在action中声明的TT方法可以在此处使用
    //在此处我们可以监听创建好的异步action,此处有三个取值是比较常用的
   		1、fulfilled 成功之后需要做的操作
  		2、pending 加载时需要做的操作
  		3、rejected失败后需要做什么处理
  
    extraReducers: builder => {
        builder.addCase(myApi.fulfilled, (state: stuState, {payload}: PayloadAction<number>) => {
            state.id = payload
        })
    }
})

export const { changeName, changeId } = stuSlice.actions 
export const student = (state:RootState) => state.stu
export default stuSlice.reducer

对以上builder的解释:此重载接受一个回调函数,该函数接收一个builder对象作为其参数。该构建器提供addCase,addMatcher和addDefaultCase函数,可以调用这些函数来定义此 reducer 将处理的操作。(详情建议官网查)

hooks.ts文件

//此处对redux中的useDispatch, useSelector 进行二次封装方便项目中调用
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'
import type { AppDispatch, RootState } from './store'

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

action.ts文件

//为了可以后期去更好的维护自己的代码,这边建议可以吧异步的操作放到action中专门来处理
import { applyMiddleware, createAsyncThunk } from '@reduxjs/toolkit'

export const myApi = createAsyncThunk('student', async (): Promise<number> => {
  const res = await api //这边访你需要调取的接口
  return res
})

注文:
在此单独对createAsyncThunk这个方法进行讲解
createAsyncThunk这个中间件是用来处理异步操作的(副作用)
他有两个参数:
1、第一个参数传入的是一个字符串,这个地方类似去个名字
2、第二个参数是你要处理的异步,比如调接口的方法(你封装好的api)
这边写好相应的操作之后可以在相应的slice文件中去应用封装好的异步处理程序,slice中会监听这个异步

项目入口文件index.tsx文件

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { Provider } from 'react-redux'
import store from './redux/store'


ReactDOM.render(
  <React.StrictMode>
    <Provider store={store}> //这边找这些就OK了,用Provider标签包裹住
      <App />
    </Provider>
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

App.tsx 文件(使用!!终于尾声了)

import React from 'react';
//引入hooks文件中封装好的方法
import { useAppDispatch, useAppSelector } from './redux/hooks';
// 拿到两个动作
import { changeId, changeName } from './redux/slice/studentSlice';
//拿到声明的异步操作
import { myApi } from './redux/action';

function App() {
  const dispatch = useAppDispatch(); 
  const stu = useAppSelector(state => state.stu);
  return (
    <div>
      <div>
        <div>我叫{stu.name}</div>
        <button onClick={() => dispatch(changeName('王武'))}>王武</button>
        <button onClick={() => dispatch(changeName('刘叔'))}>刘叔</button>
      </div>
      <div>
        <div>我是{stu.id}号</div>
        <button onClick={() => dispatch(changeId(5))}>更改为5</button>
        <button onClick={() => dispatch(changeId(8))}>更改为8</button>
        <button onClick={() => dispatch(myApi())}>异步</button>
      </div>
    </div>
  );
}

export default App;

希望可以给你带来帮助🥳 ღ( ´・ᴗ・` )比心