How to set up a React Apollo client with a Graphcool GraphQL server
Graphcool is a service similar to Firebase except it is used to create GraphQL APIs instead of RESTful ones. Apollo Client is a GraphQL client (alternative to Relay) that can be used with React (and other frontend frameworks). Below is how to create a Graphcool GraphQL service and query it from a React frontend using Apollo Client. I also used Next.js to set up the React project. I am running Node 8.4.0 on macOS Sierra. The code for this example is on github: https://github.com/saltycrane/graphcool-apollo-example.
Jump to: Graphcool setup, Next.js setup, or Apollo setup.
Graphcool GraphQL server¶
Graphcool Apollo Quickstart: https://www.graph.cool/docs/quickstart/frontend/react/apollo-tijghei9go
- Install the Graphcool command-line tool (step 2 in quickstart)
$ npm install -g graphcool-framework
$ graphcool-framework --version graphcool-framework/0.11.5 (darwin-x64) node-v8.4.0
- Create a Graphcool service (step 3 in quickstart)
$ cd /tmp $ mkdir graphcool-apollo-example $ cd graphcool-apollo-example
$ graphcool-framework init myserver Creating a new Graphcool service in myserver... ✔ Written files: ├─ types.graphql ├─ src │ ├─ hello.js │ └─ hello.graphql ├─ graphcool.yml └─ package.json To get started, cd into the new directory: cd myserver To deploy your Graphcool service: graphcool deploy To start your local Graphcool cluster: graphcool local up To add facebook authentication to your service: graphcool add-template auth/facebook You can find further instructions in the graphcool.yml file, which is the central project configuration.
- Add a
Post
type definition. (step 4 in quickstart) Editmyserver/types.graphql
:type Post @model { id: ID! @isUnique # read-only (managed by Graphcool) createdAt: DateTime! # read-only (managed by Graphcool) updatedAt: DateTime! # read-only (managed by Graphcool) description: String! imageUrl: String! }
- Deploy the Graphcool server (step 5 in quickstart). After running the
deploy
command, it will ask to select a cluster, select a name, and create an account with Graphcool.$ cd myserver $ graphcool-framework deploy ? Please choose the cluster you want to deploy to shared-eu-west-1 Auth URL: https://console.graph.cool/cli/auth?cliToken=xxxxxxxxxxxxxxxxxxxxxxxxx&authTrigger;=auth Authenticating... ✔ Creating service myserver in cluster shared-eu-west-1... ✔ Bundling functions... 2.3s Deploying... 1.3s Success! Created the following service: Types Post + A new type with the name `Post` is created. ├─ + A new field with the name `createdAt` and type `DateTime!` is created. ├─ + A new field with the name `updatedAt` and type `DateTime!` is created. ├─ + A new field with the name `description` and type `String!` is created. └─ + A new field with the name `imageUrl` and type `String!` is created. Resolver Functions hello + A new resolver function with the name `hello` is created. Permissions Wildcard Permission ? The wildcard permission for all operations is added. Here are your GraphQL Endpoints: Simple API: https://api.graph.cool/simple/v1/cjc2uk4kx0vzo01603rkov391 Relay API: https://api.graph.cool/relay/v1/cjc2uk4kx0vzo01603rkov391 Subscriptions API: wss://subscriptions.graph.cool/v1/cjc2uk4kx0vzo01603rkov391
- Run some queries in the Graphcool playground (step 6 in quickstart). Run the following command to open a new browser tab with the Graphcool playground:Run a query to create a post:
$ graphcool-framework playground
mutation { createPost( description: "A rare look into the Graphcool office" imageUrl: "https://media2.giphy.com/media/xGWD6oKGmkp6E/200_s.gif" ) { id } }
Run a query to retrieve all posts:query { allPosts { id description imageUrl } }
- Done with Graphcool server. Also see https://console.graph.cool/server/schema/types
Next.js React frontend¶
Set up a React frontend using the Next.js framework. Next.js setup: https://github.com/zeit/next.js#setup
- Create a
myclient
directory alongside themyserver
directory:$ cd /tmp/graphcool-apollo-example $ mkdir myclient $ cd myclient
- Create
myclient/package.json
:{ "dependencies": { "next": "4.2.1", "react": "16.2.0", "react-dom": "16.2.0" }, "scripts": { "dev": "next", "build": "next build", "start": "next start" } }
- Install Next.js and React:
$ npm install npm WARN deprecated [email protected]: this package has been reintegrated into npm and is now out of date with respect to npm npm WARN deprecated @semantic-release/[email protected]: Use @semantic-release/npm instead > [email protected] install /private/tmp/graphcool-apollo-example/myclient/node_modules/fsevents > node install [fsevents] Success: "/private/tmp/graphcool-apollo-example/myclient/node_modules/fsevents/lib/binding/Release/node-v57-darwin-x64/fse.node" already installed Pass --update-binary to reinstall or --build-from-source to recompile > [email protected] postinstall /private/tmp/graphcool-apollo-example/myclient/node_modules/uglifyjs-webpack-plugin > node lib/post_install.js npm notice created a lockfile as package-lock.json. You should commit this file. npm WARN myclient No description npm WARN myclient No repository field. npm WARN myclient No license field. + [email protected] + [email protected] + [email protected] added 838 packages in 20.012s
- Create a Hello World pageCreate
$ mkdir pages
myclient/pages/index.js
:const Home = () => <div>Hello World</div>; export default Home;
- Run the Next.js dev serverGo to http://localhost:3000 in the browser
$ npm run dev
Apollo Client¶
Set up Apollo Client to query the Graphcool server. Apollo Client setup: https://www.apollographql.com/docs/react/basics/setup.html
- Install Apollo Client
$ cd /tmp/graphcool-apollo-example/myclient
$ npm install apollo-client-preset react-apollo graphql-tag graphql npm WARN [email protected] requires a peer of graphql@^0.11.0 but none is installed. You must install peer dependencies yourself. npm WARN myclient No description npm WARN myclient No repository field. npm WARN myclient No license field. + [email protected] + [email protected] + [email protected] + [email protected] added 20 packages in 5.476s
- Set up Apollo Client. Edit
myclient/pages/index.js
:import { InMemoryCache } from "apollo-cache-inmemory"; import { ApolloClient } from "apollo-client"; import { HttpLink } from "apollo-link-http"; import { ApolloProvider } from "react-apollo"; const client = new ApolloClient({ link: new HttpLink({ // Replace this with your Graphcool server URL uri: "https://api.graph.cool/simple/v1/cjc2uk4kx0vzo01603rkov391", }), cache: new InMemoryCache(), }); const Home = () => <div>Hello World</div>; const App = () => ( <ApolloProvider client={client}> <Home /> </ApolloProvider> ); export default App;
- Try running the dev serverGo to http://localhost:3000 in the browser
$ npm run dev
- But, get this error:
Error: fetch is not found globally and no fetcher passed, to fix pass a fetch for your environment like https://www.npmjs.com/package/node-fetch. For example: import fetch from 'node-fetch'; import { createHttpLink } from 'apollo-link-http'; const link = createHttpLink({ uri: '/graphql', fetch: fetch }); at warnIfNoFetch (/private/tmp/graphcool-apollo-example/myclient/node_modules/apollo-link-http/lib/httpLink.js:72:15) at createHttpLink (/private/tmp/graphcool-apollo-example/myclient/node_modules/apollo-link-http/lib/httpLink.js:89:5) at new HttpLink (/private/tmp/graphcool-apollo-example/myclient/node_modules/apollo-link-http/lib/httpLink.js:159:34) at Object.
(/private/tmp/graphcool-apollo-example/myclient/.next/dist/pages/index.js:25:9) at Module._compile (module.js:573:30) at Module._compile (/private/tmp/graphcool-apollo-example/myclient/node_modules/source-map-support/source-map-support.js:492:25) at Object.Module._extensions..js (module.js:584:10) at Module.load (module.js:507:32) at tryModuleLoad (module.js:470:12) at Function.Module._load (module.js:462:3) - Install
node-fetch
. This is needed because Next.js runs on a Node server in addition to the browser.$ npm install node-fetch npm WARN [email protected] requires a peer of graphql@^0.11.0 but none is installed. You must install peer dependencies yourself. npm WARN myclient No description npm WARN myclient No repository field. npm WARN myclient No license field. + [email protected] updated 1 package in 4.028s
- Update the code to use
node-fetch
as described in the error message:import { InMemoryCache } from "apollo-cache-inmemory"; import { ApolloClient } from "apollo-client"; import { createHttpLink } from "apollo-link-http"; import gql from "graphql-tag"; import fetch from "node-fetch"; import { ApolloProvider } from "react-apollo"; const client = new ApolloClient({ link: createHttpLink({ // Replace this with your Graphcool server URL uri: "https://api.graph.cool/simple/v1/cjc2uk4kx0vzo01603rkov391", fetch: fetch, }), cache: new InMemoryCache(), }); class Home extends React.Component { componentDidMount() { client .query({ query: gql` { allPosts { id description imageUrl } } `, }) .then(console.log); } render() { return <div>Look in the devtools console</div>; } } const App = () => ( <ApolloProvider client={client}> <Home /> </ApolloProvider> ); export default App;
- Try running the dev server againGo to http://localhost:3000 in the browser
$ npm run dev
- It works. Open the browser devtools console and see the result of the query:
{ "data": { "allPosts": [ { "id": "cjbffxjq5rrvd0192qmptpm2f", "description": "A rare look into the Graphcool office", "imageUrl": "https://media2.giphy.com/media/xGWD6oKGmkp6E/200_s.gif", "__typename": "Post" } ] }, "loading": false, "networkStatus": 7, "stale": false }
- Use the
graphql
higher-order component to make things nicer. Editmyclient/pages/index.js
:import { InMemoryCache } from "apollo-cache-inmemory"; import { ApolloClient } from "apollo-client"; import { createHttpLink } from "apollo-link-http"; import gql from "graphql-tag"; import fetch from "node-fetch"; import { ApolloProvider, graphql } from "react-apollo"; const client = new ApolloClient({ link: createHttpLink({ // Replace this with your Graphcool server URL uri: "https://api.graph.cool/simple/v1/cjc2uk4kx0vzo01603rkov391", fetch: fetch, }), cache: new InMemoryCache(), }); const MY_QUERY = gql` { allPosts { id description imageUrl } } `; const Home = ({ data }) => <pre>{JSON.stringify(data, null, 2)}</pre>; const HomeWithData = graphql(MY_QUERY)(Home); const App = () => ( <ApolloProvider client={client}> <HomeWithData /> </ApolloProvider> ); export default App;
- Run the dev serverGo to http://localhost:3000 in the browser and see this result on the page:
$ npm run dev
{ "variables": {}, "loading": false, "networkStatus": 7, "allPosts": [ { "id": "cjbffxjq5rrvd0192qmptpm2f", "description": "A rare look into the Graphcool office", "imageUrl": "https://media2.giphy.com/media/xGWD6oKGmkp6E/200_s.gif", "__typename": "Post" } ] }
Related posts
- How to use ast-grep with GraphQL — posted 2024-09-24
- Next.js App Router (RSC) projects w/ open source code — posted 2024-07-30
- Next.js Relay GraphQL Pokemon example — posted 2024-05-22
- Example Node.js Passport.js SAML app using OneLogin — posted 2024-05-10
- Aphrodite to CSS Modules codemod — posted 2022-12-09
- Simple codemod example with jscodeshift — posted 2021-05-03