react reducx的使用

安装依赖

在React项目中,需要安装@reduxjs/toolkit和react-redux两个包:

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

创建Redux相关文件

  1. 创建slice

    • 使用createSlice创建slice,它会自动生成action creator和reducer。例如:

      复制代码
      import { createSlice } from '@reduxjs/toolkit';
      
      const counterSlice = createSlice({
        name: 'counter',
        initialState: {
          count: 0
        },
        reducers: {
          increment(state) {
            state.count++;
          },
          decrement(state) {
            state.count--;
          },
          addToNum(state, action) {
            state.count += action.payload;
          }
        }
      });
      
      export const { increment, decrement, addToNum } = counterSlice.actions;
      export default counterSlice.reducer;
  2. 创建store

    • 使用configureStore创建store,它会自动配置中间件和Redux DevTools:

      复制代码
      import { configureStore } from '@reduxjs/toolkit';
      import counterReducer from './counterSlice';
      
      const store = configureStore({
        reducer: {
          counter: counterReducer
        }
      });
      
      export default store;

在React应用中使用Redux

  1. 提供store

    • 在React应用的顶层组件中,使用<Provider>组件将store提供给整个应用:

      复制代码
      import React from 'react';
      import ReactDOM from 'react-dom';
      import { Provider } from 'react-redux';
      import store from './store';
      import App from './App';
      
      ReactDOM.render(
        <Provider store={store}>
          <App />
        </Provider>,
        document.getElementById('root')
      );
  2. 在组件中使用Redux

    • 在React组件中,可以使用useSelector和useDispatch两个Hooks来读取state和分发action

      复制代码
      import React from 'react';
      import { useSelector, useDispatch } from 'react-redux';
      import { increment, decrement, addToNum } from './counterSlice';
      
      function Counter() {
        const count = useSelector(state => state.counter.count);
        const dispatch = useDispatch();
      
        return (
          <div>
            <p>Count: {count}</p>
            <button onClick={() => dispatch(increment())}>Increment</button>
            <button onClick={() => dispatch(decrement())}>Decrement</button>
            <button onClick={() => dispatch(addToNum(20))}>Add 20</button>
          </div>
        );
      }
      
      export default Counter;

2. 创建异步Thunk

使用createAsyncThunk创建一个异步Thunk,它会自动生成pending、fulfilled和rejected的action类型。例如,假设你有一个API接口https://jsonplaceholder.typicode.com/users,你想要获取用户数据并更新state:

复制代码
// src/thunks/userThunks.js
import { createAsyncThunk } from '@reduxjs/toolkit';

export const fetchUserById = createAsyncThunk(
  'users/fetchById',
  async (userId) => {
    const response = await fetch(`https://jsonplaceholder.typicode.com/users/${userId}`);
    if (!response.ok) {
      throw new Error('Failed to fetch user');
    }
    return response.json();
  }
);

3. 创建Slice

在createSlice中处理异步Thunk的pending、fulfilled和rejected状态。你可以使用extraReducers来监听这些状态并更新state:

复制代码
// src/slices/userSlice.js
import { createSlice } from '@reduxjs/toolkit';
import { fetchUserById } from '../thunks/userThunks';

const initialState = {
  user: null,
  status: 'idle', // 'idle' | 'loading' | 'succeeded' | 'failed'
  error: null
};

const userSlice = createSlice({
  name: 'user',
  initialState,
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(fetchUserById.pending, (state) => {
        state.status = 'loading';
      })
      .addCase(fetchUserById.fulfilled, (state, action) => {
        state.status = 'succeeded';
        state.user = action.payload;
      })
      .addCase(fetchUserById.rejected, (state, action) => {
        state.status = 'failed';
        state.error = action.error.message;
      });
  }
});

export default userSlice.reducer;

4. 创建Store

在store.js中配置store,引入你的slice和Thunk:

复制代码
// src/store.js
import { configureStore } from '@reduxjs/toolkit';
import userReducer from './slices/userSlice';

export const store = configureStore({
  reducer: {
    user: userReducer
  }
});

5. 在React组件中使用

在React组件中,你可以使用useDispatch来触发异步Thunk,并使用useSelector来读取state:

复制代码
// src/components/UserComponent.js
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { fetchUserById } from '../thunks/userThunks';

function UserComponent() {
  const dispatch = useDispatch();
  const { user, status, error } = useSelector((state) => state.user);

  const handleFetchUser = () => {
    dispatch(fetchUserById(1)); // 假设用户ID为1
  };

  return (
    <div>
      <button onClick={handleFetchUser}>Fetch User</button>
      {status === 'loading' && <p>Loading...</p>}
      {status === 'succeeded' && (
        <div>
          <h2>User Details</h2>
          <p>Name: {user.name}</p>
          <p>Email: {user.email}</p>
        </div>
      )}
      {status === 'failed' && <p>Error: {error}</p>}
    </div>
  );
}

export default UserComponent;

6. 提供Store

确保在顶层组件中使用<Provider>来提供store:

复制代码
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { store } from './store';
import App from './App';

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);

2.多个reducer时, 使用combineReducers组合reducer

在store.js中,使用combineReducers将多个reducer组合成一个根reducer,然后传递给store。

复制代码
// src/store.js
import { configureStore, combineReducers } from '@reduxjs/toolkit';
import userReducer from './slices/userSlice';
import counterReducer from './slices/counterSlice';

const rootReducer = combineReducers({
  user: userReducer,
  counter: counterReducer
});

export const store = configureStore({
  reducer: rootReducer
});
相关推荐
中文呀1 小时前
三维 GIS 离线缓存实战:逆向 CesiumOfflineCache,并亲手为它补上"自动更新"能力
前端
前进前进前进2 小时前
TRAE 全链路实战:做了一个警示牌一键生成器:纯 Canvas、单文件、零依赖
前端
小万7423 小时前
God‘s Eye View 深度解析:15 路公开信号 + CesiumJS 的浏览器级 OSINT 控制台,60 帧渲染的“真实间谍卫星模拟器”
前端
IT星宿3 小时前
浏览器标签页全是一个图标:我用名字哈希生成 favicon,让每个项目都有身份标识
前端
全栈项目管理程序猿3 小时前
ArcGIS JS 基础教程(32):体元系列 - VoxelSlice 体元切片
前端·javascript
结局无敌5 小时前
React Native for OpenHarmony 实战:三方库 react-native-modal-dialog 的鸿蒙化适配指南
深度学习·算法·react native·react.js·harmonyos
拖孩5 小时前
AI 帮我写的小程序「厨菜记」上线满月了,挣了两百块!!!
前端·后端·微信小程序
用户360055579005 小时前
Kestrel_VLLM - 13 · 为什么排除 MoE FFN Tiling 与 Tensor Core
前端
Hilaku6 小时前
AI 流式输出都用 SSE,什么时候必须换 WebSocket?
前端·javascript·程序员
奇牙coding6 小时前
Codex CLI 升级后多文件编辑静默失效:config.yaml 枚举变更排查与修复指南
java·前端·javascript·ai