函数式组件使用Redux Toolkit----react状态管理工具

一、Redux Toolkit概念了解

`@reduxjs/toolkit`是Redux官方为了简化和提高开发体验而开发的一个工具包。它为使用Redux构建应用程序提供了一组常用的工具和实用程序,旨在简化开发流程并减少样板代码。通过`@reduxjs/toolkit`,您可以更快速地编写Redux代码,同时仍然享受到完整的Redux功能。

Redux Toolkit 最初是为了帮助解决有关 Redux 的三个常见问题而创建的:

"配置 Redux store 过于复杂"

"我必须添加很多软件包才能开始使用 Redux"

"Redux 有太多样板代码"

Redux Toolkit 提供了以下主要功能:

1. 集成了Redux常用的工具:`@reduxjs/toolkit`内置了常用的Redux工具,例如`createStore`、`createReducer`、`createAction`等。这些工具帮助您更方便地创建和组织Redux store、reducers以及actions。

2. 内置不可变性更新:`@reduxjs/toolkit`使用了`immer`库,它允许您以一种可变的方式来更新Redux状态。您可以直接修改状态对象,而`immer`会自动处理不可变性更新。这样,您可以省去手动编写不可变性更新逻辑的麻烦。

3. 简化的Redux配置:`@reduxjs/toolkit`通过使用`configureStore`函数来简化Redux的配置。它为您处理了一些常见的设置,例如中间件、持久化等。

4. 内置了Redux DevTools集成:`@reduxjs/toolkit`自动为您启用Redux DevTools的集成,使您可以轻松地在开发工具中查看和调试Redux store的状态和操作。

二、核心API

configureStore()

configureStore():创建 Store。用于替代 Redux 的 createStore() 方法。

接收一个对象作为参数,包含以下内容:

1.reducer:对象类型。可以接收多个 reducer 函数。

原有的 combineReducers() 合并函数就不需要了。

2.middleware:对象类型。可以接收多个中间件。

默认已经集成了 redux-thunk 和 redux-devtool 中间件。

devTools:布尔值类型。是否开启 devTools 工具,默认为 true。

createSlice()

createSlice():创建一个 slice 片段。一个 slice 片段其实是 Action 和 Reducer 的集合。createSlice() 接收一个对象作为参数,包含以下内容:

1.name:字符串类型。标记 slice。

作为 action.type 的前缀,在使用的时候默认使用 name/actionName,解决了 Action 中的 type 可能会同名的情况。在 Redux DevTools 调试工具中可以看到。

2.initialState:对象类型。State 的初始值。

3.reducers:对象类型,相当于之前的 Reducer 函数。

对象中可以添加任意多个函数,每一个函数就相当于之前 Reducer 函数中的一个 case 语句。会接收到 State 和 Action 作为其参数(Action 有两个属性:type 和 payload,dispatch 派发 Action 时传入的参数就会作为 payload),直接修改 State 中对应的值即可。

Redux Toolkit 底层使用了 immerjs 库,因此可以直接使用赋值的方式改变 State,不再需要每一次都返回一个新的 State。
immerjs 底层是使用了 proxy 来对原状态进行了拦截,生成了草稿状态,在草稿状态上进行读写操作后,返回最终的状态。也就实现了既保证了原状态的不可变性,也保证了返回的是一个不同引用地址的新状态。

4.extraReducers:对象类型或者函数类型。可以让 slice 处理在别处定义的 Action, 包括由 createAsyncThunk() 或其他 slice 生成的 Action。

createAsyncThunk()

createAsyncThunk():创建一个异步 Action。

接收两个参数:第一个参数是一个表示类型的字符串,用于标识这个异步 Action,在 Redux DevTools 调试工具中可以看到;第二个参数是一个函数,可以在其中进行异步操作,返回的数据会被传入到 createSlice() extraReducers 中函数的 action.payload 参数中。

createAsyncThunk() 方法触发的时候会有三种状态:pending(进行中)、fulfilled(成功)、rejected(失败),可以在 createSlice() 的 extraReducers 中监听结果。

三、Redux Toolkit 使用

1、安装 react - redux 和 @reduxjs/toolkit
# NPM
npm install @reduxjs/toolkit  react-redux

# Yarn
yarn add @reduxjs/toolkit  react-redux
2、创建 store

文件路径示例:

文件路径:src/store/index.js

// 引入 configureStore 方法
import {configureStore} from '@reduxjs/toolkit'
// 引入各个 reducer 切片
import countReducer from './features/count'

// 创建 store 用来创建store对象,需要一个配置对象作为参数
const store = configureStore({
  // 将导出的 slice 中的 reducer 传入,合并多个slice切片
  reducer: {
    count: countReducer,
  },
})

// 导出 store
export default store;
3、根组件配置 store

文件路径:项目入口 index.js 文件

创建 store 后,便可以在 React 组件中使用它。 在 src/index.js 中引入我们刚刚创建的 store , 通过 React-Redux 的 <Provider>将 <App> 包裹起来,并将 store 作为 prop 传入。

import ReactDOM from 'react-dom/client'
// 从 react-redux 中引入 Provider
import {Provider} from 'react-redux'
// 引入 store
import store from './store'

import App from './App'

const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
  // 使用 <Provider> 包裹根组件,将 Store 作为属性赋值给 <Provider>
  <Provider store={store}>
    <App />
  </Provider>
)
4、createSlice 创建 reducer 的切片

createSlice() 的返回值是一个对象,包含以下属性:

reducer:当前 slice 片段中的所有 Reducer。
actions:当前 slice 片段中的所有 Action。

文件路径: store/feature/count.js

