Rudex

今天学的不多喵()事情有点多,小忙

基本介绍

是React最常用的集中状态管理工具,类似于Vue的Pinia(Vuex),可以独立于框架运行。

image-20260209192855801

使用步骤:

我们先脱离框架,使用纯redux实现计数器。

  1. 定义一个 reducer 函数 (根据当前想要做的修改返回一个新的状态)
  2. 使用 createStore 方法传入 reducer 函数 生成一个 store 实例对象
  3. 使用 store 实例的 subscribe 方法 订阅数据的变化 (数据一旦变化,可以得到通知)
  4. 使用 store 实例的 dispatch 方法提交 action 对象 触发数据变化 (告诉reducer你想怎么改数据)
  5. 使用 store 实例的 getState 方法 获取最新的状态数据更新到视图中
 <button id="decrement">-</button>
 <span id="count">0</span>
 <button id="increment">+</button>
 <script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.2.1/redux.min.js"></script>
 <script>
  /*1.定义reducer函数根据不同的action对象返回不同的state*/
  function reducer(state = {count:0},action){
     if(action.type === 'INCREMENT'){
       return {count:state.count + 1}
    }
     if(action.type === 'DECREMENT'){
       return {count:state.count - 1}
    }
     return state
  }
  /*2.生成实例*/
  const store = Redux.createStore(reducer)
  /*3.订阅数据变化,回调函数在每次state变化的时候自动执行*/
  store.subscribe(()=>{
     console.log('data changed')
     document.getElementById('count').innerText = store.getState().count
  })
  const inBtn = document.getElementById('increment')
  inBtn.addEventListener('click',() =>{
     store.dispatch({
       type:'INCREMENT'
    })
  })
  const dBtn = document.getElementById('decrement')
  dBtn.addEventListener('click',()=>{
     store.dispatch({
       type: 'DECREMENT'
    })
  })
 </script>
Redux 的单向数据流
  1. View:用户点击了一个按钮(比如“购买”)。
  2. Dispatch Action :视图发出一个 Action。例如:{ type: 'ADD_TO_CART', product: 'Book' }
  3. Reducer (处理):Reducer 收到这个 Action,根据它执行逻辑(原来的购物车数量 +1)。
  4. Store (仓库):Reducer 返回的新状态被存入 Store(图中那个装着很多 state 的大框子)。
  5. View Update (更新视图):由于 Store 里的 State 变了,界面(View)会自动感知并重新渲染,显示购物车里有了 1 本书。

这样做你知道每一笔数据改变是谁引起的,如果数据错了,你只需要检查那个对应的 Reducer 逻辑,而不需要搜遍整个项目的代码。

环境准备

react中使用redux我们需要ReduxToolkit(RTK)和react-redux两个插件。

RTK是官方推荐的编写Redux逻辑的方式,是一个工具集。

react-redux是链接redux和组件的中间件。

 npm install @reduxjs/toolkit react-redux

目录结构设计

创建Store目录,然后新建main.js,和modules文件夹,store的入口文件组合文件夹中的子模块并且导出,为一个store对象。

代码实现

我们再次实现计数器案例

counterStore.js

 import {createSlice} from "@reduxjs/toolkit"
 ​
 const counterStore = createSlice({
   name: 'counter',
   initialState:{
     count:0
  },
   reducers:{
     increment(state) {
       state.count++
    },
     decrement(state){
       state.count--
    }
  }
 })
 ​
 /*解构actionCreater函数 */
 const {increment,decrement} = counterStore.actions
 const reducer = counterStore.reducer
 ​
 export{increment,decrement}
 export default reducer

main.js

 import { configureStore } from "@reduxjs/toolkit";
 import counterReducer from "./modules/counterStore";
 const store = configureStore({
   reducer:{
     counter:counterReducer
  }
 })
 export default store

为react注入store,用内置的Provider组件注入到应用中链接正式建立。

 import { StrictMode } from 'react'
 import { createRoot } from 'react-dom/client'
 import App from './App.jsx'
 import store from './store/main.js'
 import { Provider } from "react-redux"
 createRoot(document.getElementById('root')).render(
   <StrictMode>
     <Provider store={store}>
           <App />
     </Provider>
   </StrictMode>,
 )

