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]);
相关推荐
李剑一1 小时前
要闹哪样?又出现了一款新的格式化插件,尤雨溪力荐,速度提升了惊人的45倍!
前端·vue.js
闲云一鹤1 小时前
Git LFS 扫盲教程 - 你不会还在用 Git 管理大文件吧?
前端·git·前端工程化
阿虎儿2 小时前
React Context 详解:从入门到性能优化
前端·vue.js·react.js
Sailing2 小时前
🚀 别再乱写 16px 了!CSS 单位体系已经进入“计算时代”,真正的响应式布局
前端·css·面试
喝水的长颈鹿3 小时前
【大白话前端 03】Web 标准与最佳实践
前端
爱泡脚的鸡腿3 小时前
Node.js 拓展
前端·后端
左夕4 小时前
分不清apply,bind,call?看这篇文章就够了
前端·javascript
Zha0Zhun5 小时前
一个使用ViewBinding封装的Dialog
前端
兆子龙5 小时前
从微信小程序 data-id 到 React 列表性能优化:少用闭包,多用 data-*
前端
滕青山5 小时前
文本行过滤/筛选 在线工具核心JS实现
前端·javascript·vue.js