前端学习--React(3)

一、Redux

集中状态管理工具,不需要react即可使用,每个store的数据都是独立于组件之外的

vue小链接:vuex/pinia

基本使用

Redux将数据修改流程分成三个概念,state、action和reducer

state - 一个对象 存放我们管理的数据状态

action - 一个对象 描述你如何修改数据

reducer - 一个函数 根据action的描述生成新的state

javascript 复制代码
<button id="decrement">-</button>
<span id="count">0</span>
<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) {
    // 数据不可变:基于原始状态生成一个新的状态 所以要返回新对象
    if (action.type === 'INCREMENT') {
      return { count: state.count + 1 }
    }
    if (action.type === 'DECREMENT') {
      return { count: state.count - 1 }
    }
    return state
  }

  // 2. 使用reducer函数生成store实例
  const store = Redux.createStore(reducer)

  // 3. 通过store实例的subscribe订阅数据变化
  // 回调函数可以在每次state发生变化的时候自动执行
  store.subscribe(() => {
    console.log('state变化了', store.getState())
    document.getElementById('count').innerText = store.getState().count
  })

  // 4. 通过store实例的dispatch函数提交action更改状态 
  const inBtn = document.getElementById('increment')
  inBtn.addEventListener('click', () => {
    // 增
    store.dispatch({
      type: 'INCREMENT'
    })
  })

  const dBtn = document.getElementById('decrement')
  dBtn.addEventListener('click', () => {
    // 减
    store.dispatch({
      type: 'DECREMENT'
    })
  })

  // 5. 通过store实例的getState方法获取最新状态更新到视图中

</script>

react中使用redux

相关工具

Redux Toolkit 简化redux书写逻辑

react-redux 链接Redux和React的中间件

javascript 复制代码
npm i @reduxjs/toolkit react-redux

安装成功

目录创建

创建src/store,modules存放子模块

counterStore.js

javascript 复制代码
//1 导入并创建store
import {createSlice} from "@reduxjs/toolkit"

const counterStore = createSlice({
    name:'counter',
    // 初始状态
    initialState:{
        count:0
    },
    // 更新状态的方法
    reducers:{
        inscrement(state){
            state.count++
        },
        descrement(state){
            state.count --
        }
    }
})

const {inscrement, descrement} = counterStore.actions
const reducer = counterStore.reducer

export{
    inscrement,
    descrement
}

export default reducer

store/index.js

集成store/modules中所有子模块

javascript 复制代码
import { configureStore } from "@reduxjs/toolkit";
import counterReducer from "./modules/counterStore"

// 将子模块中的所有store合成一个根store方便访问
const store = configureStore({
    reducer:{
        counter:counterReducer,
    }
})

export default store

src/index.js

javascript 复制代码
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import store from "./store"
import { Provider } from 'react-redux';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  // 通过react-redux提供的Provider 给组件注入store 使得redux定义的store能够被react组件使用
  <Provider store={store}>
    <App />
  </Provider>
);

App.js

useDispatch() 通过这个来派发reducer修改状态

javascript 复制代码
import { useSelector, useDispatch } from "react-redux";
import {inscrement, descrement} from "./store/modules/counterStore"
function App() {
  const { count } = useSelector(state => state.counter)
  const dispatch = useDispatch()
  return (
    <div className="App">
      <button onClick={() => dispatch(inscrement())}>+</button>
      {count}
      <button onClick={() => dispatch(descrement())}>-</button>
    </div>
  );
}

export default App;

然后就完成了:

进阶版-提交action时传参

counterStore.js

增加了一个addToNum函数

javascript 复制代码
//1 导入并创建store
import {createSlice} from "@reduxjs/toolkit"

const counterStore = createSlice({
    name:'counter',
    // 初始状态
    initialState:{
        count:0
    },
    // 更新状态的方法
    reducers:{
        inscrement(state){
            state.count++
        },
        descrement(state){
            state.count --
        },
        addToNum(state, action){
            // dispatch调用该方法时传入的参数就存放在action.payload
            state.count += action.payload
        }
    }
})

