react-redux使用总结(一)

雷献
2023-12-01

一、redux使用场景

当多个组件的state互相依赖,且组件间无法进行有效通信时,我们希望把这些state抽离出来进行集中管理,各组件可按照一定的规则进行状态的读写,这就是redux提供的功能

二、介绍

redux

一款状态管理工具,用于集中管理应用中(多个组件共享)的state
有下面三个核心概念:
store 整个应用中的state都存储在一棵object tree上,并且这个 object tree 只存在于唯一一个 store 中。store不可直接修改,需要结合下面的action和reducer 来完成

import { createStore } from 'redux'
import reducer from './reducers'

// 创建
const store = createStore(reducer)

action 要想更新 state 中的数据,你需要发起一个 action,action描述发生了什么

{ type: 'ADD_TODO', value: 'Go to swimming pool' }

reducer 为了把 action 和 state 串起来,开发一些函数,这就是 reducer。action通过dispatch派发,到达 reducer,通过自定义处理事件,返回新的 state 的函数,完成state的修改

function todos(state = [], action) {
	switch (action.type) {
		case 'ADD_TODO':
	    	return state.concat([{ text: action.value, completed: false }]);
	  	default:
	    	return state;
	}
}

react-redux

react的官方绑定库

redux-toolkit(RTK)

redux工具箱,规范了redux逻辑的编写方式
动机:
1、解决redux存储配置复杂问题
2、解决redux引入依赖过多问题
3、解决redux样例代码过多问题

redux-persist

redux持久化插件
通过把数据存储在localstorage中,使页面刷新后还能保持原来的状态

三、安装

npm install --save redux react-redux @reduxjs/toolkit redux-persist

四、使用

1、创建store及redux-persist持久化配置

通过RTK提供的configureStore创建store,而不是使用原生redux提供的createStore,configureStore 方法还提供了中间件的配置,默认提供了三个中间件,也可添加额外的 中间件

import { combineReducers } from "redux";
import { configureStore } from "@reduxjs/toolkit";
import counterReducer from "./counterReducer";
import storage from 'redux-persist/lib/storage';
import autoMergeLevel2 from 'redux-persist/es/stateReconciler/autoMergeLevel2';
import { persistReducer } from "redux-persist";

// 持久化存储设置
const persistConfig = {
  key: "root",
  storage: storage,
  stateReconciler: autoMergeLevel2,
//   whitelist: ["counter"],
//   blacklist: ["counter"]
};
// 合成reducer
const reducer = combineReducers({
    counter: counterReducer,
})
const myPersistReducer = persistReducer(persistConfig, reducer); 
// 配置store
export default configureStore({
    reducer: myPersistReducer,
    // devTools: process.env.NODE_ENV !== 'production',
    // middleware: [ thunk ]
    middleware: (getDefaultMiddleware) =>
        getDefaultMiddleware({
            serializableCheck: false, // toolkit默认添加的 可序列化检查中间件
            // immutabilityCheck: false,  // 不变性检查
            // thunk: false,
        }).concat(),
})

2、入口文件配置

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import reportWebVitals from './reportWebVitals';
import Page from './pages';
import { Provider } from 'react-redux'
import store from './redux/store'; 
import { PersistGate } from 'redux-persist/integration/react';
import { persistStore } from 'redux-persist';

const root = ReactDOM.createRoot(document.getElementById('root'));

let persistor= persistStore(store)
 
root.render(
  <React.StrictMode>
    {/* 通过provide,使所有组件都可以访问到store */}
    <Provider store={store}>
      <PersistGate loading={<div>loading...</div>} persistor={persistor}>
        <Page />
      </PersistGate>
    </Provider>
  </React.StrictMode>
);
reportWebVitals();

3、创建reducer

createSlice 一个函数,它接受初始state、reducer函数的对象和名称,并自动生成与reducer和state相对应的动作创建者和动作类型。
这个 API 是编写 Redux 逻辑的标准方法

import { createSlice} from "@reduxjs/toolkit";
export const counterSlice = createSlice({
  name: "counter",
  initialState: {
    value: 10
  },
  reducers: {
    // toolkit引用了immer的库,允许在createSlice中直接修改state
    increment: (state) => {
      state.value += 1
    },
    decrement: (state) => {
      state.value -= 1
    },
    incrementByAmount: (state, action) => { 
      state.value += action.payload
    }
  }
})
export const { increment, decrement, incrementByAmount} = counterSlice.actions
export default counterSlice.reducer

4、在组件中获取store值,触发reducer更新store

通过react-redux提供的useSelector、useDispatch可以直接获取到store中的数据和通过dispatch触发reducer,修改state

import React,{useState} from 'react'
import { useSelector, useDispatch, shallowEqual } from 'react-redux'
import { decrement, increment, incrementByAmount, } from '../../redux/counterReducer'
import styles from "./style.module.scss"

const Counter = () => {
    const [amount,setAmount] = useState(1)
    const dispatch = useDispatch()
    // shallowEqual-在组件决定是否被渲染之前,会进行一次浅比较如果该组件依赖的state并没有被更改,不进行渲染
    // 获取store
    const {value} = useSelector((state) => state.counter, shallowEqual) 

    return (
        <div className={styles.counterContainer}>
            <div>
                <p>{value}</p>
                <p>状态:{status}</p>
                <button onClick={() => dispatch(increment())} >
                    加一
                </button> 
                &nbsp;
                <button onClick={() => dispatch(decrement())} >
                    减一
                </button>
                <br /><br />
                <input value={amount} onChange={(e) => 	setAmount(Number(e.target.value))}/>
                <button onClick={() => 	dispatch(incrementByAmount(amount))}>+</button>
            </div>
        </div>
    )
}
export default Counter
 类似资料: