I'm working on a Rails/React/GraphQl
project and getting an Uncaught (in promise): Error: Cannot read property of undefined
in the RegisterUser mutation. I searched for similar questions on Google but couldn't find anything similar. I'm pretty new to React/GraphQL/Apollo
.
When there is a ActiveReacord
error it's been successfully logged to the console with this setup.
On a success
I get the success message plus the above mentioned Uncaught Error
printed to the console. Also, I see in rails console the new user was created, but the form hangs and doesn't get close (I'm assuming due to the error?).
Here's where the error is coming from: (at line .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
Not sure what causing this error, any suggestions are greatly appreciated. Thank you for your time.
UPDATE(S): 1/29/2020 issue was fixed based on @xadm's reply bellow.
1) Register
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
}
}
}
```