当前位置: 首页 > news >正文

React-Redux

1、安装

npm i redux react-redux @reduxjs/toolkit

2、基础使用方式(无 Toolkit)

(1)核心Api

  • createStore:创建数据仓库;
  • store.dispatch():用于派发action,执行修改动作;
  • store.getState():用于获取store里面的数据;
  • store.subscribe():订阅store的修改,只要store发生改变,回调函数就会被执行;

(2)store的创建和使用

        创建仓库:createStore()

// src/store/index.js
import { createStore } from "redux";
import reducer from "./reducer";const store = createStore(reducer);export default store;

        通过reducer提供数据源,reducer是一个纯函数

// src/store/reducer.js
const defaultState = {    count: 0
}const reducer = (state = defaultState, action) => {switch (action.type) {case "REDUCE":state.count--;break;case "ADD":state.count++;break;default: break;}return state;
}export default reducer;

        通过store.getState().keys来获取仓库中的数据

//组件内部引入仓库
import store from "./store/index";//获取数据
<h2>{store.getState().count}</h2>

(3)数据的修改和订阅

        在组件内部定义要执行的动作action,并触发

reduceCount() {let action = {type: "REDUCE",mydata: 10}store.dispatch(action)
}<button onClick={this.reduceCount.bind(this)}>-</button>

        接收动作并修改数据:通过dispatch触发动作后,会将action传递到reducer函数的第二个参数中

const reducer = (state = defaultState, action) => {switch (action.type) {case "REDUCE":state.count--;break;default: break;}return state;
}

        组件中及时响应更新的数据:订阅

componentDidMount() {store.subscribe(this.updatePage.bind(this))
}
updatePage() {this.setState(store.getState())
}

3、使用 Redux Toolkit

        目录结构: 

                                       

(1)创建Slice

// store/modules/counterStore.js
import { createSlice } from '@reduxjs/toolkit'const counterSlice = createSlice({name: 'counter',// 初始化stateinitialState: {count: 0},// 修改状态的方法 同步方法 支持直接修改reducers: {increment: (state) => {state.count++},decrement: (state) => {state.count--}}
})export const { increment, decrement } = counterSlice.actions 
export default counterSlice.reducer

(2)配置store

// store/inedx.js
import { configureStore } from "@reduxjs/toolkit"
import counterReducer from './modules/counterStore.js'export default configureStore({reducer: {counter: counterReducer}
})

(3)为react注入store

// src/index.js
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(<Provider store={store}><App /></Provider>
);

(4)组件中使用(Hooks 写法)

// App.js
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement } from './store/modules/counterStore';function App() {const { count } = useSelector(state => state.counter)const dispatch = useDispatch()return (<div className="App"><button onClick={() => dispatch(decrement())}>-</button>{ count }<button onClick={() => dispatch(increment())}>+</button></div>);
}export default App;

(5)提交action时传参

// App.js
import { increment, decrement, addToNum } from './store/modules/counterStore';<button onClick={() => dispatch(addToNum(20))}>+20</button>// store/modules/counterStore.js
addToNum: (state, action) => {state.count += action.payload
}

4、异步状态操作

        上面的操作都是同步更新数据,如果要实现异步操作,可以使用 createAsyncThunk:

// store/modules/channelStore.js
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import axios from 'axios'; // 定义异步 Action
export const fetchChannelList = createAsyncThunk('channel/fetchChannelList', // [切片名称]/[动作名称]async (url, thunkAPI) => {const res = await axios.get(url)return res.data.data.channels}
);const channelSlice = createSlice({name: 'channel',initialState: {channelList: [],loading: false,error: null},reducers: {},extraReducers: (builder) => {  // 处理异步操作的结果builder.addCase(fetchChannelList.pending, (state) => { // 请求进行中state.loading = truestate.error = null}).addCase(fetchChannelList.fulfilled, (state, action) => { // 请求成功state.loading = falsestate.channelList = action.payload}).addCase(fetchChannelList.rejected, (state, action) => { // 请求失败state.loading = falsestate.error = action.error.message})}
})export default channelSlice.reducer
// App.js
import { useSelector, useDispatch } from 'react-redux';
import { fetchChannelList } from './store/modules/channelStore';
import { useEffect } from 'react';
function App() {const { channelList, loading, error } = useSelector(state => state.channel)const dispatch = useDispatch()// 使用useEffect触发异步请求函数useEffect(() => {dispatch(fetchChannelList('http://geek.itheima.net/v1_0/channels'))}, [dispatch])return (<div className="App">{ loading && <div>加载中...</div>}{ error && <div>Error:{ error }</div>}<ul>{ channelList.map(item => <li key={item.id}>{item.name}</li>)}</ul></div>);
}export default App;

相关文章:

  • 4.26-count部分的渲染
  • 基于STM32定时器中断讲解(HAL库)
  • 聊聊Spring AI Alibaba的YuQueDocumentReader
  • Rule.issuer(通过父路径配置loader处理器)
  • 启动你的RocketMQ之旅(五)-Broker详细——消息传输
  • 学习Spire.Office for Java版本的科学实践
  • 硬件须知的基本问题2
  • Claude系列模型-20250426
  • 系统架构设计中的ATAM方法:理论、实践与深度剖析
  • AWS中国区ICP备案全攻略:流程、注意事项与最佳实践
  • Power BI企业运营分析——BCG分析
  • 1软考系统架构设计师:第一章系统架构概述 - 超简记忆要点、知识体系全解、考点深度解析、真题训练附答案及解析
  • 【教程】Docker运行gitlab容器
  • w307MES生产制造执行系统设计与实现
  • Unity AssetBundle (AB) 打包详解
  • 【新技术】微软 Azure Test Impact Analyzer (TIA) 全面解析
  • 29-算法打卡-字符串-KMP算法理论2-第二十九天
  • Adobe Photoshop(PS)2022 版安装与下载教程
  • 一篇入门之-评分卡变量分箱(卡方分箱、决策树分箱、KS分箱等)实操例子
  • CSS预处理器
  • 新希望去年归母净利润4.74亿同比增逾九成,营收降27%
  • 为国出征指纹却无法识别?他刷新了我军在这一项目的最好成绩
  • 合同约定拿850万保底利润?重庆市一中院:约定无效,发回重审
  • 王宝强谈《棋士》:饰演这个灰度人物有一种被割裂的痛苦
  • 上海天文馆加持,书友可在徐家汇书院“飞越银河系”!
  • 法治日报:强制统一店铺广告牌匾事件何以频发?