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
});
相关推荐
于慨14 小时前
Lambda 表达式、方法引用(Method Reference)语法
java·前端·servlet
石小石Orz14 小时前
油猴脚本实现生产环境加载本地qiankun子应用
前端·架构
从前慢丶14 小时前
前端交互规范(Web 端)
前端
CHU72903514 小时前
便捷约玩,沉浸推理:线上剧本杀APP功能版块设计详解
前端·小程序
GISer_Jing14 小时前
Page-agent MCP结构
前端·人工智能
王霸天14 小时前
💥别再抄网上的Scale缩放代码了!50行源码教你写一个永不翻车的大屏适配
前端·vue.js·数据可视化
小领航14 小时前
用 Three.js + Vue 3 打造炫酷的 3D 行政地图可视化组件
前端·github
@大迁世界14 小时前
2026年React大洗牌:React Hooks 将迎来重大升级
前端·javascript·react.js·前端框架·ecmascript
PieroPc14 小时前
一个功能强大的 Web 端标签设计和打印工具,支持服务器端直接打印到局域网打印机。Fastapi + html
前端·html·fastapi
悟空瞎说15 小时前
深入 Vue3 响应式:为什么有的要加.value,有的不用?从设计到源码彻底讲透
前端·vue.js