// 引入 createSlice
import {createSlice, createAsyncThunk} from "@reduxjs/toolkit";
import axios from "axios";

// 通过 createAsyncThunk 创建一个异步的 Action 并导出
export const getAsyncCountAction = createAsyncThunk('getBannerAction', async () => {
  // 执行异步操作
  const res = await axios.get('http://123.207.32.32:8000/home/multidata')
  // 返回的数据会被传入到 extraReducers 中函数的 action.payload 参数中
  return res.data.data.banner.list.length
})

// 创建 slice。每一个 slice 里都包含了 reducer 和 actions,可以实现模块化的封装
const slice = createSlice({
  // 标记 slice,作为 action.type 的前缀
  name: 'count',
  // state 的初始值
  initialState: {
    count: 0,
  },
  // 相当于之前的 reducer 函数
  reducers: {
    // 一个函数就相当于之前的 reducer 函数中的一个 case 语句
    // 相当于既定义了组件中 dispatch 使用的同步 Action(函数名就相当于 Action 的类型),也定义了 Reducer 更新状态函数(函数体就相当于 Reducer 更新 State)
    increaseCount(state, action) {
      // 可以直接使用赋值的方式修改 State,不再需要每一次都返回一个新的 State
      state.count += action.payload
    },
    decreaseCount(state, action) {
      state.count -= action.payload
    },
  },
  // extraReducers 可以让 slice 处理在别处定义的 Action,包括由 createAsyncThunk 创建的异步的 Action或其他 slice 生成的 Action
  extraReducers: {
    [getAsyncCountAction.pending](state, action) {
      console.log('getAsyncCountAction.pending')
    },
    // 监听 createAsyncThunk 创建的异步 Action 的结果,修改 State 中指定的数据
    [getAsyncCountAction.fulfilled](state, action) {
      console.log('getAsyncCountAction.fulfilled')
      state.count = action.payload
    },
    [getAsyncCountAction.rejected](state, action) {
      console.log('getAsyncCountAction.rejected')
    },
  },
// extraReducers 还有另外一种写法,可以是一个函数,接收一个 builder 作为参数,可以给 builder 添加 case 来监听异步操作的结果
  extraReducers: builder => {
    builder
      .addCase(getAsyncCountAction.pending, (state, action) => {
        console.log('getAsyncCountAction.pending')
      })
      .addCase(getAsyncCountAction.fulfilled, (state, action) => {
        console.log('getAsyncCountAction.fulfilled')
        state.count = action.payload
      })
  },

// 导出 slice 片段中的 reducer,以供创建 store 时使用
export default slice.reducer

// 导出 slice 片段中的 action,以供组件中 dispatch 时使用
export const {increaseCount, decreaseCount} = slice.actions
5、页面使用

useDispatch() 用来获取派发器对象
useSelector() 用来加载 state 中的数据

import React from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { increaseCount } from '../../store/features/count'
 
export default function ReduxTest() {
    const { count } = useSelector(state => state.SetInitState);
    const dispatch = useDispatch();
 
    // 改变count状态
    const clickCount = () => {
        dispatch(increaseCount());
    }
    return (
        <div>
            <div style={{ background: "white" }}>
                <p>ReduxTest页面Redux-Count:{count}</p>
            </div>
            <br />
            <p><button onClick={clickCount}>ReduxTest组件,点击count+1</button></p>
        </div>
 
    )
}

四、redux-persist 持久化储存(选学)

在实际开发中,如果用户刷新了网页,那么我们通过 redux 存储的全局数据就会丢失,比如登录信息。可以通过 localStorage 将信息存储到本地,需要自己添加逻辑(了解)。

通过 redux-persist 实现持久化储存,使用过程:

1、 安装
npm install redux-persist
2、配置 store

文件路径:src/store/index.js

import { configureStore } from '@reduxjs/toolkit'
import { combineReducers } from 'redux'
// 配置数据的持久化效果
import { persistStore, persistReducer} from 'redux-persist'
// 导入需要配置的数据源,可选storage、cookie、session等
import storage from 'redux-persist/lib/storage'
// import storageSession from 'redux-persist/lib/storage/session'
import count from '@/store/feature/count'
import menuReducer from '@/store/slicers/menuSlice'

// 合并多个模块
const reducers = combineReducers({
	user: count,
	menu: menuReducer
})

// 配置持久化设置
const persistConfig = {
    key: 'root',
    storage, // 持久化存储引擎
    // 可选的配置项,如白名单、黑名单等 选其一
    // blacklist: ['不想缓存的状态的名字'],
    // whitelist: ['想要缓存状态的名字']  
}

// 创建持久化的配置persist的信息
const persistedReducer = persistReducer(persistConfig, reducers)

// 创建存储对象并且抛出对象
export const store = configureStore({
	reducer: persistedReducer
})

// 使用persistStore包裹并抛出
export const persistor = persistStore(store) 
3、index.js入口文件中配置

在入口文件中使用 PersistGate 包裹根组件,这将延迟渲染 app 视图直到持久化状态取回并保存到 redux 中。

将 store 提供给应用程序,persistor对象提供给根组件

import ReactDOM from 'react-dom/client'
import App from './App'
import { Provider } from 'react-redux'
// 导入redux中对应抛出的store对象和persistor对象
import { store, persistor } from '@/store'
// 如果使用React,则使用 PersistGate 包裹根组建
import { PersistGate } from 'redux-persist/lib/integration/react'

const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
    <Provider store={store}>
    	<PersistGate loading={null} persistor={persistor}>
    		<App />
    	</PersistGate>
    </Provider>
)

  • 19
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值