等待dispatch thunk执行代码功能正常但编译器告警,求优化方案
优化方案
方案一:修改Thunk类型,解决不必要await告警
步骤1:更新AppThunk类型定义
修改AppThunk的类型,支持自定义返回值,让Thunk可以返回Promise:
// 原定义 // export type AppThunk = ThunkAction<void, RootState, null, Action<string>> // 修改后 export type AppThunk<ReturnType = void> = ThunkAction<ReturnType, RootState, null, Action<string>>
步骤2:让导出Thunk返回Promise
在ImportExportSlice.ts中,指定导出Thunk的返回类型为AppThunk<Promise<void>>,确保dispatch后能拿到Promise:
export const export = ( fpNumber?: number, errorMsg?: Record<string, string>, callback?: (status: string, errorMsg: Record<string, string>) => void ): AppThunk<Promise<void>> => async (dispatch) => { await (fpNumber ? importExportApi.export(fpNumber) : importExportApi.export()) .catch((error) => { const statusCode: string = error.response.status.toString() dispatch(setExportErrorStatusCode(statusCode)) callback?.(statusCode, errorMsg) }) .finally(() => dispatch(importExportProtokollLoad())) }
步骤3:组件中正常使用await
此时dispatch(export(...))会返回合法的Promise,await不再是多余操作,IntelliJ告警消失,同时能正确等待导出完成再关闭加载状态:
const handleOnExport = useCallback( async (fpNumber?: number) => { setIsExportAktionAktive(true) const statusCode2Error: Record<string, string> = { '403': I18n.t('...'), '423': I18n.t('...') } try { await dispatch(export(fpNumber, statusCode2Error, handleImportExportError)) } catch (error) { console.error(error) } finally { setIsExportAktionAktive(false) } }, [I18n, dispatch, handleImportExportError] )
方案二:将加载状态存入Slice(更优的集中式状态管理)
如果希望状态统一维护,避免组件分散管理状态,可以把加载状态移到Slice中:
步骤1:在Slice State中添加加载状态
interface ImportExportState { // 原有状态字段... isExportLoading: boolean } const initialState: ImportExportState = { // 原有初始值... isExportLoading: false }
步骤2:添加更新加载状态的Action
const importExportSlice = createSlice({ name: 'importExport', initialState, reducers: { // 原有reducer... setExportLoading: (state, action: PayloadAction<boolean>) => { state.isExportLoading = action.payload } } }) export const { setExportLoading } = importExportSlice.actions
步骤3:修改导出Thunk,自动管理加载状态
export const export = ( fpNumber?: number, errorMsg?: Record<string, string>, callback?: (status: string, errorMsg: Record<string, string>) => void ): AppThunk<Promise<void>> => async (dispatch) => { dispatch(setExportLoading(true)) try { await (fpNumber ? importExportApi.export(fpNumber) : importExportApi.export()) } catch (error) { const statusCode: string = error.response.status.toString() dispatch(setExportErrorStatusCode(statusCode)) callback?.(statusCode, errorMsg) } finally { dispatch(importExportProtokollLoad()) dispatch(setExportLoading(false)) } }
步骤4:组件中直接从Store获取加载状态
无需再维护组件内的isExportAktionAktive状态,直接从Store读取:
const isExportLoading = useSelector((state: RootState) => state.importExport.isExportLoading) const handleOnExport = useCallback( async (fpNumber?: number) => { const statusCode2Error: Record<string, string> = { '403': I18n.t('...'), '423': I18n.t('...') } try { await dispatch(export(fpNumber, statusCode2Error, handleImportExportError)) } catch (error) { console.error(error) } }, [I18n, dispatch, handleImportExportError] )
关于useCallback中async/await的说明
async函数作为useCallback的回调是完全合法的,只要依赖项数组配置正确就没有问题。所谓"不佳"的说法通常是指依赖项处理不当导致的不必要重渲染,只要你当前的依赖项[I18n, dispatch, handleImportExportError]是正确的,就无需担心。如果handleImportExportError是组件内定义的函数,记得用useCallback包裹它避免不必要的依赖变化。
内容的提问来源于stack exchange,提问作者physicsuser
相关产品推荐
相关产品推荐

