[英]How to return a promise from redux thunk action and consume it in component
我正在使用 React+Redux+Redux Thunk + Firebase 身份驗證。 在 Typescript 中編寫代碼。 我的行動是:
//Type for redux-thunk. return type for rdux-thunk action creators
type AppThunk<ReturnType = void> = ThunkAction<
ReturnType,
IStoreState, //my store state
null,
Action<userActionTypes>
>
export const signInWithEmailAndPasword =(email:string, pasword:string): AppThunk=>{
return async (dispatch)=>{
auth.signInWithEmailAndPassword(email, pasword).then(response=>{
if(response.user){
const docRef = db.collection("users").doc(response.user.uid);
docRef.get().then(function(doc) {
if (doc.exists) {
const userData = doc.data(); //user data from firebase DB
//if user exists in DB, dispatch
dispatch({
type: userActionTypes.SIGN_IN_USER,
payload: userData
})
return userData;
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
}).catch(function(error) {
console.log("Error getting document:", error);
});
}
})
.catch(err=> dispatch(setUserError(err.message)))
}
}
我的 SignIn 組件,我將在其中發送上述操作:
import React, { useState } from 'react'
//some other imports
//...
//
import { useDispatch, useSelector } from 'react-redux';
import { signInWithEmailAndPasword } from '../../redux/actions/userActions';
interface ISignInState {
email: string;
password: string;
}
const SignIn = (props:any) => {
const [values, setValues] = useState<ISignInState>({ email: '', password: '' })
const dispatch = useDispatch();
const handleInputChange = (e: React.FormEvent<HTMLInputElement>): void => {
const { name, value } = e.currentTarget;
setValues({ ...values, [name]: value })
}
const handleFormSubmit = (e: React.FormEvent) => {
e.preventDefault()
const { email, password } = values;
dispatch(signInWithEmailAndPasword(email, password))
//// -> gives error: Property 'then' does not exist on
//// type 'ThunkAction<void, IStoreState, null, Action<userActionTypes>>'
.then(()=>{
props.history.push('/');
setValues({ email: '', password: '' })
})
}
return (<div>Sign in UI JSX stuff</div>)
因此,當我嘗試在dispatch(signInWithEmailAndPasword(email, password))
.then()
之后使用 .then() 時,它給出了一個錯誤Property 'then' does not exist on type 'ThunkAction<void, IStoreState, null, Action<userActionTypes>>'
那么如何我可以從 redux 操作返回承諾並在其上鏈接.then()
嗎? 我一直認為默認情況下 thunk 操作會返回 promises。 感謝您的幫助 編輯:臨時解決方案是使用any
作為上述操作的返回類型:
export const signInWithEmailAndPasword = (email:string, pasword:string):any =>{
return async (dispatch: any)=>{
try {
const response = await auth.signInWithEmailAndPassword(email, pasword)
if(response.user){
const userInDb = await getUserFromDB(response.user)
dispatch(userSignIn(userInDb))
return userInDb
}
} catch (error) {
dispatch(setUserError(error.message))
}
}
}
但我不想使用any
只需在此行之前添加return
:
auth.signInWithEmailAndPassword(email, pasword).then(response=>{
所以它會是:
export const signInWithEmailAndPasword =(email:string, pasword:string): AppThunk=>{
return async (dispatch)=>{
return auth.signInWithEmailAndPassword(email, pasword).then(response=>{
它應該工作。
AppThunk<Promise<void>>
您需要顯式聲明 AppThunks 返回類型,在本例中應該是一個什么都不包含的Promise
。 您已經將其設為異步,因此只需確保輸入正確的 AppThunk 返回類型
export const signInWithEmailAndPassword = (email: string, password: string): AppThunk<Promise<void>> => {
return async (dispatch) => {
// do stuff
}
}
Thunks 返回函數,而不是承諾。 為此,您可以查看redux-promise
。 但老實說,如果你做這么復雜的事情,你最好使用redux-saga
。
另一種方法是使用redux-api-middleware
背后的概念來創建您自己的自定義 redux 中間件。 我過去這樣做是為了將消息隊列連接到 redux。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.