React Component not getting the updated state from the reducer

106 Views Asked by At

I am new to react and trying the redux hooks for the first time and got stuck in this issue for a day. Finally thought of putting in the forum. I am attaching the screenshots of the code here.

When I submit the form, the success scenario is working pretty fine. It is sending the request to the backend where the user is getting saved correctly to DB! The issue is with the error case, where the user submits a form with already taken email. In this case, the if block of (auth.error) is not invoking as the state is not getting an error object from the reducer.

const Signup = () => {
  debug('In the Render shit!');
  const auth = useSelector((state) => state, shallowEqual);
  const dispatch = useDispatch();
  const [values, setValues] = useState({
    name: 'Rahul',
    lastname: 'Kodu',
    email: '[email protected]',
    password: '12345',
    success: false,
  });

  const { name, email, password, success, lastname } = values;

  const handleChange = (event) => {
    setValues({
      ...values,
      [event.target.name]: event.target.value,
    });
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    //make thunk call here
    debug('Submit Button Clicked');
    const user = { name, email, password, lastname };
    dispatch(signUpUser(user))
      .then(() => {
        debug('In then of thunk!');
        //Finale
        debug(auth);
        if (auth.error) {
          setValues({ ...values, success: false });
          toast.error('Email Already Taken');
        } else {
          toast.info(' Signed Up! Now Sign in!');
          setValues({
            email: '',
            password: '',
            name: '',
            lastname: '',
            success: true,
          });
        }
        //finale
      })
      .catch((err) => {
        debug('In err of thunk' + err);
      });
  };
  const successMessage = () => {
    if (success) {
      return <Redirect to="/signin"></Redirect>;
    }
  };

  const signUpForm = () => {
    return (
      <div className="row">
        <div className="col-md-6 offset-sm-3 text-left">
          <form onSubmit={handleSubmit}>
            <div className="form-group">
              <label htmlFor="name-field">Name</label>
              <input
                className="form-control"
                type="text"
                id="name-field"
                name="name"
                value={name}
                onChange={handleChange}
                required
              />
            </div>
            <div className="form-group">
              <label htmlFor="name-field">Last name</label>
              <input
                className="form-control"
                type="text"
                id="lastname-field"
                name="lastname"
                value={lastname}
                onChange={handleChange}
                required
              />
            </div>
            <div className="form-group">
              <label htmlFor="email-field">Email</label>
              <input
                className="form-control"
                type="email"
                id="email-field"
                name="email"
                value={email}
                onChange={handleChange}
                required
              />
            </div>
            <div className="form-group">
              <label htmlFor="password-field">Password</label>
              <input
                className="form-control"
                type="password"
                id="password-field"
                name="password"
                value={password}
                onChange={handleChange}
                required
              />
            </div>
            <div className="form-group">
              <button
                type="submit"
                className="btn btn-sm btn-custom btn-block mt-5"
              >
                Sign-up!
              </button>
            </div>
          </form>
        </div>
      </div>
    );
  };

  return (
    <Base title="Signup Page" description="Exisitng user? Goto Signin">
      {JSON.stringify(auth)}
      {signUpForm()}
      {successMessage()}
    </Base>
  );
};

The async part of the action. The thunk part is as below. The error part of promise is giving an issue.

//thunk
export const signUpUser = (user) => {
  return function (dispatch) {
    dispatch(beginApiCall());

    const options = {
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
      },
    };

    return axios
      .post(config.API + 'signup', user, options)
      .then((response) => {
        debug('In success of axios');
        dispatch(signUpUserSuccess(response.data));
      })
      .catch((err) => {
        debug('In err of axios');
        dispatch(signUpUserFailure(err.response.data));
        dispatch(apiCallError());
      });
  };
};

In the reducer, I am returning a new object for failure cases(SIGNUP_USER_FAILURE) using the spread syntax to play by the immutability rules.

const authReducer = (state = initialState.auth, action) => {
  switch (action.type) {
    case types.LOAD_PROFILE:
      if (!action.newAuth) {
        action.newAuth = state;
      }
      return action.newAuth;

    case types.SIGNUP_USER_SUCCESS:
      if (!action.user) {
        action.user = state;
      }
      debug(action.user);
      return { ...action.user };
    case types.SIGNUP_USER_FAILURE:
      return { ...state, ...action.error };
    default:
      return state;
  }
};

However, the state is updated in the reducer, but the component is not getting the updated state to take an action. But after the next rendering, the component is getting the data. I am thinking there is something going wrong with the rendering. Please help me here. I

0

There are 0 best solutions below