react reducx的使用

安装依赖

在React项目中,需要安装@reduxjs/toolkitreact-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组件中,可以使用useSelectoruseDispatch两个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,它会自动生成pendingfulfilledrejected的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的pendingfulfilledrejected状态。你可以使用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
});
相关推荐
console.log('npc')5 分钟前
2026 实测:Grok 4.5 与 Grok 4.6 怎么选?前端开发、教程写作、Figma 还原选型指南
前端·大模型·ai编程·figma·grok
yyt36304584119 分钟前
一次鼠标交互触发两次 Vue flushJobs:把高频交互从 VDOM 里拆出来
前端·vue.js·计算机外设
YUJIANYUE26 分钟前
查立得万用查分安卓版(web环境+查询系统免安装单文件一键运行包)
android·前端
慧都小项1 小时前
从 Figma 到 Qt:Qtitan 能减少哪些界面还原工作?
前端·qt·嵌入式·figma·图形界面·工业界面·qtitan
YWL1 小时前
OpenLayers导出功能:地图截图+GeoJSON导出完整方案,从Canvas合并到PDF生成
前端·vue·openlayers
苦瓜小生1 小时前
【前端】【力扣与手撕】十天带你刷完前端算法与手撕,全是最简单好记的最优解法!day4
前端·数据结构·算法·leetcode·面试
mayaairi1 小时前
Vue2 实战进阶:表单数据收集、指令系统与自定义指令全解析
前端·javascript·vue.js
计算机魔术师1 小时前
实测GPT-6 Astra后,我发现过去十年的专业门槛正在失效
前端
虎头金猫1 小时前
Pic Smaller 本地部署:压缩图片、转换格式,再搭建自己的 Web 工具
运维·前端·开源·aigc·ai编程·ai写作
hunterandroid2 小时前
Android ANR 排查实战:从线上告警到主线程卡点定位
android·前端