• 【Redux】Redux 基本使用


    1. Redux 快速上手

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

    <button id="decrement">-button>
    <span id="count">0span>
    <button id="increment">+button>
    
    <script src="https://unpkg.com/redux@latest/dist/redux.min.js">script>
    
    <script>
      // 1. 定义 reducer 函数 
      // 根据不同的 action 对象,返回不同的 state
      // state 管理数据的初始状态
      // action 对象的 type 属性标记需要做的修改操作
      function reducer (state = { count: 0 }, action) {
        switch (action.type) {
          case 'INCREMENT':
            // state 是对象,所以返回的数据也是对象
            return { count: state.count + 1 }
          case 'DECREMENT':
            return { count: state.count - 1 }
          default:
            return state
        }
      }
      // 2. 使用reducer函数生成store实例
      const store = Redux.createStore(reducer)
    
      // 3. 通过 store 实例的 subscribe 订阅数据变化
      // 回调函数在每一次 state 发生变化时自动执行
      store.subscribe(() => {
        console.log(store.getState())
        document.getElementById('count').innerText = store.getState().count
    
      })
      // 4. 通过 store 的 dispatch 函数提交 action 的更改状态
      const inBtn = document.getElementById('increment')
      inBtn.addEventListener('click', () => {
        // 匹配的是 action 对象,所以传入 action 对象
        store.dispatch({
          type: 'INCREMENT'
        })
      })
      // 减
      const dBtn = document.getElementById('decrement')
      dBtn.addEventListener('click', () => {
        store.dispatch({
          type: 'DECREMENT'
        })
      })
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    2.png

    2. React 中使用 Redux

    2.1 配制环境

    1. Redux Toolkit(RTK)- 官方推荐编写Redux逻辑的方式,简化书写方式
    2. react-redux - 用来链接 Redux 和 React组件的中间件
    npx create-react-app react-redux-demo
    npm i @reduxjs/toolkit  react-redux 
    
    • 1
    • 2

    2.2 使用 RTK

    创建 counterStore

    // @/store/modules/counterStore.js
    import { createSlice } from '@reduxjs/toolkit'
    
    const counterStore = createSlice({
      // 模块名称唯一
      name: 'counter',
      // 初始 state
      initialState: {
        count: 1
      },
      // 修改数据的同步方法 支持直接修改
      reducers: {
        increment (state) {
          state.count++
        },
        decrement(state){
          state.count--
        },
        addToNum(state, action) {
          state.count = action.payload
        }
      }
    })
    // 解构出 actionCreater 函数
    const { increment,decrement, addToNum } = counterStore.actions
    
    // 获取 reducer 函数
    const counterReducer = counterStore.reducer
    
    // 导出
    export { increment, decrement, addToNum }
    export default counterReducer
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    // @/store/modules/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 fetchChannlList = () => {
      return async (dispatch) => {
        const res = await axios.get('http://geek.itheima.net/v1_0/channels')
        dispatch(setChannels(res.data.data.channels))
      }
    }
    
    export { fetchChannlList }
    
    const reducer = channelStore.reducer
    
    export default reducer
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    // @/store/index.js
    import { configureStore } from '@reduxjs/toolkit'
    
    import counterReducer from './modules/counterStore'
    
    export default configureStore({
      reducer: {
        // 注册子模块
        counter: counterReducer
      }
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    为 React 注入 store

    // @/index.js
    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>
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在 React 组件中使用修改 store 中的数据

    // App.js
    import { useEffect } from 'react'
    import { useDispatch, useSelector } from 'react-redux'
    // 导入actionCreater
    import { inscrement, decrement, addToNum } from './store/modules/counterStore'
    import { fetchChannlList } from './store/modules/channelStore'
    
    function App () {
      // useSelector 函数将 store 中的数据映射到组件中 counter 是 store 名字
      const { count } = useSelector(state => state.counter)
      const { channelList } = useSelector(state => state.channel)
      const dispatch = useDispatch()
      // 使用useEffect触发异步请求执行
      useEffect(() => {
        dispatch(fetchChannlList())
      }, [dispatch])
      return (
        <div className="App">
          <button onClick={() => dispatch(decrement())}>-</button>
          {count}
          <button onClick={() => dispatch(inscrement())}>+</button>
          {/* 变为10 和 变为20 */}
          <button onClick={() => dispatch(addToNum(10))}>add To 10</button>
          <button onClick={() => dispatch(addToNum(20))}>add To 20</button>
          <ul>
            {channelList.map(item => <li key={item.id}>{item.name}</li>)}
          </ul>
        </div>
      )
    }
    
    export default App
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
  • 相关阅读:
    持续测试(Continuous Testing)
    RT-Thread学习笔记(四):RT-Thread Studio工具使用
    vuex基础用法1.0
    【深度学习】P0 系列博文架构
    文件操作 和 IO - 详解
    一个简单HTML5期末考核大作业,学生个人html静态网页制作代码
    zdpgo_gin_limit 为zdpgo_gin打造的接口限流框架,当API接口需要限制访问频率的时候可以使用此框架
    终于找到你!数字化时代的秘密武器
    硬技能之上的软技巧(一)
    python用于NLP的seq2seq模型实例:用Keras实现神经网络机器翻译
  • 原文地址:https://blog.csdn.net/XiugongHao/article/details/134487001