我有一个自定义钩子,该钩子包装了react-redux
的{{1}}方法,如果被拒绝,则通知我。问题是我无法推断已解析的类型。
useDispatch
// useAction
type AnyFn = (...s: any[]) => any;
export default <T extends AnyFn>(actionCreator: T) => {
const dispatch = useDispatch<(action: any) => Promise<any>>(); // * Note Promise<any>
const action = useCallback((...args: Parameters<typeof actionCreator>) => {
return dispatch(actionCreator(...args))
.then(result => {
return unwrapResult(result) // @reduxjs/toolkit
})
.catch(err => {
// the reason this hook is needed
// notify error ... then
return Promise.reject(err)
})
}, [dispatch])
return [action] as const;
}
那么,如何键入// action
const fetchUsersActionCreator = createAsyncThunk(
'fetch', (id: number) => Promise.resolve([id]) // return type IUser[]
)
// consumer
const [fetchUsers] = useAction(fetchUsersActionCreator);
useEffect(() => {
fetchUsers()
.then((result) => {
console.log(result.length) // Property 'length' does not exist on type PayloadAction<IUser[]...
})
}, [fetchUsers])
// But if I unwrap results here the result type is inferred correctly
useEffect(() => {
fetchUsers()
.then(unwrapResult)
.then((result) => {
console.log(result.length) // OK
})
}, [fetchUsers])
钩子,以便从useAction
的返回类型中推断出已解析的类型?我知道它与unwrapResult
的类型有关,但是我无法动弹……
感谢您的帮助
编辑:我已指定操作为异步重击
答案 0 :(得分:0)
如果您使用的类型为described in the docs的useDispatch
类型,我认为您的问题已经解决了:
import { configureStore } from '@reduxjs/toolkit'
import { useDispatch } from 'react-redux'
import rootReducer from './rootReducer'
const store = configureStore({
reducer: rootReducer
})
export type AppDispatch = typeof store.dispatch
export const useAppDispatch = () => useDispatch<AppDispatch>() // Export a hook that can be reused to resolve types
如果这样做没有帮助,则可以复制并使用the RTK source中的PayloadForActionTypesExcludingErrorActions
类型,但是请记住,此行为在this PR的下一个发行版中会稍有变化将被合并。如果您需要复制该类型,则可能需要在下一个版本中进行调整。
答案 1 :(得分:0)
您的action
钩子中的useAction
函数是一个函数,其参数与actionCreator
相同,并返回一个解析为Promise
的{{1}}创建的操作的属性。
我不喜欢这里的所有反向推论,也不知道为什么您返回一个1长度元组而不是直接返回函数,但是这种返回类型应该基于当前代码工作。如果从退货中删除payload
,则可以删除readonly
。
as const
我会这样写:
const useAction = <T extends AnyFn>(
actionCreator: T
): readonly [(...args: Parameters<typeof actionCreator>) => Promise<ReturnType<typeof actionCreator>['payload']>]
答案 2 :(得分:0)
我要回答我自己的问题,这可能对其他尝试实现相同功能的人很有用。
感谢@phry和@ linda-paiste的回答,因为它为我指明了正确的方向。
import { unwrapResult, AsyncThunk } from '@reduxjs/toolkit';
import { AppDispatch } from '../store'; // type AppDispatch = typeof store.dispatch
// useAction aka useAsyncThunk
export default <Arg, Returned>(
actionCreator: AsyncThunk<Returned, Arg, {}>
) => {
const dispatch = useDispatch<AppDispatch>();
return useCallback((arg: Arg) => {
return dispatch(actionCreator(arg))
.then(result => {
return unwrapResult(result) // @reduxjs/toolkit
})
.catch(err => {
// the reason this hook is needed
// notify error ... then
return Promise.reject(err)
})
}, [dispatch, actionCreator])
};