user18578945
user18578945

Reputation:

How to reset state when route changes?

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

Answers (1)

Andrea Costanzo
Andrea Costanzo

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:

  1. Update your reducer to manage the new action, otherwise is useless. I've not fully understood how it works otherwise I would have updated myself
  2. Usually, to keep the code "clean", the action should be stored in a separate file from the actual component and then imported.

Upvotes: 4

Related Questions