前端学习--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商店里下载

相关推荐
王俊山IT12 分钟前
C++学习笔记----10、模块、头文件及各种主题(一)---- 模块(5)
开发语言·c++·笔记·学习
小政爱学习!16 分钟前
封装axios、环境变量、api解耦、解决跨域、全局组件注入
开发语言·前端·javascript
魏大帅。22 分钟前
Axios 的 responseType 属性详解及 Blob 与 ArrayBuffer 解析
前端·javascript·ajax
花花鱼28 分钟前
vue3 基于element-plus进行的一个可拖动改变导航与内容区域大小的简单方法
前端·javascript·elementui
k093331 分钟前
sourceTree回滚版本到某次提交
开发语言·前端·javascript
EricWang13581 小时前
[OS] 项目三-2-proc.c: exit(int status)
服务器·c语言·前端
September_ning1 小时前
React.lazy() 懒加载
前端·react.js·前端框架
Mephisto.java1 小时前
【大数据学习 | kafka高级部分】kafka中的选举机制
大数据·学习·kafka
web行路人1 小时前
React中类组件和函数组件的理解和区别
前端·javascript·react.js·前端框架
番茄小酱0011 小时前
Expo|ReactNative 中实现扫描二维码功能
javascript·react native·react.js