 React - Redux
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目录,在内部编写业务分类的子 store
- store 中的入口文件 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
