React - Redux
# Redux 介绍
Redux 是 React 最常用的集中状态管理工具(全局变量),类似于 Vue 中的 Pinia(Vuex),可以独立于框架运行 作用:通过集中管理的方式管理应用的状态
为什么要使用 Redux?
- 独立于组件,无视组件之间的层级关系,简化通信问题
- 单项数据流清晰,易于定位 bug
- 调试工具配套良好,方便调试
# 使用
Redux Toolkit
(RTK)- 官方推荐编写 Redux 逻辑的方式,是一套工具的集合集,简化书写方式react-redux
- 用来 链接 Redux 和 React 组件 的中间件
npm i @reduxjs/toolkit react-redux
# store 目录
通常集中状态管理的部分都会单独创建一个单独的
store
目录应用通常会有很多个子 store 模块,所以创建一个
modules
目录,在内部编写业务分类的子 storestore 中的入口文件 index.js 的作用是组合 modules 中所有的子模块,并导出 store
# 编码
store/modules/counterStore.js
import { createSlice } from '@reduxjs/toolkit'
// 1. 创建模块
const counterStore = createSlice({
// 定义模块名称,独一无二
name: 'counter',
// 定义初始数据
initialState: {
count: 1
},
// 定义修改数据的同步方法
reducers: {
increment (state) {
state.count++
},
decrement(state){
state.count--
}
}
})
// 2. 解构出actionCreater 修改方法
const { increment,decrement } = counterStore.actions
// 获取reducer函数
const counterReducer = counterStore.reducer
// 导出
export { increment, decrement }
export default counterReducer
store/index.js
:注册子模块
import { configureStore } from '@reduxjs/toolkit'
import counterReducer from './modules/counterStore'
export default configureStore({
reducer: {
// 1. 注册子模块为counter
counter: counterReducer
}
})
index.js
:Provider 包裹 App 使 redux 生效
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
+// 导入store
+import store from './store'
+// 导入store提供组件Provider
+import { Provider } from 'react-redux'
ReactDOM.createRoot(document.getElementById('root')).render(
// 提供store数据
+ <Provider store={store}>
<App />
+ </Provider>
)
App.js
:读取与修改
// useDispatch(写操作) useSelector(读操作)
import {useDispatch, useSelector} from "react-redux";
import {decrement, increment} from "./store/modules/counterStore";
function App() {
const { count } = useSelector(state => state.counter)
const dispatch = useDispatch()
return (
<div>
<button onClick={()=>dispatch(decrement())}> -</button>
{count}
<button onClick={()=>dispatch(increment())}> +</button>
</div>
);
}
export default App;
# action 传参
# 异步操作
channelStore.js
import { createSlice } from '@reduxjs/toolkit'
import axios from 'axios'
const channelStore = createSlice({
name: 'channel',
initialState: {
channelList: []
},
reducers: {
setChannelList (state, action) {
state.channelList = action.payload
}
}
})
// 创建异步
const { setChannelList } = channelStore.actions
const url = 'http://geek.itheima.net/v1_0/channels'
// 封装一个函数 在函数中return一个新函数 在新函数中封装异步
// 得到数据之后通过dispatch函数 触发修改
const fetchChannelList = () => {
return async (dispatch) => {
const res = await axios.get(url)
dispatch(setChannelList(res.data.data.channels))
}
}
export { fetchChannelList }
const channelReducer = channelStore.reducer
export default channelReducer
App.js
import { useEffect } from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { fetchChannelList } from './store/channelStore'
function App () {
// 使用数据
const { channelList } = useSelector(state => state.channel)
useEffect(() => {
dispatch(fetchChannelList())
}, [dispatch])
return (
<div className="App">
<ul>
{channelList.map(task => <li key={task.id}>{task.name}</li>)}
</ul>
</div>
)
}
export default App
# 持久化
Redux 不支持持久化,浏览器刷新即会清除数据,需要配合 localStorage
方法来实现
initialState: {
// 初始化时,先从localStorage取,取不到再set空串
token: localStorge.getItem('token_key') || ''
}
setToken(state,action){
// set的时候依次set到redux和localStorage
state.token = action.payload
localStorage.setItem('token_key',action,payload)
}
笔记
可将操作 localStorage 中 token 的方法封装起来,使用 getToken
、 setToken
、 removeToken
来操作
# 浏览器插件 - Redux DevTools
Redux 官方提供了针对于 Redux 的调试工具,支持实时 state 信息展示,action 提交信息查看等
上次更新: 2024/08/28, 13:22:10