React Redux 完整用法

一、安装依赖

bash

运行

bash 复制代码
# 现代推荐:redux toolkit(简化redux)+ react-redux
npm install @reduxjs/toolkit react-redux

二、目录结构

plaintext

bash 复制代码
src/
├── store/
│   ├── index.js    # 仓库入口
│   └── slices/
│       └── userSlice.js  # 模块状态
├── App.js
└── main.js  # 根入口

三、1. 创建 Slice(拆分模块状态)

store/slices/userSlice.js

js

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

// 初始状态
const initialState = {
  name: '',
  age: 18
}

const userSlice = createSlice({
  name: 'user', // 模块名
  initialState,
  reducers: {
    // 修改state方法(直接赋值,不用手动immutable)
    setName: (state, action) => {
      state.name = action.payload
    },
    setAge: (state, action) => {
      state.age = action.payload
    },
    addAge: (state) => {
      state.age += 1
    }
  }
})

// 导出action方法
export const { setName, setAge, addAge } = userSlice.actions
// 导出reducer给仓库
export default userSlice.reducer

四、2. 配置仓库 store/index.js

js

javascript 复制代码
import { configureStore } from '@reduxjs/toolkit'
import userReducer from './slices/userSlice'

export const store = configureStore({
  reducer: {
    // 挂载模块:key=模块名,value=slice reducer
    user: userReducer
  }
})

五、3. 根组件注入 Provider(main.js)

让所有子组件能访问 redux

jsx

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

const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
  {/* 包裹App,传入store */}
  <Provider store={store}>
    <App />
  </Provider>
)

六、4. 组件中使用(hooks API,函数组件)

useSelector:读取状态

useDispatch:派发 action 修改状态

App.js

jsx

javascript 复制代码
import { useSelector, useDispatch } from 'react-redux'
import { setName, setAge, addAge } from './store/slices/userSlice'

function App() {
  // 读取user模块下的状态
  const user = useSelector(state => state.user)
  const dispatch = useDispatch()

  return (
    <div>
      <h3>姓名:{user.name}</h3>
      <h3>年龄:{user.age}</h3>

      {/* 修改数据 */}
      <button onClick={() => dispatch(setName('张三'))}>改名字</button>
      <button onClick={() => dispatch(setAge(22))}>改年龄</button>
      <button onClick={() => dispatch(addAge())}>年龄+1</button>
    </div>
  )
}

export default App

七、异步请求(Redux Toolkit createAsyncThunk)

1. slice 中写异步

userSlice.js

js

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

// 异步请求函数
export const getUserInfo = createAsyncThunk(
  'user/getUserInfo',
  async (params, { rejectWithValue }) => {
    const res = await fetch('https://xxx/api/user')
    return res.json()
  }
)

const initialState = {
  info: null,
  loading: false
}

const userSlice = createSlice({
  name: 'user',
  initialState,
  reducers: {},
  // 处理异步
  extraReducers: (builder) => {
    builder
      .addCase(getUserInfo.pending, (state) => {
        state.loading = true
      })
      .addCase(getUserInfo.fulfilled, (state, action) => {
        state.loading = false
        state.info = action.payload
      })
      .addCase(getUserInfo.rejected, (state) => {
        state.loading = false
      })
  }
})

export default userSlice.reducer

2. 组件调用异步

jsx

javascript 复制代码
import { getUserInfo } from './store/slices/userSlice'

function User() {
  const dispatch = useDispatch()
  const { info, loading } = useSelector(s => s.user)

  return (
    <>
      <button onClick={() => dispatch(getUserInfo())}>请求用户数据</button>
      {loading ? '加载中' : JSON.stringify(info)}
    </>
  )
}

八、Class 组件老式用法(过时了解即可)

jsx

scala 复制代码
import { connect } from 'react-redux'

class Demo extends React.Component {
  render() {
    return <div>{this.props.user.name}</div>
  }
}

// 映射state到props
const mapState = state => ({ user: state.user })
// 映射dispatch到props
const mapDispatch = { setName }

export default connect(mapState, mapDispatch)(Demo)

九、核心知识点总结

  1. Redux Toolkit:官方推荐,内置 immutable、异步、中间件,简化冗余代码
  2. createSlice:整合 state + reducers + actions,自动生成 action
  3. Provider:全局提供 store,必须包裹根组件
  4. useSelector:订阅读取 redux 数据,数据变化自动重渲染
  5. useDispatch:触发 reducer 修改全局状态
  6. createAsyncThunk:专门处理网络异步请求
相关推荐
用户921080262861 小时前
前端 Vue 专栏 07:模板编译、虚拟 DOM、Diff 与 key
前端
光影少年1 小时前
react navite process.nextTick 和 Promise.then 的执行顺序
前端·react native·react.js
雪芽蓝域zzs1 小时前
第四十二节:全局字典封装(后端字典,下拉选择复用)
开发语言·前端·javascript
用户64596598710881 小时前
Nginx + Vue Router 基础:SPA History 部署、反向代理与请求分流
前端
样子20181 小时前
Js 之根据白名单过滤 HTML(防止 XSS 攻击)
android·前端·javascript·html·xss
lewis_lk2 小时前
ReactJs状态迷思:从"常量"到"闭包陷阱"的底层逻辑
前端·react.js
尘世中一位迷途小书童2 小时前
在 Cesium 上画全球网格:我们怎么把 GeoSOT 接到瓦片调度上
前端·javascript·前端框架
aixingpan2 小时前
aixingpan.cn API开发文档:api_docs_trichart_natal_progression_ter_transit2接口指南
前端·php
liuyt20222 小时前
【javaweb】day3
前端
CoderYanger2 小时前
Java EE 进阶:2.3 JavaScript
java·开发语言·前端·javascript·css·职场和发展·java-ee