Skip to content
Advertisement

Weird error in react – using apollo/client – graphql

I’m developing a MERNG App, and everything is working fine so far, but i’m getting some errors in the fronted with useMutations, let me explain to you.

So, in the login/register part, if you leave fields empty or in the login, if your user is not found in the DB, it’ll give errors, and i receive those errors in the function onError(err), but, the problem is that, it gives me error always, and it said, Cannot read property ‘extensions’ of undefined, it gives that errors even if i have no errors, let me show you the code

import React, { useState } from "react";
import { useMutation, gql } from "@apollo/client";

import { useHistory } from "react-router-dom";
import { useDispatch } from "react-redux";

import {
  FormAuth,
  TitleAuth,
  TitleAuthImage,
  ContainInput,
  InputAuth,
  ContainSingleInput,
  ContainButtons,
  Button,
  ButtonSpan
} from "../../website/Auth/AuthStyled";

import instagram from "../../img/instagram.svg";
import Loading from "../Loading/Loading";

const Login = ({ setLogin }) => {
  const history = useHistory();
  const dispatch = useDispatch();

  const [userData, setUserData] = useState({
    email: "",
    password: ""
  });

  const [errors, setErrors] = useState({});

  const [addUser, { loading }] = useMutation(LOGIN_MUTATION, {
    update(
      _,
      {
        data: { login: data }
      }
    ) {
      dispatch({ type: "LOGIN", payload: data });
      history.push(`/profile/${data.id}`);
    },
    onError(err) {
      setErrors(err.graphQLErrors[0].extensions.exception.errors);
    },
    variables: userData
  });

  const handleSubmit = e => {
    e.preventDefault();
    addUser();
    setUserData({ email: "", password: "" });
  };

  // Framer motion animations

  const PopUp = {
    hidden: { x: 1000 },
    visible: {
      x: 0,
      transition: { duration: 0.7 }
    }
  };

  return (
    <>
      {!loading ? (
        <FormAuth
          onSubmit={handleSubmit}
          variants={PopUp}
          initial="hidden"
          animate="visible"
        >
          <TitleAuth>
            <TitleAuthImage src={instagram} />
          </TitleAuth>

          <ContainInput>
            <ContainSingleInput top="2rem">
              <InputAuth
                name="email"
                type="email"
                placeholder={errors.email ? errors.email : "Email"}
                maxLength="50"
                value={userData.email}
                onChange={e =>
                  setUserData({ ...userData, email: e.target.value })
                }
              />
            </ContainSingleInput>
            <ContainSingleInput top="7rem">
              <InputAuth
                name="password"
                type="password"
                placeholder={errors.password ? errors.password : "Password"}
                maxLength="50"
                value={userData.password}
                onChange={e =>
                  setUserData({ ...userData, password: e.target.value })
                }
              />
            </ContainSingleInput>
          </ContainInput>

          <ContainButtons>
            <Button
              type="submit"
              Login
              whileHover={{ scale: 1.1 }}
              whileTap={{ scale: 0.85 }}
            >
              Login
            </Button>
            <ButtonSpan
              Register
              whileHover={{ scale: 1.1 }}
              whileTap={{ scale: 0.85 }}
              onClick={() => setLogin(false)}
            >
              Register
            </ButtonSpan>
          </ContainButtons>
        </FormAuth>
      ) : (
        <Loading />
      )}
    </>
  );
};

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

export default Login;

This is how the login looks like, the credentials are correct there enter image description here

The error in the browser after clicking login

enter image description here

The weird part here is that, it was working before normally, but know it breaks, and i don’t know why or how, if i have errors they will appear in the input’s placeHolder, but know, it always breakes

Advertisement

Answer

According to the apollo docs onError for useMutation passes an ApolloError which contains several elements.

With your current implementation you assume there there is such a graphQLErrors element in the onError and that it is indeed populated with at least 1 element. This may not be the case. For that reason, when you attempt to access err.graphQLErrors[0] you get undefined which causes your particular error.

The docs recommend testing for evidence of a particular error before taking action:

onError(({graphQLErrors, networkError}) => {
    if (graphQLErrors)
        graphQLErrors.forEach(({message, locations, path}) =>
            console.log(
                `[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`,
            ),
        );

    if (networkError) {
        console.log(`[Network error]: ${networkError}`);
    }
});

Alternatively, you can use the built-in mechanism for tracking loading and error state

const [addUser,
    {loading: mutationLoading, error: mutationError}] = useMutation(LOGIN_MUTATION, {
    update(
        _,
        {
            data: {login: data}
        }
    ) {
        dispatch({type: "LOGIN", payload: data});
        history.push(`/profile/${data.id}`);
    },
    variables: userData
});
User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement