WPGraphQL useMutation GraphQL error: Unknown argument "username" on field "registerUser" of type "RootMutation"

1.7k views Asked by At

I'm building a headless wordpress website using react, nextjs and wpgraphql. I'm trying to create a mutation to register user, but I'm getting the following errors after submitting my form:

Error: GraphQL error: Unknown argument "username" on field "registerUser" of type "RootMutation".
GraphQL error: Unknown argument "email" on field "registerUser" of type "RootMutation".
GraphQL error: Unknown argument "clientMutationId" on field "registerUser" of type "RootMutation".
GraphQL error: Field "registerUser" argument "input" of type "RegisterUserInput!" is required but not provided.

Everything works as expected when I test the mutation directly in wordpress using the GraphiQL:

mutation registerUser {
  registerUser(input: {username: "new_user", clientMutationId: "39slh", email: "[email protected]"}) {
    user {
      id
      name
    }
  }
}

This is the code I'm using:

import React, { useState } from 'react';
import { useMutation } from '@apollo/react-hooks';
import { gql } from 'apollo-boost';
import Layout from '../components/Layout';
import withData from '../lib/apollo';

const CREATE_USER = gql`
mutation registerUser {
    registerUser(input: {$name, $mutation, $email}) {
      user {
        id
        name
      }
    }
  }`;

const Login = () => {
    const [email, setEmail] = useState('');
    const [name, setName] = useState('');
    const mutation = 'reslkj3sd';
    const [createUser, { loading, error }] = useMutation(CREATE_USER);

    const updateEmail = (value) => {
        setEmail(value);
    };
    const updateName = (value) => {
        setName(value);
    };

    const handleCreateUser = (event) => {
        event.preventDefault();
        createUser({ variables: { name, mutation, email } });
    };

    return (
        <Layout>
            <form onSubmit={handleCreateUser}>
                <input type="email" value={email} onChange={(e) => { updateEmail(e.target.value) }} />
                <input type="text" value={name} onChange={(e) => { updateName(e.target.value) }} />
                <input type="submit"></input>
                {error && <p>{error.message}</p>}
            </form>
        </Layout>
    );
};

export default withData(Login);

I appreciate any help I can get to get this to work.

1

There are 1 answers

0
Andrew Ross On

Those GraphQL variables need to be defined before they are passed in. Think of the GraphQL schema as an object. The values injected on the return line are always defined using GraphQL values in the line immediately preceding that. For example

// query DocumentNode
const GET_ALL_AUTHORS = gql`
    query GetAllAuthors(
        $order: OrderEnum!
        $field: PostObjectsConnectionOrderbyEnum!
        $first: Int!
    ) {
        AllAuthors(
            where: { orderby: { field: $field, order: $order } }
            first: $first
        ) {
            edges {
                node {
                    id
                    name
                    firstName
                    lastName
                    avatar {
                        url
                        size
                        height
                        width
                    }
                    slug
                    locale
                }
            }
        }
    }
`;

// your variables to pass into the query hook
const GetAllAuthorsQueryVars = {
    first: 20,
    field: PostObjectsConnectionOrderbyEnum.SLUG,
    order: OrderEnum.ASC
};
  • You could, however, pass form-derived data directly into the variables defined by GetAllAuthors so long as said data satisfies their definitions.

Moving on to user registration. This mutation can be absolutely massive. I will try to simplify it, but you do need a password object, and to provide that via WPGraphQL you should install the WPGraphQL JWT plugin and follow the steps to configure a JWT Secret in your wp-config.php file. Once that is configured, you can generate a refresh token via executing a login mutation using your wordpress credentials. It will return an Auth Token as well which is relatively ephemeral and depends on the Refresh token to perpetually regenerate it. Once you configure this plugin, make sure you store the tokens returned in cookies or something. If the super strict EU laws passed in recent years apply to you, be sure to not store the email or any other information that would violate that law in your cookie.

Anyway, using your credentials (plus a password variable):


const REGISTER_USER = gql`mutation registerUser($username: String!, $password: String!, email: String!, $clientMutationId: String!) {
  registerUser(input: {username: $username, clientMutationId: $clientMutationId email: $email, password: $password}) {
    clientMutationId
        user {
      id
      name
            email
    }
  }
}`

You can inject these values straight into the registerUser definition or you can practice separation of concerns and define a mutation variable object as follows:

const GetMutationInputVars = {
    username: inputE1,
    clientMutationId: inputE2,
    email: inputE3,
    password: inputE4
};

This should get you off on the right foot.

Below is an example of how extensive this particular mutation can get, which more than likely isn't necessary beyond the scope of large projects.

import { gql } from '@apollo/client';

const NEW_USER = gql`
    mutation RegisterUser(
        $locale: String
        $refreshJwtUserSecret: Boolean
        $nickname: String
        $clientMutationId: String!
        $username: String!
        $password: String!
        $email: String!
        $firstName: String
        $lastName: String
        $registered: String!
    ) {
        registerUser(
            input: {
                locale: $locale
                clientMutationId: $clientMutationId
                refreshJwtUserSecret: $refreshJwtUserSecret
                username: $username
                password: $password
                email: $email
                firstName: $firstName
                lastName: $lastName
                registered: $registered
                nickname: $nickname
            }
        ) {
            clientMutationId
            user {
                id
                databaseId
                username
                email
                firstName
                lastName
                registeredDate
                avatar {
                    foundAvatar
                    url
                }
                jwtAuthExpiration
                jwtUserSecret
                jwtRefreshToken
                nickname
                locale
                slug
                uri
                roles {
                    nodes {
                        capabilities
                    }
                }
            }
        }
    }
`;

export default NEW_USER;