如何提高redux开发效率?当然是redux-tookit啦!

寻技术 React 2024年01月21日 121

前言

使用react-redux的朋友都经历过这种痛苦吧?

定义一个store仓库,首先创建各种文件,比如reducer、action、store...,然后 将redux和react连接使用。整个流程繁琐,写起来代码冗余。

react-redux创建仓库,文件目录如下:
image.png

好怀念使用 vuex创建写仓库的日子.......
直到有一天我发现了redux-toolkit ,原来redux还能这样写呀!

什么是redux-toolkit

redux-toolkit 是官方推荐的编写redux逻辑的方法,简化了redux的配置过程,无需再创建actions、reducer的,更大程度方便使用redux仓库

基本使用

redux-toolkit的使用步骤,可分为如下5步

  • 1、安装 redex-toolkit
  • 2、创建slices
  • 3、创建store
  • 4、将Redux连接到React应用(provide)
  • 5、在React组件中使用(useSelector、useDispath)

环境配置

vscode
React Redux Toolkit RTK Quer
安装npm

npm i redux react-redux @reactjs/toolkit

创建切片 slices

一个切片是一个包含 reducer 函数和 action creator 的对象。它定义了一部分状态和与该状态相关的操作。

// sliceTbale.js

import { createSlice } from '@reduxjs/toolkit';

const moviesSlice = createSlice({
  name: 'movies',
  // c初始化状态
  initialState: {
    currentData:[],// 
    tableData:[]
  },  
  reducers: {
      delete_table: (state, { payload }) => { 
            // 通过筛选实现删除 
             state.currentTable = state.currentTable.filter((item:{id:any})=>{
                return item.id !== payload.id
             }) 
             state.table =  state.currentTable
             message.success('删除成功') 
        },
  },
});

export const { addMovie } = moviesSlice.actions; // 导出 action creator
export default moviesSlice.reducer; // 导出 reducer

创建仓库-store

我们使用 configureStore 函数来创建 Redux Store,并使用刚刚创建的 reducer 将切片与 Store 关联起来。

// 创建store仓库
import { configureStore } from "@reduxjs/toolkit";
import  initTable  from "./module/table";

const reduxStore = configureStore({
    reducer: {
        // xxx: xxx,
        table:initTable
    },
})

export default reduxStore

redux链接react

完成以上步骤,redux配置ok啦,如何让整个项目中应用redux呢?
使用Provider包裹 React顶层组件,将 Redux store 对象传递给组件树中的所有组件,使得 Redux 的状态管理能够在整个应用程序中生效。
打开项目的入口文件 index.tsx,代码如下:

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import RouterConfig from './router/routerConfig';
import RouterView from './router/routerView';
import "nprogress/nprogress.css" // 样式
import { Provider } from 'react-redux';
import reduxStore from './store';

const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);
root.render(
  <React.StrictMode>
    <Provider store={reduxStore}> 
      <RouterView config={RouterConfig}></RouterView>
    </Provider>
  </React.StrictMode>
);

组件中使用redux

使用状态和操作:在组件中,可以使用 useSelector 和 useDispatch 钩子来访问状态和触发 action。

import React, { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';

interface IndexProps {}

const Index: React.FC<IndexProps> =  (props) => {
  //  获取redux仓库数据
  const tableState = useSelector((state:any)=>state.table)
   // 创建redux 派发器
  const Dispath = useDispatch()
  console.log('table仓库数据',tableState)  
  return (
    <> 
      {tableState.currentData.length}
     </>
  );
};

export default Index;

进阶使用

redux中如何执行异步呢?
createAsyncThunk 创建异步操作, 通常用于发出异步请求。
createAsyncThunk 创建一个异步action,方法触发的时候会有三种状态:

  • pending(进行中)
  • fulfilled(成功)
  • rejected(失败)
export const getMovieData:any = createAsyncThunk('sliceTable/getMovie', 
  async () => {
    const res= await getMovieListApi();
    return res;
  }
);

完整示例

import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import { getMovieListApi } from "../../API/home";
 import { message } from "antd";
// // createAsyncThunk 创建异步操作, 通常用于发出异步请求。
// createAsyncThunk 创建一个异步action,方法触发的时候会有三种状态:
// pending(进行中)、fulfilled(成功)、rejected(失败)
export const getMovieData: any = createAsyncThunk('sliceTable/getMovie',
    async () => {
        const res = await getMovieListApi();
        return res;
    }
);

const sliceName = createSlice({
    name: "sliceTable",
    initialState: {
        table: [],
        currentTable: []
    },
    reducers: {
        initTable: (state, { payload }) => {
            // console.log('初始化sliceTable数据')
        },
        delete_table: (state, { payload }) => { 
            // 通过筛选实现删除 
             state.currentTable = state.currentTable.filter((item:{id:any})=>{
                return item.id !== payload.id
             }) 
             state.table =  state.currentTable
             message.success('删除成功') 
        },
        serach_table: (state, { payload }) => { 
            // 通过筛选实现删除 
            console.log('payload',payload)
             state.currentTable = state.table.filter((item:{name:string})=>{
                return item.name.includes(payload)
             })  
        },
        
    },
    // 让 slice 处理在别处定义的 actions, // 包括由 createAsyncThunk 或其他slice生成的actions
    extraReducers: builder => builder
        .addCase(getMovieData.pending, (state, { payload }) => {
            // state.loading = true
            console.log('异步请求 中')
        })
        .addCase(getMovieData.fulfilled, (state, { payload }) => {
            // state.loading = false
            console.log('拿到异步数据')
            state.table = payload.data.data.list
            state.currentTable = payload.data.data.list
        })
        .addCase(getMovieData.rejected, (state, { payload }) => {
            // state.loading = false
            // state.error = payload
            console.log('异步操作错误')
    
        })

})


export const { initTable,delete_table ,serach_table} = sliceName.actions
export default sliceName.reducer

extraReducers
// extraReducers 字段让 slice 处理在别处定义的 actions, // 包括由 createAsyncg 或其他slice生成的actions。

store 映射到组件props中

使用 connect 函数将 store 内的数据映射到组件 props内

image-20231007232652559

读者朋友好呀,我是王天~

尝试做过很多事情,汽修专业肄业生,半路出道的野生程序员、前端讲师、新手作者,最终还是喜欢写代码、乐于用文字记录热衷分享~

如文章有错误或者不严谨的地方,期待给于指正,万分感谢。

如果喜欢或者 有所启发,欢迎 star,对作者也是一种鼓励。

微信:「wangtian3111」,加我进王天唯一的读者群。

个人博客:https://itwangtian.com

关闭

用微信“扫一扫”