const {inscrement, descrement, addToNum} = counterStore.actions
const reducer = counterStore.reducer

export{
    inscrement,
    descrement,
    addToNum
}

export default reducer

App.js

增加了两个值,传入不同参数

javascript 复制代码
import { useSelector, useDispatch } from "react-redux";
import {inscrement, descrement, addToNum} from "./store/modules/counterStore"
function App() {
  const { count } = useSelector(state => state.counter)
  const dispatch = useDispatch()
  return (
    <div className="App">
      <button onClick={() => dispatch(inscrement())}>+</button>
      {count}
      <button onClick={() => dispatch(descrement())}>-</button>
      <button onClick={() => dispatch(addToNum(10))}>+ 10</button>
      <button onClick={() => dispatch(addToNum(-10))}>- 10</button>
    </div>
  );
}

export default App;

再进阶版-异步状态操作

channelStore.js

javascript 复制代码
import {createSlice} from '@reduxjs/toolkit'
import axios from 'axios'

const channelStore = createSlice({
    name:'channel',
    initialState:{
        channelList:[]
    },
    reducers:{
        getChannels(state, action){
            state.channelList = action.payload
        }
    }
})

const {getChannels} = channelStore.actions


//单独写一个异步action的函数 异步操作处理完毕后再调用同步action修改状态
const getChannelList = () => {
    return async(dispatch) => {
        const res = await axios.get('http://geek.itheima.net/v1_0/channels')
        dispatch(getChannels(res.data.data.channels))
    }
}

export {getChannelList}

const reducer = channelStore.reducer
export default reducer

App.js

javascript 复制代码
import { useSelector, useDispatch } from "react-redux";
import {inscrement, descrement, addToNum} from "./store/modules/counterStore"
import {getChannelList} from "./store/modules/channelStore"
import {useEffect} from 'react'
function App() {
  const { count } = useSelector(state => state.counter)
  const { channelList } = useSelector(state => state.channel)
  const dispatch = useDispatch()

  useEffect(()=> {
    dispatch(getChannelList())
  }, [dispatch])
  
  return (
    <div className="App">
      <button onClick={() => dispatch(inscrement())}>+</button>
      {count}
      <button onClick={() => dispatch(descrement())}>-</button>
      <button onClick={() => dispatch(addToNum(10))}>+ 10</button>
      <button onClick={() => dispatch(addToNum(-10))}>- 10</button>
      <ul>
        {channelList.map(item => <li key={item.id}>{item.name}</li>)}
      </ul>
    </div>
  );
}

export default App;

调试工具redux devtools

直接在chorme商店里下载

相关推荐
贾saisai6 分钟前
Xilinx系FPGA学习笔记(九)DDR3学习
笔记·学习·fpga开发
北岛寒沫10 分钟前
JavaScript(JS)学习笔记 1(简单介绍 注释和输入输出语句 变量 数据类型 运算符 流程控制 数组)
javascript·笔记·学习
(⊙o⊙)~哦1 小时前
JavaScript substring() 方法
前端
无心使然云中漫步2 小时前
GIS OGC之WMTS地图服务,通过Capabilities XML描述文档,获取matrixIds,origin,计算resolutions
前端·javascript
Bug缔造者2 小时前
Element-ui el-table 全局表格排序
前端·javascript·vue.js
铁匠匠匠2 小时前
从零开始学数据结构系列之第六章《排序简介》
c语言·数据结构·经验分享·笔记·学习·开源·课程设计
xnian_2 小时前
解决ruoyi-vue-pro-master框架引入报错,启动报错问题
前端·javascript·vue.js
麒麟而非淇淋3 小时前
AJAX 入门 day1
前端·javascript·ajax
架构文摘JGWZ3 小时前
Java 23 的12 个新特性!!
java·开发语言·学习
2401_858120533 小时前
深入理解MATLAB中的事件处理机制
前端·javascript·matlab