I'm beginner with React/Redux. I want to authenticate a User and display a notification on my app when error occurs.
This is my login function:
const [loading, setLoading] = useState(false);
const dispatch = useDispatch();
const handleSignIn = (values: SignInOpts, setSubmitting: any) => {
setLoading(true);
dispatch(authenticationActions.signInAndFetchUser(values))
.then(res => {
console.log("SignIn Success");
setLoading(false);
})
.catch(err => {
console.log("SignIn Failure");
setLoading(false);
showErrorNotification(
"Error notification"
);
});
};
My action:
export const signInAndFetchUser = (credentials: SignInOpts) => {
return (dispatch, getState) => {
return dispatch(signIn(credentials)).then(res => {
const token = getState().authentication.token;
return dispatch(getMe(token));
});
};
};
The error I have :

How can I perform this ?
Generally for thunks, dispatch(myThunk()) will return whatever the thunk returns and can be a Promise, as also the case in your signInAndFetchUser method.
The problem is that the normal useDispatch hook typings do not know which middlewares you are using and thus have no overload for that behaviour.
That is why the Redux TypeScript Quickstart Tutorial recommends you define your own, correctly-typed hooks:
// Use throughout your app instead of plain `useDispatch` and `useSelector`
export const useAppDispatch = () => useDispatch<AppDispatch>()
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector
If you are using the official Redux Toolkit (especially with TypeScript, you definitely should as it cuts out almost all type annotations), you can just get
export type AppDispatch = typeof store.dispatch
If you are using old-style vanilla Redux, just use ThunkDispatch as AppDispatch.
Most of your work should happen in the thunk (the action). dispatch does not return a promise. So you have to handle your promise inside your thunk and dispatch the corresponding action, it will then be send to the reducer. The new state will reflects the changes.
Here is a thunk which should give you an idea of how it works :
export const signInAndFetchUser = (credentials: SignInOpts) => {
return (dispatch, getState) => {
dispatch(action.startLoading);
signIn(credentials)
.then((res) => {
// do something with res : maybe recover token, and store it to the store ?
// if the token is in the store already why do you need to signIn ?
dispatch(action.signedInSuccess(res.token));
getMe(res.token)
.then((user) => {
dispatch(action.getMeSucceded(user));
})
.catch((err) => dispatch(action.getMeFailed(err)));
})
.catch((err) => dispatch(action.signInFailed(err)));
};
};
Or using async/await :
export const signInAndFetchUser = (credentials: SignInOpts) => {
return async (dispatch, getState) => {
dispatch(action.startLoading);
try {
const res = await signIn(credentials);
dispatch(action.signedInSuccess(res.token));
try {
const user = await getMe(res.token);
dispatch(action.getMeSucceded(user));
} catch (err) {
dispatch(action.getMeFailed(err));
}
} catch {
dispatch(action.signInFailed(err));
}
};
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With