我正在使用redux-thunk
来使用异步操作创建者。结果也将返回给相应的调用者。
function fetchUserName(userId: number): Promise<string> {
return Promise.resolve(`User ${userId}`)
}
function requestUserName(userId: number) {
return (dispatch: Dispatch) => {
return fetchUserName(userId).then(name => {
dispatch({
type: 'SET_USERNAME',
payload: name,
})
})
}
}
这样,商店将得到更新,同时允许组件直接处理响应。
function User() {
const dispatch = useDispatch()
useEffect(() => {
dispatch(requestUserName(1))
.then(name => {
console.log(`user name is ${name}`)
})
.catch(reason => {
alert('failed fetching user name')
})
}, [])
}
这可以按预期工作,但是由于类型无效,TypeScript不会对其进行编译。
dispatch
返回的useDispatch
未被识别为返回Promise的函数,因此TypeScript认为Property 'then' does not exist on type '(dispatch: Dispatch<AnyAction>) => Promise<void>'.
。如何解决这种情况?
对于我来说,在useDispatch
周围创建包装器或重新定义dispatch
的类型对我来说是完全可以的,但是我不知道在这种特殊情况下该类型应该是什么样。
非常感谢您的任何建议。
答案 0 :(得分:12)
useDispatch
返回Dispatch
类型used by Redux,因此您只能使用它调度标准操作。要还分派重击动作,请将其类型声明为ThunkDispatch
(来自redux-thunk
)。
ThunkDispatch
接收存储状态extra thunk args和您的操作类型的类型参数。它允许调度ThunkAction
,这基本上是requestUserName
的内部功能。
例如,您可以这样输入:
import { ThunkDispatch } from "redux-thunk";
import { AnyAction } from "redux";
type State = { a: string }; // your state type
type AppDispatch = ThunkDispatch<State, any, AnyAction>;
// or restrict to specific actions instead of AnyAction
function User() {
const dispatch: AppDispatch = useDispatch();
useEffect(() => {
dispatch(requestUserName(1))
.then(...) // works now
}, []);
...
}
AppDispatch
也可以通过typeof store.dispatch
从商店inferred来>>
import thunk, { ThunkDispatch, ThunkMiddleware } from "redux-thunk";
const mw: ThunkMiddleware<State, AnyAction> = thunk;
const dummyReducer = (s: State | undefined, a: AnyAction) => ({} as State);
const store = createStore(dummyReducer, applyMiddleware(mw));
type AppDispatch = typeof store.dispatch // <-- get the type from store
答案 1 :(得分:-4)
您应该用dispatch
包裹Promise.resolve()
function User() {
const dispatch = useDispatch()
useEffect(() => {
Promise.resolve(dispatch(requestUserName(1)))
.then(name => {
console.log(`user name is ${name}`)
})
.catch(reason => {
alert('failed fetching user name')
})
}, [])
}