Redux Toolkit (RTK) + TypeScript

文章目录

Redux 的三个核心阶段( 定义 Slice -> 配置 Store -> 组件使用


第一阶段:定义数据切片

这一步是业务逻辑的核心。

  • 1. 定义 IState: 为了类型安全,必须定义。
  • 2. initialState:
  • 3. createAsyncThunk: 专门处理 HTTP 请求。
  • 4. createSlice:
  • 5. reducers vs extraReducers :
    • 补充reducers 处理同步(如:toggleMenu),extraReducers 监听异步 Thunk 的状态(pending, fulfilled, rejected)。
    • 注意 :在 TS 中,extraReducers 现在推荐使用 builder callback 写法(builder.addCase(...)),这样类型推断最准确。
  • 6. Export : 导出 actions 给 UI 用,导出 reducer 给 Store 用。

第二阶段:配置全局 Store

这一步是把分散的 Slice 组装成大脑。

  • 7. combineReducers :
    • 这一步在 RTK 中是可选 的。直接传一个对象,configureStore 底层会自动帮你调 combineReducers
    • 写法const rootReducer = combineReducers({ user, order })
    • 简化写法reducer: { user: userReducer, order: orderReducer }(推荐,少写一行代码)。
  • 8. configureStore: 这是 RTK 的核心,自动开启了 Redux DevTools。
  • 9. Export Hooks : 非常重要!
    • 你提到了 useAppDispatchuseAppSelector,这非常关键。
    • 原因 :原生的 useDispatch 不知道你 Thunk 的类型,原生的 useSelector 不知道你 RootState 的结构。二次封装后,你在组件里写代码会有完美的 TS 提示。

第三阶段:组件使用

这一步是 UI 与数据交互。

  • 10. useAppDispatch :
    • 术语纠正 :我们通过 dispatch 触发 action,而不是直接调用 reducers。Reducers 是在后台听到 action 后执行的。
  • **11. useAppSelector:
    • 补充:它会自动订阅更新。只要 Store 里的数据变了,组件会自动 Re-render(重新渲染),不需要你手动干预。
  • 12. useEffect 监听 :
    • 场景 A(自动更新视图) :不需要 useEffectuseAppSelector 拿到的数据变了,页面这块 DOM 自动就变了。
    • 场景 B(副作用) :比如"登录成功后跳转页面"或者"弹出成功提示",这种才需要用 useEffect 监听状态变化。

极简代码模板

1. Slice (userSlice.ts)
typescript 复制代码
// Step 1
interface UserState {
  loading: boolean;
  data: any;
}
// Step 2
const initialState: UserState = { loading: false, data: null };

// Step 3
export const loginUser = createAsyncThunk('user/login', async (params) => {
  return await api.login(params);
});

// Step 4
const userSlice = createSlice({
  name: 'user',
  initialState,
  // Step 5: 同步
  reducers: {
    logout: (state) => { state.data = null; }
  },
  // Step 5: 异步 (Builder 写法是 TS 最佳实践)
  extraReducers: (builder) => {
    builder.addCase(loginUser.fulfilled, (state, action) => {
      state.data = action.payload;
    });
  }
});

// Step 6
export const { logout } = userSlice.actions;
export default userSlice.reducer;
2. Store (store.ts)
typescript 复制代码
import { configureStore } from '@reduxjs/toolkit';
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
import userReducer from './userSlice';

// Step 7 & 8 (合并写法)
export const store = configureStore({
  reducer: {
    user: userReducer, // 这里自动 combineReducers
  },
});

// Step 9: 导出 TS 类型和 Hooks
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;

export const useAppDispatch = () => useDispatch<AppDispatch>();
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
3. Component (Page.tsx)
typescript 复制代码
// Step 10
const dispatch = useAppDispatch();
// Step 11
const { data, loading } = useAppSelector(state => state.user);

// 触发操作
const handleLogin = () => {
  dispatch(loginUser({ username: 'admin' }));
};

// Step 12 (仅用于副作用)
useEffect(() => {
  if (data) {
    message.success('登录成功');
  }
}, [data]);
相关推荐
广州山泉婚姻几秒前
微服务时代,前后端分离架构该怎样高效协同?
前端·后端
EatFan5 分钟前
多租户系统到底怎么设计?从 tenant_id 到 JWT 租户隔离的真实实践
前端·后端·全栈·多租户
计算机魔术师11 分钟前
硅谷四大AI巨头联手踩刹车,是真心怕失控还是怕被超越?
前端
岁岁种桃花儿19 分钟前
Vue组件第六篇:Vue单文件组件
开发语言·前端·javascript·vue.js
yivifu22 分钟前
创建支持交叉链接且鼠标悬停显示注释框的HTML文件
前端·javascript·html
GreenTea1 小时前
🔥别再用压缩了,Codex、NVIDIA、DeepSeek、Uber 给出 Agent 上下文管理的新答案
前端·后端·算法
IT_陈寒1 小时前
React重渲染这坑,我跳进去又爬出来了
前端·人工智能·后端
郑州光合科技余经理3 小时前
本地生活系统:多业务订单字段怎么分账本导出
java·开发语言·前端·数据库·uni-app·php·ai编程