Niccolò Caselli
Niccolò Caselli

Reputation: 882

Show errors received from my server with react-redux

If I perform all authentication requests to my API not directly inside the "handleSubmit" function of react-redux but in a custom redux action, I have the problem of going to show any errors received by the server as a reply.

This is the authentication action (authActions.js):

export const loginUser = userData => dispatch => {
  axios
    .post("auth/local/signin")
    .then(res => {

      dispatch({
        type: SET_CURRENT_USER,
        payload: res
      });
    })
    .catch(err => {

      dispatch({
        type: GET_ERRORS,
        payload: err.response.data
      });
    });
};

authReducer.js

import { SET_CURRENT_USER } from "../actions/types";

const initialState = {
  isAuthenticated: false,
  user: {}
};

export default function(state = initialState, action) {
  switch (action.type) {
    case SET_CURRENT_USER:
      return {
        ...state,
        isAuthenticated: Object.keys(action.payload).length > 0,
        user: action.payload
      };

    default:
      return state;
  }
}

errorReducer.js

  import { GET_ERRORS, CLEAR_ERRORS } from "../actions/types";

    const initialState = {};

    export default function(state = initialState, action) {
      switch (action.type) {
        case GET_ERRORS:
          return action.payload;
        case CLEAR_ERRORS:
          return {};
        default:
          return state;
      }
    }

The only thing that came to mind is then to connect to redux, as well as redux-form, the component and then go to report a possible error through "new SubmissionError (errors)". But this does not work on the first submit.

class SignInForm extends Component {

  handleSubmit = values => {
    const userData = {
      username: values.username,
      password: values.password
    };

    this.props.loginUser(userData);

    const { errors } = this.props;
    console.log(errors);

    errors.username = errors.user;

    if (errors) throw new SubmissionError(errors);
  };

  render() {
    const { valid, handleSubmit, submitting } = this.props;

    return (
      <View>
      ...
      </View>
    );
  }
}

const mapStateToProps = state => ({
  auth: state.auth,
  errors: state.errors
});

const form = reduxForm({
  form: "Login", 
  validate, 
  asyncValidate,
  asyncChangeFields: ["username"]
})(SignInForm);

export default connect(
  mapStateToProps,
  { loginUser }
)(form);

Upvotes: 0

Views: 315

Answers (1)

Shawn Andrews
Shawn Andrews

Reputation: 1442

You could use Promises to pass the result back to the signin component. Now that you're in the signin component you can show the error to the user, if it failed.

authActions.js

export const loginUser = userData => dispatch => {
    return new Promise((resolve, reject) => {
        axios
        .post("auth/local/signin")
        .then(res => {

          dispatch({
            type: SET_CURRENT_USER,
            payload: res
          });
          return resolve();
        })
        .catch(err => {
          return reject(err);
        });
    });
}

signin.js (?)

handleSubmit = values => {
    const userData = {
      username: values.username,
      password: values.password
    };

    this.props.loginUser(userData)
        .catch((err) => {
            this.setState({ errorMsg: err });
        });

};

render() {
    const { valid, handleSubmit, submitting } = this.props;

    return (
      <View>
          ...
          <div>Failed to login with error message: {this.state.errorMsg}</div>
      </View>
    );
}

Upvotes: 1

Related Questions