使用钩子函数useSelector把store里面的数据映射到组件中

 import { useSelector } from 'react-redux'
 ​
 function App () {
   // 使用 useSelector 从 store 中提取 count 状态
   const { count } = useSelector(state => state.counter)
   
   return (
     <div className="App">
      {count}
     </div>
  )
 }
 ​
 export default App

使用钩子函数useDispatch,修改store中的数据。

 import { userDispatch, useSelector } from 'react-redux'
 import {decrement,increment} from './store/modules/counterStore'
 function App () {
   // 使用 useSelector 从 store 中提取 count 状态
   const { count } = useSelector(state => state.counter)
   const dispatch = useDispatch()
   return (
     <div className="App">
    <button onClick={() => dispatch(decrement())}>-</button>
    <span>{count}</span>
         <button onClick={() => dispatch(increment())}>+</button>
     </div>
  )
 }
 ​
 export default App

提交action传参

上面的单击按钮按一下增加1,但是我想要增加一个任意值呢?

 import {createSlice} from "@reduxjs/toolkit"
 ​
 const counterStore = createSlice({
   name: 'counter',
   initialState:{
     count:0
  },
   reducers:{
     increment(state) {
       state.count++
    },
     decrement(state){
       state.count--
    },
     addToNum(state,action) {
       state.count = action.payload
    }
  }
 })
 ​
 /*解构actionCreater函数 */
 const {increment,decrement,addToNum} = counterStore.actions
 const reducer = counterStore.reducer
 ​
 export{increment,decrement,addToNum}
 export default reducer

我们增加一个reducer,这里需要传入action

 import { userDispatch, useSelector } from 'react-redux'
 import {decrement,increment,addToNum} from './store/modules/counterStore'
 function App () {
   // 使用 useSelector 从 store 中提取 count 状态
   const { count } = useSelector(state => state.counter)
   const dispatch = useDispatch()
   return (
     <div className="App">
    <button onClick={() => dispatch(decrement())}>-</button>
    <span>{count}</span>
         <button onClick={() => dispatch(increment())}>+</button>
         <button onClick={() => dispatch(addToNum(10))}>+10</button>
     </div>
  )
 }
 ​
 export default App

异步状态操作

样板代码

channelStore.js

 import { createSlice } from '@reduxjs/toolkit'
 import axios from 'axios'
 ​
 const channelStore = createSlice({
   name: 'channel',
   initialState: {
     channelList: []
  },
   reducers: {
     setChannels(state, action) {
       state.channelList = action.payload
    }
  }
 })
 ​
 const { setChannels } = channelStore.actions
 const fetchChannelList = () => {
   return async (dispatch) => {
     const res = await axios.get('http://geek.itheima.net/v1_0/channels')
     dispatch(setChannels(res.data.data.channels))
  }
 }
 ​
 export { fetchChannelList }
 export default channelStore.reducer

单独封装一个函数,内部 return 一个 async 函数,在里面 await 请求完后再 dispatch 同步方法,来实现异步逻辑

main.js

 import { configureStore } from "@reduxjs/toolkit";
 import counterReducer from "./modules/counterStore";
 import channelReducer from "./modules/channelStore"
 const store = configureStore({
   reducer:{
     counter:counterReducer,
     channel: channelReducer
  }
 })
 export default store

App.jsx

 import { useEffect } from 'react'
 import { useSelector, useDispatch } from 'react-redux'
 import { fetchChannelList } from './store/modules/channelStore'
 ​
 function App() {
   const dispatch = useDispatch()
   const { channelList } = useSelector(state => state.channel)
 ​
   useEffect(() => {
     // 组件加载时派发异步请求动作
     dispatch(fetchChannelList())
  }, [dispatch])
 ​
   return (
     <div className="App">
       <ul>
        {channelList.map(item => <li key={item.id}>{item.name}</li>)}
       </ul>
     </div>
  )
 }
 ​
 export default App

Redux调试——devtools

image-20260209214233460

下一下浏览器插件,然后打开开发者工具找到这个图片就能打开这个插件

image-20260209214344082

//具体使用这里就不多描述了喵。

暂无评论

发送评论 编辑评论


				
上一篇
下一篇