Integrate relay hook in expo app

Hyo
dooboolab
Published in
4 min readJun 24, 2020

This is a guide to implement an app with a relay hook which is currently experimental, in expo managed workflow.

Image from https://medium.com/open-graphql/react-hooks-for-graphql-3fa8ebdd6c62

We’ve been managing our experiments in an opensource chat app called HackaTalk. Previously, we’ve integrated our app with apollo-client v2 and recently, we were thinking of migrating to apollo-client v3.

Many developers today are suspecting that the relay might possibly be integrated inside react when concurrent mode rises in react v17. Therefore, this time, I took time in reading about react and relay, and the react’s official blog truly helped me to drive my next graphql-client to use the relay.

Image by codeburst.io

Since I’ve provided useful articles in the above paragraphs, people might be aware of what react, relay, expo, concurrent mode, and graphql are. Therefore, I’ll just go through how to use the relay in our project HackaTalk. Also, this will help other people to use the relay in their projects.

Let’s look at our work in relay integration in PR done by Eunho Lee 🙌

Since we’d like to use the relay hook, we chose relay experimental and followed the installation guide.

1. Installation

yarn add react@experimental react-dom@experimental react-relay@experimental// dev
yarn add --dev babel-plugin-relay graphql relay-compiler

(Optional) Additional step for typescript users

plugins: [
['relay', { artifactDirectory: './src/__generated__' }],
...
  • Declare module in your environment file.
// environment.d.ts
declare module 'babel-plugin-relay/macro' {
export { graphql } from 'react-relay';
}
  • Exclude below in tsconfig.json
"exclude": ["node_modules", "**/*.test.tsx", "**/*.spec.ts", "src/__generated__"],
  • Additional note when a jest is failing. Followed by the issue provided, you can try to remove the brackets.

2. Add relay compile script to package.json

"relay": "relay-compiler --src ./src --schema schema.graphql --language typescript --artifactDirectory ./src/__generated__","relay-watch": "yarn relay-compiler --schema schema.graphql --src ./src/ --extensions ts tsx --language typescript --artifactDirectory ./src/__generated__ --watch",
  • relay for compiling once and relay-watch for compiling while coding.

3. Install experimental version for react, react-dom, and relay

"react": "^0.0.0-experimental-33c3af284",
"react-dom": "^0.0.0-experimental-33c3af284",
"react-relay": "^0.0.0-experimental-94e87455",
"relay-hooks": "^3.4.0",
  • Above versions are what we are using to use relay-hook

4. Add relay.config.js file

module.exports = {
src: './src',
schema: './schema.graphql',
exclude: [
'**/node_modules/**',
'**/__mocks__/**',
'src/__generated__/**'
],
};
  • Above file contains a configuration options accepted by the relay-compiler command-line tool and babel-plugin-relay.

5. Add relay configuration file in relay directory

relay/fetch.ts
relay/RelayEnvironment.ts

6. Import relay hooks in which you want to put root graphql provider

import {  RelayEnvironmentProvider,  graphql,  preloadQuery,  usePreloadedQuery,  useRelayEnvironment,} from 'react-relay/hooks';import relayEnvironment from './relay/RelayEnvironment';

Then wrap with RelayEnvironmentProvider.

<RelayEnvironmentProvider environment={relay}>
<Suspense fallback={<Text>loading app...</Text>}>
<ActionSheetProvider>
<App />
</ActionSheetProvider>
</Suspense>
</RelayEnvironmentProvider>

7. Writing the first mutation

1. Write the mutation query in SignIn.tsx

const signInEmail = graphql`
mutation SignInEmailMutation($email: String!, $password: String!) {
signInEmail(email: $email, password: $password) {
token
user {
id
email
name
photoURL
verified
}
}
}
`;
  • Important rule here is that the mutation should start with the same name as a component which is SignIn in here.

2. Running yarn relay will generate SignInEmailMutation and
SignInEmailMutationResponse so import them.

import type {
SignInEmailMutation,
SignInEmailMutationResponse,
} from '../../__generated__/SignInEmailMutation.graphql';

3. Inside the SignIn screen component, add below mutationConfig

const [commitEmail, isInFlight] = useMutation<SignInEmailMutation>(signInEmail);const mutationConfig = {
variables: {
email,
password,
},
onCompleted: async (response: SignInEmailMutationResponse): Promise<void> => {
const { token, user } = response.signInEmail;
if (user && !user.verified) {
return navigation.navigate('VerifyEmail', {
email,
});
}
await AsyncStorage.setItem('token', token);
await AsyncStorage.setItem('password', password);
initializeEThree(user.id);
setUser(user);
},
onError: (error: any): void => {
showAlertForGrpahqlError(error?.graphQLErrors);
},
};
  • The commitEmail is where you want to request signInEmail to the server while isInFlight judges the loading state.

8. Writing the first query

1. As we did in writing mutation query, write a query in App.tsx.

const userQuery = graphql`
query AppUserQuery {
me {
id
email
verified
}
}
`;
  • Here again, important rule follows as in mutation. The query should start with the same name as a component which is App in here.

2. Run yarn relay and generate AppUserQuery and AppUserQueryResponse.

import type { AppUserQuery, AppUserQueryResponse } from './__generated__/AppUserQuery.graphql';

3. Use userPreloadQuery to query the result.

const result = preloadQuery<AppUserQuery>(
environment,
userQuery,
{},
{ fetchPolicy: 'store-and-network' },
);

const data = usePreloadedQuery<AppUserQuery>(userQuery, result);
  • Next to data, it will fetch data and return results.

4. Use useEffect to handle the received data.

useEffect(() => {
// do what you want
}, [data.me]);

9. Testing

1. Install relay-test-utils

yarn add relay-test-utilsyarn add -D @types/relay-test-utils

2. Add below in test/setupTest.js which is one of jest setupFiles.

jest.mock('../src/relay/RelayEnvironment', () => {
const { createMockEnvironment } = require('relay-test-utils');
return createMockEnvironment();
});
  • Above setting will prevent your tests to fail when running npx jest. However, more advanced testing experience will be shared separately.

Thanks for reading 🙏.

Here is the post for testing relay components.

--

--