Ошибки правильно отображаются в Graphiql, но не возвращаются клиенту Apollo в ответном интерфейсе - PullRequest
0 голосов
/ 10 ноября 2019

Я намеренно оставил поле имени пустым (""), чтобы можно было проверить свою пользовательскую форму проверки ошибок на сервере GraphQL. Используя Graphiql, массив ошибок хорошо отображается. (String! только предотвращает null, а не "".)

Может кто-нибудь объяснить, почему ошибки не попадают в реальный компонент реакции и что делать, чтобы это исправить?

PS: Мутация работает отлично после заполнения полей. Он также обновляется с помощью только что созданной записи.

Панель запросов Graphiql

mutation addEmployee(
  $name: String!
  $position: String!
) {
  addEmployee(name: $name, position: $position) {
    name
    position
  }
}

query getEmployees {
  employees {
    _id
    name
    position
    createdAt
  }
}

Переменные запросов Graphiql: обратите внимание на пустое поле name.

{
  "name": "",
  "position": "CEO",
}

Результаты GraphiqlПанель - работает как положено.

{
  "errors": [
    {
      "message": "Field cannot be empty",
      "statusCode": 400
    }
  ],
  "data": {
    "addEmployee": null
  }
}

Консольный журнал getEmployeesQuery в компоненте реагирования показывает это:

called: true
error: undefined
fetchMore: ƒ (fetchMoreOptions)
loading: false
networkStatus: 7
refetch: ƒ (variables)
employees: (16) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
startPolling: ƒ (pollInterval)
stopPolling: ƒ ()
subscribeToMore: ƒ (options)
updateQuery: ƒ (mapFn)
variables: {}

Это моя мутация:

const Mutation = new GraphQLObjectType({
  name: "Mutation",
  fields: {
    addEmployee: {
      type: EmployeeType,
      args: {
        name: { type: new GraphQLNonNull(GraphQLString) },
        position: { type: new GraphQLNonNull(GraphQLString) },
      },
      resolve(parent, args) {
        let employee = new Employee({
          name: args.name,
          position: args.position,
        });
        let errors = [];

        try {
          if (!args.name) {
            errors.push("name");
          }
          if (errors.length) throw new Error(errorName.INVALID_FIELD);
          return employee.save();
        } catch (err) {
          throw new GraphQLError(err.message);
        }
      }
    }
  }
});

Это мой компонент:

const Employees = ({
  getEmployeesQuery: { employees, loading, errors },
  addEmployeeMutation
}) => {

  const [state, setState] = useState({
    name: "",
    position: "",
  });

  const showEmployee = id => () => {
    const employee = store.state.employees.find(v => v._id === id);
  };

  const handleChange = name => evt => {
    setState({ ...state, [name]: evt.target.value });
  };

  const addEmployee = () => {
    addEmployeeMutation({
      variables: {
        name: state.name,
        position: state.position,
      },
      refetchQueries: [{ query: getEmployeesQuery }]
    });
  };

  return (
    <div className={styles.root}>
      <h2>Employees</h2>
      <div className={styles.listContainer}>
        <header>
          <div>Employee Name</div>
          <div>Position</div>
        </header>
        <div className={styles.list}>
          {!loading ? (
            employees.map(v => (
              <Employee
                key={v._id}
                showEmployees={showEmployees(v._id)}
                position={v.position}
                id={v._id}
              />
            ))
          ) : (
            <Loader />
          )}
        </div>
      </div>
      {(errors || []).map((error, i) => (
        <div>{error.message}</div>
      ))}
      <EmployeeForm
        fields={state}
        handleChange={handleChange}
        submit={addEmployee}
      />
    </div>
  );
};

Employees.propTypes = {
  classes: PropTypes.object,
  route: PropTypes.string,
  name: PropTypes.string
};

export default compose(
  getEmployeesQuery,
  addEmployeeMutation
)(Employees);

Запросы:

import { gql } from "apollo-boost";
import { graphql } from "react-apollo";

export const getEmployeesQuery = graphql(
  gql`
    {
      employees {
        _id
        createdAt
        name
        position
      }
    }
  `,
  { name: "getEmployeesQuery" }
);

export const addEmployeeMutation = graphql(
  gql`
    mutation(
      $name: String!
      $position: String!
    ) {
      addEmployee(
        name: $name
        position: $position
      ) {
        _id
        createdAt
        name
        position
      }
    }
  `,
  { name: "addEmployeeMutation" }
);

Это становится длинным, но это последний. Promise. Вот index.js!

import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter } from "react-router-dom";

import "./index.css";
import App from "./layout/App";
import * as serviceWorker from "./serviceWorker";

import { ApolloProvider } from "react-apollo";
import { ApolloClient } from "apollo-client";
import { createHttpLink } from "apollo-link-http";
import { InMemoryCache } from "apollo-cache-inmemory";

const httpLink = createHttpLink({
  uri: "http://localhost:4000/graphql"
});

const client = new ApolloClient({
  link: httpLink,
  cache: new InMemoryCache()
});

ReactDOM.render(
  <ApolloProvider client={client}>
      <BrowserRouter>
        <App />
      </BrowserRouter>
  </ApolloProvider>,
  document.getElementById("root")
);

serviceWorker.register();

1 Ответ

0 голосов
/ 11 ноября 2019

Проблема была элементарной. Но для тех, кто попадает в ту же глупую ловушку. ,,Убедитесь, что вы запустили preventDefault() для события отправки. Действие по умолчанию перезагружало страницу при отправке, которая выполнялась только getEmployeesQuery. Вот почему на addEmployeeMutation ничего не существовало. preventDefault заставляет addEmployeeMutation возвращаться с ошибками.

Также убедитесь, что ошибки перехватываются при попытке / перехвате. Они не включены в реквизит. (Спасибо Длинный Нгуен ).

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

const addEmployee = async evt => {
    evt.preventDefault(); // This fixed it!
    try {
      await addEmployeeMutation({
        variables: {
          name: state.name,
          position: state.position,
        },
        refetchQueries: [{ query: queries.getEmployeesQuery }]
      });
    } catch (e) {
      setErrors([e.message]);
    }
  };
...