Redux中如何标识方法调用成功?TypeScript报错求助
问题原因
Redux Toolkit的reducer(CaseReducer)不允许返回布尔值。根据类型定义,reducer的返回值只能是以下三种之一:
void:修改Immer包装的state(draft)后不返回任何值(Immer自动处理state更新)- 完整的
StrategySlice状态对象(直接返回新state) - Immer的
WritableDraft<StrategySlice>类型对象
你返回boolean不符合任何类型要求,因此触发TypeScript错误。
最佳实现方案
要避免静默失败并实现错误处理,推荐以下几种方案:
方案一:使用createAsyncThunk(推荐)
虽然你的逻辑是同步的,但createAsyncThunk可以让你明确返回操作结果,还会自动生成对应状态的action,组件能直接获取成功/失败反馈,完美解决静默失败问题。
代码实现
import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'; // 定义异步thunk,内部执行同步删除逻辑 export const deleteStage = createAsyncThunk( 'strategy/deleteStage', (payload: { strategyId: string; stageId: string }) => { // 这里复用你的存在性校验逻辑 const strategyIndex = findStrategyIndexById({ strategies: [] }, payload.strategyId); // 替换为实际state获取方式 if (strategyIndex !== -1) { return { success: true, ...payload }; } return { success: false }; } ); const strategySlice = createSlice({ name: 'strategy', initialState, reducers: {}, extraReducers: (builder) => { builder.addCase(deleteStage.fulfilled, (state, action) => { if (action.payload.success) { const { strategyId, stageId } = action.payload; const strategyIndex = findStrategyIndexById(state, strategyId); if (strategyIndex !== -1) { state.strategies[strategyIndex].stages = state.strategies[strategyIndex].stages.filter( stage => stage.id !== stageId ); } } }); } }); export default strategySlice.reducer;
组件中使用
import { useDispatch } from 'react-redux'; import { deleteStage } from './strategySlice'; const YourComponent = () => { const dispatch = useDispatch(); const handleDelete = async (strategyId: string, stageId: string) => { try { const result = await dispatch(deleteStage({ strategyId, stageId })).unwrap(); if (result.success) { console.log('删除成功'); } else { console.log('未找到目标策略,删除失败'); } } catch (err) { console.error('删除操作出错:', err); } }; return <button onClick={() => handleDelete('strat-1', 'stage-2')}>删除阶段</button>; };
方案二:在state中添加操作状态字段
如果不想用thunk,可以在slice的state中新增一个字段记录最近一次操作的结果,组件通过useSelector读取该状态判断操作是否成功。
代码实现
首先修改state结构:
interface StrategySlice { strategies: Strategy[]; lastOperationStatus: 'idle' | 'success' | 'failed'; } const initialState: StrategySlice = { strategies: [], lastOperationStatus: 'idle' };
然后更新slice:
const strategySlice = createSlice({ name: 'strategy', initialState, reducers: { deleteStage: (state, action: PayloadAction<{ strategyId: string; stageId: string }>) => { const { strategyId, stageId } = action.payload; const strategyIndex = findStrategyIndexById(state, strategyId); if (strategyIndex !== -1) { state.strategies[strategyIndex].stages = state.strategies[strategyIndex].stages.filter( stage => stage.id !== stageId ); state.lastOperationStatus = 'success'; } else { state.lastOperationStatus = 'failed'; } }, resetOperationStatus: (state) => { state.lastOperationStatus = 'idle'; } } }); export const { deleteStage, resetOperationStatus } = strategySlice.actions; export default strategySlice.reducer;
组件中使用
import { useDispatch, useSelector } from 'react-redux'; import { deleteStage, resetOperationStatus } from './strategySlice'; import { useEffect } from 'react'; const YourComponent = () => { const dispatch = useDispatch(); const operationStatus = useSelector(state => state.strategy.lastOperationStatus); const handleDelete = (strategyId: string, stageId: string) => { dispatch(deleteStage({ strategyId, stageId })); }; // 监听操作状态,处理后重置状态 useEffect(() => { if (operationStatus === 'success') { console.log('删除成功'); dispatch(resetOperationStatus()); } else if (operationStatus === 'failed') { console.log('删除失败'); dispatch(resetOperationStatus()); } }, [operationStatus, dispatch]); return <button onClick={() => handleDelete('strat-1', 'stage-2')}>删除阶段</button>; };
方案三:组件内直接验证结果(简单场景适用)
组件在dispatch后,通过useSelector监听state变化,验证目标stage是否存在,以此判断操作是否成功。注意React状态更新是异步的,需要用useEffect触发校验。
组件代码
import { useDispatch, useSelector } from 'react-redux'; import { deleteStage } from './strategySlice'; import { useEffect, useState } from 'react'; const YourComponent = ({ strategyId, stageId }) => { const dispatch = useDispatch(); const strategies = useSelector(state => state.strategy.strategies); const [deleteTriggered, setDeleteTriggered] = useState(false); const handleDelete = () => { dispatch(deleteStage({ strategyId, stageId })); setDeleteTriggered(true); }; useEffect(() => { if (deleteTriggered) { const targetStrategy = strategies.find(s => s.id === strategyId); const stageStillExists = targetStrategy?.stages.some(s => s.id === stageId); if (!stageStillExists) { console.log('删除成功'); } else { console.log('删除失败'); } setDeleteTriggered(false); } }, [deleteTriggered, strategies, strategyId, stageId]); return <button onClick={handleDelete}>删除阶段</button>; };
方案推荐
优先选择方案一,它符合Redux Toolkit的最佳实践,将状态更新逻辑集中在reducer中,组件只需处理业务反馈,代码结构清晰,还能避免状态残留问题。
内容的提问来源于stack exchange,提问作者Olivia Bates
相关产品推荐
相关产品推荐

