react + redux 状态管理操作

目录

  • [1 概念](#1 概念)
  • [2 Redux 安装](#2 Redux 安装)
  • [3 创建子模块并导入](#3 创建子模块并导入)
  • [4 中间件为 react 注入 store](#4 中间件为 react 注入 store)
  • [5 在组件中使用 store 数据](#5 在组件中使用 store 数据)
  • [6 修改 store 数据](#6 修改 store 数据)
  • [7 提交 action 传参](#7 提交 action 传参)
  • [8 异步状态操作](#8 异步状态操作)
  • [9 redux 调试工具](#9 redux 调试工具)

1 概念

Redux 是一个全局状态管理的 JS 库

2 Redux 安装

在react中使用redux,官方要求安装两个其他插件:Redux Toolkit 和 react-redux

  • Redux Toolkit:官方推荐编写redux逻辑的方式,简化书写方式
  • react-redux:用来连接 redux 和 react 组件的中间件

通过命令:

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

3 创建子模块并导入

创建如下目录结构

counterStore.js 代码如下:

javascript 复制代码
import { createSlice } from "@reduxjs/toolkit";

const counterStore = createSlice({
    name: 'counter',
    // 初始化state
    initialState: {
        count: 0
    },
    // 修改状态的方法 (同步方法)
    reducers: {
        increment(state) {
            state.count++
        },
        decrement(state) {
            state.count--
        }
    }
})

// 解构出来action函数
const { increment, decrement } = counterStore.actions
// 获取reducer
const reducer = counterStore.reducer

// 导出actions
export { increment, decrement }
// 默认导出reducer
export default reducer

其中,我们定义了数据:count

以及两个 action:increment / decrement,后续会通过 dispatch 来触发 action 修改数据

react 只有一种方式能够修改数据,就是 action,我们需要用 dispatch 提交 action,来修改数据

然后再将子模块 counterStore.js 引入

index.js 代码如下:

javascript 复制代码
import { configureStore } from '@reduxjs/toolkit'
import counter from './modules/counterStore'

// 导入子模块reducer
export default configureStore({
  reducer: {
    counter
  }
})

4 中间件为 react 注入 store

react-redux 负责把 react 和 redux 连接起来,内置 Provider 组件 通过 store 参数把创建好的 store 实例注入到应用中,连接正式建立

通过导入 store 和 Provider 后

使用 Provider 将 App 包裹起来

js 复制代码
import store from "./store";
import { Provider } from "react-redux";

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>
);

5 在组件中使用 store 数据

需要用到一个钩子函数 useSelector(),他的作用是把 store 的数据映射到组件中

javascript 复制代码
import './App.css';
import { useSelector } from "react-redux";

function App() {
  // 获得 count 数据
  const { count } = useSelector(state => state.counter)
  return (
    <div className="App">
      {count}
    </div>
  );
}

export default App;

使用 {count} 语法,界面中会展示 count 初始值

6 修改 store 数据

需要另外一个 hook 函数 userDispatch,它的作用是生成提交 action 对象的 dispatch 函数

react 只有一种方式能够修改数据,就是 action,我们需要用 dispatch 提交 action,来修改数据

javascript 复制代码
import './App.css';
import { useDispatch, useSelector } from "react-redux";
// 导入action 
import { increment, decrement } from './store/modules/counterStore.js'

function App() {
  // 获得 count 数据
  const { count } = useSelector(state => state.counter)
  // 通过 dispatch 提交action 修改数据
  const dispatch = useDispatch()

  return (
    <div className="App">
      <button onClick={() => dispatch(decrement())}>-</button>
      {count}
      <button onClick={() => dispatch(increment())}>+</button>
    </div>
  );
}

export default App;

7 提交 action 传参

在调用 action 时,参数会被传递到 action 对象的 payload 属性上

javascript 复制代码
import './App.css';
import { useDispatch, useSelector } from "react-redux";
// 导入action 
import { increment, decrement, addToNum } from './store/modules/counterStore.js'

function App() {
  // 获得 count 数据
  const { count } = useSelector(state => state.counter)
  // dispatch 提交action 修改数据
  const dispatch = useDispatch()

  return (
    <div className="App">
      <button onClick={() => dispatch(decrement())}>-</button>
      {count}
      <button onClick={() => dispatch(increment())}>+</button>
      <button onClick={() => dispatch(addToNum(10))}>+10</button>
    </div>
  );
}

export default App;
javascript 复制代码
import { createSlice } from "@reduxjs/toolkit";

const counterStore = createSlice({
    name: 'counter',
    // 初始化state
    initialState: {
        count: 0
    },
    // 修改状态的方法 (同步方法)
    reducers: {
        increment(state) {
            state.count++
        },
        decrement(state) {
            state.count--
        },
        addToNum(state, action) {
            state.count += action.payload
        }
    }
})

// 解构出来action函数
const { increment, decrement, addToNum } = counterStore.actions
// 获取reducer
const reducer = counterStore.reducer

// 导出actions
export { increment, decrement, addToNum }
// 默认导出reducer
export default reducer

8 异步状态操作

  • 创建 store 的 state 和 action 不变
  • 在子模块中单独封装一个函数,新函数中异步请求拿到数据,并使用 dispatch 触发 action

    创建新的 store 模块
    store/modules/channelStore.js 代码如下:
javascript 复制代码
import { createSlice } from "@reduxjs/toolkit";

const channelStore = createSlice({
    name: 'channel',
    // 初始化state
    initialState: {
        channel: [{id: 50}, {id: 100}]
    },
    // 修改状态的方法 (同步方法)
    reducers: {
        setChannels(state, action) {
            state.channel = action.payload
        }
    }
})

// 解构出来action函数
const { setChannels } = channelStore.actions
// 获取reducer
const reducer = channelStore.reducer

// 异步请求
const fetchChannList = () => {
    return async (dispatch) => {
        setTimeout(() => {
            dispatch(setChannels([{id: 50}, {id: 100}, {id: 150}, {id: 200}]))
        })  // 模拟产生异步请求
        console.log('aaa')
    }
}

// 导出异步方法
export { fetchChannList }
// 默认导出reducer
export default reducer

App.js 代码如下:

javascript 复制代码
import './App.css';
import { useEffect } from 'react';
import { useDispatch, useSelector } from "react-redux";
// 导入action 
import { increment, decrement, addToNum } from './store/modules/counterStore.js'

import { fetchChannList } from './store/modules/channelStore.js'

function App() {
  // 获得 state 数据
  const { count } = useSelector(state => state.counter)
  const { channel } = useSelector(state => state.channel)

  // dispatch 提交action 修改数据
  const dispatch = useDispatch()

  // 使用useEffect触发异步请求
  useEffect(() => {
    dispatch(fetchChannList())
  }, [dispatch])

  return (
    <div className="App">
      <button onClick={() => dispatch(decrement())}>-</button>
      {count}
      <button onClick={() => dispatch(increment())}>+</button>
      <button onClick={() => dispatch(addToNum(10))}>+10</button>

      <ul>
        {channel.map(item => <li key={item.id}>{item.id}</li>)}
      </ul>
    </div>
  );
}

export default App;

9 redux 调试工具

谷歌下载:redux devtools

相关推荐
Cool----代购系统API37 分钟前
css设置盒子动画,CSS3 transition动画 animation动画
前端·css·css3
哟哟耶耶1 小时前
css-设置元素的溢出行为为可见overflow: visible;
前端·css
sunly_1 小时前
CSS:跑马灯
前端·css
2301_818732061 小时前
用layui表单,前端页面的样式正常显示,但是表格内无数据显示(数据库连接和获取数据无问题)——已经解决
java·前端·javascript·前端框架·layui·intellij idea
yqcoder1 小时前
npm link 作用
前端·npm·node.js
林涧泣1 小时前
【Uniapp-Vue3】页面和路由API-navigateTo及页面栈getCurrentPages
前端·vue.js·uni-app
Komorebi゛1 小时前
【uniapp】获取上传视频的md5,适用于APP和H5
前端·javascript·uni-app
林涧泣1 小时前
【Uniapp-Vue3】动态设置页面导航条的样式
前端·javascript·uni-app
杰九1 小时前
【全栈】SprintBoot+vue3迷你商城(10)
开发语言·前端·javascript·vue.js·spring boot
Hopebearer_2 小时前
入门 Canvas:Web 绘图的强大工具
前端·javascript·es6·canva可画