In my last post I showed how we can log into a WordPress site from a headless app using GraphQL and cookies.
In this post we’ll create a log-out mutation in GraphQL, and a custom React Hook to utilise it. I’ll be using Apollo Client to make the actual API calls.
Creating the GraphQL Mutation
We need to register a logout mutation in WP GraphQL first which logs the user out and unsets their authentication cookies.
Reminder: In GraphQL, a mutation query is something that modifies data and returns a value. It’s the equivalent of a POST request in REST.
This mutation doesn’t need any input; it just needs to unset the cookie (which in this case is a HTTP Cookie that React and JavaScript cannot see, nor access).
add_action( 'graphql_register_types', function() {
register_graphql_mutation(
'logout',
array(
'inputFields' => array(),
'outputFields' => array(
'status' => array(
'type' => 'String',
'description' => 'Logout result',
'resolve' => function( $payload ) {
return $payload['status'];
},
),
),
'mutateAndGetPayload' => function() {
wp_logout(); // This destroys the WP Login cookie.
return array( 'status' => 'SUCCESS' );
},
)
)
} );
Code language: PHP (php)
This code would live in a custom plugin or your theme, on the server running WordPress.
Setting up Apollo Client
If you’ve not familiar with Apollo Client, it essentially provides us some React hooks with which we can make GraphQL requests to the server. For example, it provides a handy useMutation
hook that runs a mutation query and returns the result. The getting started guide is here.
When using Apollo, you’ll likely want to wrap your App code in the Apollo Client context. For sake of completeness, here is a small example from my own app that sets up Apollo and ensures credentials
are included with our requests (our cookies).
import { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client';
import { BatchHttpLink } from '@apollo/client/link/batch-http';
const cache = new InMemoryCache( {} );
const httpLink = new BatchHttpLink( {
uri: 'https://morricsmagicalcauldron.wpcomstaging.com/index.php?graphql', // My GraphQL Server
credentials: 'include', // This sends our logged in cookie with the requests!
} );
export const useAppApolloClient = () => {
return new ApolloClient( {
link: httpLink,
cache,
} );
};
function App() {
const client = useAppApolloClient();
return (
<AuthContextProvider>
<ApolloProvider client={ client }>
{ // Your App Code Here }
</ApolloProvider>
</AuthContextProvider>
);
}
Code language: JavaScript (javascript)
With Apollo client setup in this way, it can now be used from our other custom hooks.
Create a custom hook in React JS
With Apollo Client setup, we can create a custom hook in React JS to make our logout functionality reusable across the app.
import { gql, useMutation, useApolloClient } from '@apollo/client';
const LOGOUT = gql`
mutation Logout {
logout(input: {}) {
status
}
}
`;
export const useLogoutMutation = () => {
const apolloClient = useApolloClient();
const [ mutation, mutationResults ] = useMutation( LOGOUT );
const logoutMutation = async () => {
// Remove all data from the store since we are now logged out.
await apolloClient.clearStore();
return mutation();
};
return { logoutMutation, results: mutationResults };
};
Code language: JavaScript (javascript)
With this in place, we can create a logout button like this:
const { logoutMutation } = useLogoutMutation();
return ( <button onClick={ () => logoutMutation() }>
Logout
</button> );
Code language: JavaScript (javascript)
You can see where I implemented this in my app here and here. You can see in my app I created another hooked named `useAuth` to house my login, logout, and status queries which are used across the app.
Wrapping up
We now have the ability to logout from the app using a button! WP GraphQL will log the user out and destroy any cookies. You can see a working example this in my D&D app here, and the source code is also public on GitHub.
Apollo Client really makes the process of interacting with GraphQL simple, and takes care of all kinds of things like batching and cache for us. I highly recommend it if you’re using React!