React router 4 history push component re render

Viewed 501

With redux-saga and react router 4. I am trying to implement a flow for user registration. I am focusing on the part where user is presented a registration screen on /user/register route.

GOAL

Goal is to update the status of user registration on this same screen as an Alert depending upon either the user created successfully or there already exists a user. I am using redux-saga and using history.push from saga to update the view.

PROBLEM

The alert is shown but only after I reload the /user/register page.

I am passing state to history.push from my saga and then in my component based on that state which I extract from this.props.location.state I prepare the content for alert.

Register Component

// Form submission handler
handleUserRegistration = user => {
   this.props.registerUser(user, this.props.history);
}

// Prepring the alert content
getAlertUI = signupState =>  {
   if (signupState.signupSuccess) {
       return <UncontrolledAlert color='success'>{'Verification email sent. Please verify your account.'}</UncontrolledAlert>
   }else {
       return <UncontrolledAlert color='danger'>{signupState.error.message}</UncontrolledAlert>
   }
}

render () {
  let alertContent = null;

  const signupResponse = this.props.location.state;
  if (signupResponse) {
   if (signupResponse.error) {
     alertContent = this.getAlertUI({signupSuccess: false, error: signupResponse.error});
   }else {
     if (signupResponse.verificationEmailSent) {
       alertContent = this.getAlertUI({signupSuccess: true})
     }
   }
  }

  return (
   <div> {alertContent} </div>
   // My form component goes here.
  )
}

While is my saga. I am using history.push with the necessary information.

saga.js

const registerWithEmailPasswordAsync = async (userData) =>

    await axios.post(apiUrls.SINGUP_USER, userData )
                    .then(response => {
                        return {
                            isError: false,
                            data: response.data,
                        }
                    })
                    .catch(error => {
                        return {
                            isError: true,
                            errorDetails: {
                                status: error.response ? error.response.status : null,
                                message: error.response ? error.response.data : null,
                            }
                        }
                    })

function* registerUser({ payload }) {
    const { history } = payload;
    try {
        const registerUser = yield call(registerWithEmailPasswordAsync, payload.user);
        if (!registerUser.isError) {
            history.push('/user/register', {verificationEmailSent: true});
        } else {
            if (registerUser.errorDetails) {
                history.push('/user/register', {error: registerUser.errorDetails} );
            }
        }
    } catch (error) {
        console.log('register error : ', error)
    }
}

I am pretty new to this, Please share if this is the better approach or not? And if it is why isn't it updating my view. Any pointers are highly appreciated.

1 Answers
  1. Don't use history.push just to update state The only reason I could see you using history.push from within the saga is for sending the user to a dashboard/verification page after a successful sign up. There is no reason to use history.push just to pass some state to the component dynamically. Update your redux state by dispatching an action, not using history.push

  2. You don't necessarily have to update state to notify the user of a sign-up error You asked if your general approach was the best. Personally, I don't think it is. I wouldn't work that hard. Just use something like react-toastify. You can then just place a ToastContainer in your App component, then call toastify(successMessage/error)

Related