user8353384
user8353384

Reputation:

How to handle GraphQL errors with React-Apollo?

I'm trying to move from Rest API to GraphQL using Express + Mongoose on server and React + Apollo on client.

async resolve(_, { email, password, passwordConfirmation }) { // Sign Up mutation
            const user = new User({ email });
            user.password = password;
            user.passwordConfirmation = passwordConfirmation;
            try{
                const createdUser = await user.save();
                return createdUser;
            } catch(error) {
                console.log(error); // Returns errors object like {email: {message: 'E-mail is required'}}
                throw new Error(error); // But on the client there is a string with all errors
            }
        }`

How can I handle the whole object of errors on the client?

Upvotes: 5

Views: 2859

Answers (2)

Hemant Parashar
Hemant Parashar

Reputation: 3774

You can also use renderProps in react-apollo which gives you error and loading states in an object in the second argument.

import React, { Component } from 'react';
import { Mutation } from 'react-apollo';
import gql from 'graphql-tag';
import Error from './ErrorMessage';

const LOGIN_MUTATION = gql`
  mutation LOGIN_MUTATION($email: String!, $password: String!) {
    signin(email: $email, password: $password) {
      id
      email
      name
    }
  }
`;

class Login extends Component {
  state = {
    name: '',
    password: '',
    email: '',
  };
  saveToState = e => {
    this.setState({ [e.target.name]: e.target.value });
  };
  render() {
    return (
      <Mutation
        mutation={LOGIN_MUTATION}
        variables={this.state}
      >
        {(login, { error, loading }) => (
          <form
            method="post"
            onSubmit={async e => {
              e.preventDefault();
              await login();
              this.setState({ name: '', email: '', password: '' });
            }}
          >
            <fieldset disabled={loading}>
              <h2>Sign into your account</h2>
              <Error error={error} />
              <label htmlFor="email">
                Email
                <input
                  type="email"
                  name="email"
                  placeholder="email"
                  value={this.state.email}
                  onChange={this.saveToState}
                />
              </label>
              <label htmlFor="password">
                Password
                <input
                  type="password"
                  name="password"
                  placeholder="password"
                  value={this.state.password}
                  onChange={this.saveToState}
                />
              </label>

              <button type="submit">Sign In!</button>
            </fieldset>
          </form>
        )}
      </Mutation>
    );
  }
}

export default Login;

Hope this helps!

Upvotes: 1

Mjuice
Mjuice

Reputation: 1288

The Apollo client returns a promise when you make a mutation. The errors from that promise can be accessed in the catch block of the mutation's resultant promise. See my example below.

If there are errors from my login mutation, I will access them in the catch block of the promise that is returned and then set those errors to local state in the component. From there the errors can be rendered if they exist, or even passed down to a child component to be rendered if you like. Please note that errors are usually returned in an array.

class LoginForm extends Component {
  constructor(props) {
    super(props);

    this.state = { errors: [] };
  }


  onSubmit({ email, password }) {
    this.props.mutate({
      variables: { email, password },
      refetchQueries: [{ query }]
    }).catch(res => {
      const errors = res.graphQLErrors.map(error => error.message);
      this.setState({ errors });
    });
  }

  render() {
    return (
      <div>
        <AuthForm
          errors={this.state.errors}
          onSubmit={this.onSubmit.bind(this)}
        />
      </div>
    );
  }
}

export default graphql(query)(
  graphql(mutation)(LoginForm)
);

Upvotes: 6

Related Questions