Reputation:
I am having a problem with redux state. The state won't reset after route change. I have a component with "ForgottenPassword ", when I type in email and click on "reminde password" there is alert with text "Email have been send" (if success) or "Error occured" (if email is incorrect). When I go to login component and then comeback to "ForgottenPassword" component the alert with text (success or error) is still there cause the state did not reset. Is there a way to listen to route change and set state to initial so the success or error message would dissapear after route change?
const ForgottenPassword = (props: Props) => {
const { loginUserLoading = false, forgottenPasswordAsync } = props;
const t = useTranslationById();
const formik = useFormik({
initialValues: {
email: "",
},
onSubmit: (values: ForgottenPasswordParams) => {
forgottenPasswordAsync(values);
},
});
React.useEffect(() => {
if (props.forgotPasswordLoadingSuccess) {
formik.resetForm();
}
}, [props.forgotPasswordLoadingSuccess]);
const handleSubmitButton = React.useCallback(() => formik.handleSubmit(), [formik]);
return (
<div className={styles["forgotten-password-form"]}>
<div className={styles["forgotten-password-form__title"]}>{t("user-forgotten-password__title")}</div>
<form onSubmit={formik.handleSubmit}>
<Input
label={t("user-login__email-label")}
placeholder={t("user-login__email-label")}
name="email"
type="text"
/>
{props.forgotPasswordLoadingError && <div className={styles["forgotten-password-form__error"]}><FormattedMessage id="user-recover-password-error" /></div>}
{props.forgotPasswordLoadingSuccess && <div className={styles["forgotten-password-form__success"]}><FormattedMessage id="user-recover-password-email-send" /></div>}
<Button>
Remind password
</Button>
</form>
</div>
);
};
export default ForgottenPassword;
export const forgottenPassword = createAsyncAction(
"FORGOTTEN_PASSWORD_REQUEST",
"FORGOTTEN_PASSWORD_SUCCESS",
"FORGOTTEN_PASSWORD_FAILURE"
)<void, any, ApiError>();
const reducer = (state: UserState = {}, action: UserAction) => {
return produce(state, (draft) => {
switch (action.type) {
case getType(forgottenPassword.request):
draft.forgottenPasswordLoading = true;
break;
case getType(forgottenPassword.success):
draft.forgottenPasswordLoading = false;
draft.forgottenPasswordLoadingSuccess = true;
break;
case getType(forgottenPassword.failure):
draft.forgottenPasswordLoading = false;
draft.forgottenPasswordLoadingError = action.payload;
break;
}
});
};
const mapStateToProps = (state: RootState) => ({
forgotPasswordLoading: selectForgotPasswordLoading(state),
forgotPasswordLoadingSuccess: selectForgotPasswordLoadingSuccess(state),
forgotPasswordLoadingError: selectForgotPasswordLoadingError(state),
loginUserLoading: selectLoginUserLoading(state),
loginUserLoadingError: selectLoginUserLoadingError(state),
});
const mapDispatchToProps = (dispatch: Dispatch) =>
bindActionCreators(
{
forgottenPasswordAsync,
},
dispatch
);
export default connect(mapStateToProps, mapDispatchToProps)(ForgottenPassword);
export const selectForgotPasswordLoading = createSelector(selectState, (state) => state.forgottenPasswordLoading);
export const selectForgotPasswordLoadingSuccess = createSelector(selectState, (state) => state.forgottenPasswordLoadingSuccess);
export const selectForgotPasswordLoadingError = createSelector(selectState, (state) => state.forgottenPasswordLoadingError);
I am new here so sorry if I ask incorrectly. The code is very complex and it is hard to paste only a sample of the code.
I was trying to do if else statemnt in Forgotten component but I figure out it won't work cause it is a problem that lies in redux, which I am starting to learn.
Upvotes: 2
Views: 5064
Reputation: 2215
If you want to reset the state when the route is changed you can use the useEffect
hook in the role of a componentWillUnmount
in the page that is getting destroyed (in this case I suppose it is ForgottenPassword
).
You can manage the reset as you prefer. A solution can be adding an action to your redux state like FORGOTTEN_PASSWORD_RESET
which resets the state, and then dispatching the action from the hook.
You can write:
//ForgottenPassword.jsx
const ForgottenPassword = () => {
//existing code...
React.useEffect(()=>{
return () => {
//This will be called only when the page is destroyed.
reset() //reset your redux state here...
}
},[])
return (
//component's code...
);
}
const mapDispatchToProps = (dispatch) => {
return ({
reset: () => dispatch({ type: "FORGOTTEN_PASSWORD_RESET"}),
//OTHER ACTIONS....
})
}
export default connect(mapStateToProps, mapDispatchToProps)(ForgottenPassword);
TWO NOTES on the code above:
Upvotes: 4