Rails / GraphQL: Uncaught (в обещании): ошибка: невозможно прочитать свойство undefined - PullRequest
0 голосов
/ 27 января 2020

Я работаю над проектом Rails/React/GraphQl и получаю Uncaught (in promise): Error: Cannot read property of undefined в мутации RegisterUser. Я искал похожие вопросы в Google, но не смог найти ничего похожего. Я довольно новичок в React/GraphQL/Apollo.

Когда есть ошибка ActiveReacord, она была успешно зарегистрирована на консоли с этой настройкой.

На success я получаю сообщение об успехе плюс вышеупомянутый Uncaught Error напечатан на консоли. Кроме того, я вижу в консоли rails новый пользователь был создан, но форма зависает и не закрывается (я полагаю, из-за ошибки?).

Вот откуда исходит ошибка: ( в строке .then(({ data: { registerUser: { success, errors: [{ message }] } } }) =>)

RegisterUser / index. js:

import React, { useState } from 'react';
import { useHistory } from "react-router-dom";
import { Mutation } from 'react-apollo';
import { Register } from './operations.graphql';


const RegisterUser = () => {
  const isLoggedIn = JSON.parse(sessionStorage.getItem('isLoggedIn'));
  const history = useHistory();
  const [username, setUsername] = useState("");
  const [password, setPassword] = useState("");
  const [email, setEmail] = useState("");

  const onCompleted = (resp) => {
    console.log(resp.registerUser.success);
  }

  const onError = (message) => {
    console.log(message);
  }

    if(!isLoggedIn) {
      return (
        <Mutation mutation={Register} onCompleted={onCompleted}>
          {(registerUser, { loading, error }) => (
            <div className="card bg-light col-md-4 offset-md-4 shadow p-3 mb-5 rounded">
              <article className="card-body mx-auto" style={{maxWidth: '400px'}}>
                <p className="text-center">Create an account</p>
                <form onSubmit={ e => {
                    e.preventDefault();
                    registerUser({
                      variables: {
                        username: username,
                        password: password,
                        email:    email,
                      }
                    }).then(({ data: { registerUser: { success, errors: [{ message }] } } }) => {
                      if (success) {
                        history.push("/login");
                      } else {
                        onError(message);
                      }
                    });
                  }}
                >
                  <div className="form-group input-group">
                    <input
                      type="text"
                      value={username}
                      className="form-control"
                      onChange={e => setUsername(e.target.value)}
                      placeholder="username"
                      required
                    />
                  </div>
                  <div className={"form-group input-group"}>
                    <input
                      type="email"
                      value={email}
                      className="form-control"
                      onChange={e => setEmail(e.target.value)}
                      placeholder="email"
                      required
                    />
                  </div>
                  <div className="form-group input-group">
                    <input
                      type="password"
                      value={password}
                      className="form-control"
                      onChange={e => setPassword(e.target.value)}
                      placeholder="password"
                      required
                    />
                  </div>
                  <input type="submit" className="btn btn-primary btn-block" value="Sign up!" />
                  <p className="text-center">Have an account? <a href="/login">Log In</a> </p>
                </form>
              </article>
              {loading && <p>Loading...</p>}
              {error && <p>Error! Please try again</p>}
            </div>
          )}
        </Mutation>
      );
    }
}
export default RegisterUser;

register_user.rb:

module Mutations
  class RegisterUser < Mutations::BaseMutation
    graphql_name "RegisterUser"

    argument :attributes, Types::UserRegistrationAttributes, required: true

    field :user, Types::UserType, null: true

    def resolve(attributes:)
      user = User.new(username: attributes[:username],
                      password: attributes[:password],
                      email: attributes[:email])
      if user.save
        # current_user needs to be set so authenticationToken can be returned
        context[:current_user] = user
        {
          user: user,
          errors: [],
          success: "Sign up successfull. Please confirm your email",
        }
      else
        user_errors = user.errors.messages.map do |key, message|
          path = ["attributes", key.to_s.camelize(:lower)]
          {
            path: path,
            message: "#{key.to_s.camelize} #{message}",
          }
        end
        {
          user: user,
          errors: user_errors,
        }
      end
    end
  end
end

base_mutation.rb:

module Mutations
  # This class is used as a parent for all mutations, and it is the place to have common utilities
  class BaseMutation < GraphQL::Schema::Mutation

    field :success, String, null: true
    field :errors, [Types::UserErrorType], null: true

    protected

    def authorize_user
      return true if context[:current_user].present?

      raise GraphQL::ExecutionError, "User not signed in"
    end
  end
end

user_error_type.rb:

module Types
  class UserErrorType < Types::BaseObject
    description "A user-readable error"

    field :message, String, null: true, description: "A description of the error"
    field :path, [String], null: true, description: "Which input value this error came from"
  end
end

Не уверен, что вызывает эту ошибку, любой предложения с благодарностью. Спасибо за ваше время.

ОБНОВЛЕНИЕ (S): 1/29/2020 проблема была исправлена ​​на основе ответа @ xadm ниже.

1) Регистрация

operations.graphql

mutation Register($username: String!, $password: String!, $email: String!) {
  __typename
  registerUser(attributes: {username: $username, password: $password, email: $email}) {
    user {
      id
      username
      authenticationToken
    }
    success
    errors {
      message
      path
    }
  }
}
```

1 Ответ

1 голос
/ 28 января 2020

Проверка на внешнем инструменте доказывает, что это не [вполне] реакция / ошибка Аполлона.

Это не стандартная обработка ошибок - необязательные элементы (сообщения), выраженные в мутации, ожидаемые в ответе. Аналогичная проблема с использованием UNION: useQuery возвращает неопределенное значение, но возвращает данные на gql детской площадке

Ошибка, на которую вы указываете:

Вот где возникает ошибка from: (в строке .then (({data: {registerUser: {success, errors: [{message}]}}}) =>)

является примером "too optimisti c destructuring ", не отказоустойчивый (не останавливается на NULL), измените его на

.then(({ data: { registerUser: { success, errors } } }) =>)

и обработайте errors в теле - это массив, поэтому нет message параметра.

...