{"id":13768497,"url":"https://github.com/the-road-to-graphql/react-graphql-client-library","last_synced_at":"2026-03-17T18:04:36.586Z","repository":{"id":70926125,"uuid":"133457164","full_name":"the-road-to-graphql/react-graphql-client-library","owner":"the-road-to-graphql","description":"A simple GraphQL client for React applications. It's not powerful, but it works. It is not meant for production, but for you as inspiration to contribute to the ecosystem.","archived":false,"fork":false,"pushed_at":"2020-06-12T08:41:32.000Z","size":1995,"stargazers_count":15,"open_issues_count":3,"forks_count":4,"subscribers_count":2,"default_branch":"master","last_synced_at":"2026-02-24T21:27:29.269Z","etag":null,"topics":["graphql","graphql-client","react","react-graphql","reactjs"],"latest_commit_sha":null,"homepage":"https://www.robinwieruch.de/react-graphql-client-library","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/the-road-to-graphql.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"rwieruch","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2018-05-15T04:02:53.000Z","updated_at":"2022-09-09T06:49:25.000Z","dependencies_parsed_at":"2023-04-10T21:30:44.032Z","dependency_job_id":null,"html_url":"https://github.com/the-road-to-graphql/react-graphql-client-library","commit_stats":null,"previous_names":["rwieruch/react-graphql-client"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/the-road-to-graphql/react-graphql-client-library","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/the-road-to-graphql%2Freact-graphql-client-library","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/the-road-to-graphql%2Freact-graphql-client-library/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/the-road-to-graphql%2Freact-graphql-client-library/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/the-road-to-graphql%2Freact-graphql-client-library/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/the-road-to-graphql","download_url":"https://codeload.github.com/the-road-to-graphql/react-graphql-client-library/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/the-road-to-graphql%2Freact-graphql-client-library/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30628405,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-17T17:32:55.572Z","status":"ssl_error","status_checked_at":"2026-03-17T17:32:38.732Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["graphql","graphql-client","react","react-graphql","reactjs"],"created_at":"2024-08-03T16:01:22.179Z","updated_at":"2026-03-17T18:04:36.560Z","avatar_url":"https://github.com/the-road-to-graphql.png","language":"JavaScript","funding_links":["https://github.com/sponsors/rwieruch"],"categories":["Boilerplates and Example Apps"],"sub_categories":[],"readme":"# react-graphql-client\n\n[![Build Status](https://travis-ci.org/the-road-to-graphql/react-graphql-client-library.svg?branch=master)](https://travis-ci.org/the-road-to-graphql/react-graphql-client-library) [![Slack](https://slack-the-road-to-learn-react.wieruch.com/badge.svg)](https://slack-the-road-to-learn-react.wieruch.com/) [![Greenkeeper badge](https://badges.greenkeeper.io/the-road-to-graphql/react-graphql-client-library.svg)](https://greenkeeper.io/)\n\nThe library gives you a simple GraphQL client for React applications. But it shouldn't be used for production. Rather it should be used as inspiration for you and others to contribute to the GraphQL ecosystem.\n\nThe library hasn't powerful features. There is no caching, normalization or global state. **But** it works and it should show you that it's not too difficult to start out with the implementation of a simple GraphQL client library. You can look into the source code (_src/_) and the example application (_example/_) to see that there is not too much to it.\n\nIf you feel the urge to build a sophisticated GraphQL client library (for React) on top of it, please do it! I encourage everyone to contribute to this ecosystem, because I feel there should be more players in this field. I would love to see this library and repository **as inspiration for you and others to contribute to the GraphQL ecosystem**.\n\n[Are you keen to implement your own React GraphQL client?](https://www.robinwieruch.de/react-graphql-client-library)\n\n## Installation\n\nOn the command line, install it with npm: `npm install --save react-graphql-client`\n\n## Setup\n\nIn your top level React component, initialize the GraphQL client with a GraphQL endpoint and pass it to the provided Provider component from the library.\n\n```\nimport React from 'react';\nimport ReactDOM from 'react-dom';\n\nimport GraphQLClient, { Provider } from 'react-graphql-client';\n\nimport App from './App';\n\nconst client = new GraphQLClient({\n  baseURL: 'https://mydomain.com/graphql',\n});\n\nReactDOM.render(\n  \u003cProvider value={client}\u003e\n    \u003cApp /\u003e\n  \u003c/Provider\u003e,\n  document.getElementById('root'),\n);\n```\n\nThat's it. The GraphQL client is accessible in every React component due to [React's Context API](https://www.robinwieruch.de/react-context-api/).\n\n## Query\n\nIn order to execute a GraphQL query operation, use the Query component that is provided from the library. The Query component implements the render prop pattern with its child as a function specification. In the child as a function, you have access to the result of the query operation and further information such as loading state and errors.\n\n```\nimport React from 'react';\n\nimport { Query } from 'react-graphql-client';\n\nconst GET_ORGANIZATION = `\n  query (\n    $organizationLogin: String!\n  ) {\n    organization(login: $organizationLogin) {\n      name\n      url\n    }\n  }\n`;\n\nconst App = () =\u003e\n  \u003cQuery\n    query={GET_ORGANIZATION}\n    variables={{\n      organizationLogin: 'the-road-to-learn-react',\n    }}\n  \u003e\n    {({ data, loading, errors }) =\u003e {\n      if (!data) {\n        return \u003cp\u003eNo information yet ...\u003c/p\u003e;\n      }\n\n      const { organization } = data;\n\n      if (loading) {\n        return \u003cp\u003eLoading ...\u003c/p\u003e;\n      }\n\n      if (errors) {\n        return (\n          \u003cp\u003e\n            \u003cstrong\u003eSomething went wrong:\u003c/strong\u003e\n            {errors.map(error =\u003e error.message).join(' ')}\n          \u003c/p\u003e\n        );\n      }\n\n      return (\n        \u003cOrganization organization={organization} /\u003e\n      );\n    }}\n  \u003c/Query\u003e\n```\n\nThe query executes when it is rendered. The query and optional variables are passed as props to the Query component. Every time one of those props changes, the query will execute again.\n\n## Query with Pagination\n\nIn order to query a paginated list of items, you need to pass in sufficient variables to your query. This is specific to your GraphQL API and not to the library. However, after querying more items (e.g. with a \"More\"-button), there needs to be a resolver function to merge the previous with the new result.\n\n```\nimport React from 'react';\n\nimport { Query } from 'react-graphql-client';\n\nconst GET_REPOSITORIES_OF_ORGANIZATION = `\n  query (\n    $organizationLogin: String!,\n    $cursor: String\n  ) {\n    organization(login: $organizationLogin) {\n      name\n      url\n      repositories(first: 5, after: $cursor) {\n        totalCount\n        pageInfo {\n          endCursor\n          hasNextPage\n        }\n        edges {\n          node {\n            id\n            name\n            url\n            watchers {\n              totalCount\n            }\n            viewerSubscription\n          }\n        }\n      }\n    }\n  }\n`;\n\nconst resolveFetchMore = (data, state) =\u003e {\n  const { edges: oldR } = state.data.organization.repositories;\n  const { edges: newR } = data.organization.repositories;\n\n  const updatedRepositories = [...oldR, ...newR];\n\n  return {\n    organization: {\n      ...data.organization,\n      repositories: {\n        ...data.organization.repositories,\n        edges: updatedRepositories,\n      },\n    },\n  };\n};\n\nconst App = () =\u003e\n  \u003cQuery\n    query={GET_REPOSITORIES_OF_ORGANIZATION}\n    variables={{\n      organizationLogin,\n    }}\n    resolveFetchMore={resolveFetchMore}\n  \u003e\n    {({ data, loading, errors, fetchMore }) =\u003e {\n      ...\n\n      return (\n        \u003cOrganization\n          organization={organization}\n          onFetchMoreRepositories={() =\u003e\n            fetchMore({\n              query: GET_REPOSITORIES_OF_ORGANIZATION,\n              variables: {\n                organizationLogin,\n                cursor:\n                  organization.repositories.pageInfo.endCursor,\n              },\n            })\n          }\n        /\u003e\n      );\n    }}\n  \u003c/Query\u003e\n\nconst Organization = ({ organization, onFetchMoreRepositories }) =\u003e (\n  \u003cdiv\u003e\n    \u003ch1\u003e\n      \u003ca href={organization.url}\u003e{organization.name}\u003c/a\u003e\n    \u003c/h1\u003e\n    \u003cRepositories\n      repositories={organization.repositories}\n      onFetchMoreRepositories={onFetchMoreRepositories}\n    /\u003e\n\n    {organization.repositories.pageInfo.hasNextPage \u0026\u0026 (\n      \u003cbutton onClick={onFetchMoreRepositories}\u003eMore\u003c/button\u003e\n    )}\n  \u003c/div\u003e\n);\n```\n\nAfter a click on the \"More\"-button, the results of both lists of repositories should be merged.\n\n## Mutation\n\nLast but not least, there is a Mutation component analog to the Query component which is used to execute a mutation. However, in contrast to the Quert component, the Mutation component doesn't execute the mutation on render. You get an explicit callback function in the render prop child function for it.\n\n```\nimport React from 'react';\n\nimport { Query, Mutation } from 'react-graphql-client';\n\n...\n\nconst WATCH_REPOSITORY = `\n  mutation($id: ID!, $viewerSubscription: SubscriptionState!) {\n    updateSubscription(\n      input: { state: $viewerSubscription, subscribableId: $id }\n    ) {\n      subscribable {\n        id\n        viewerSubscription\n      }\n    }\n  }\n`;\n\nconst resolveWatchMutation = (data, state) =\u003e {\n  const { totalCount } = state.data.repository;\n  const { viewerSubscription } = data.updateSubscription.subscribable;\n\n  return {\n    repository: {\n      viewerSubscription,\n      totalCount:\n        viewerSubscription === 'SUBSCRIBED'\n          ? totalCount + 1\n          : totalCount - 1,\n    },\n  };\n};\n\nconst Repositories = ({ repositories }) =\u003e (\n  \u003cul\u003e\n    {repositories.edges.map(repository =\u003e (\n      \u003cli key={repository.node.id}\u003e\n        \u003ca href={repository.node.url}\u003e{repository.node.name}\u003c/a\u003e\n\n        \u003cMutation\n          mutation={WATCH_REPOSITORY}\n          initial={{\n            repository: {\n              viewerSubscription:\n                repository.node.viewerSubscription,\n              totalCount: repository.node.watchers.totalCount,\n            },\n          }}\n          resolveMutation={resolveWatchMutation}\n        \u003e\n          {(toggleWatch, { data, loading, errors }) =\u003e (\n            \u003cbutton\n              type=\"button\"\n              onClick={() =\u003e\n                toggleWatch({\n                  variables: {\n                    id: repository.node.id,\n                    viewerSubscription: isWatch(\n                      data.repository.viewerSubscription,\n                    )\n                      ? 'UNSUBSCRIBED'\n                      : 'SUBSCRIBED',\n                  },\n                })\n              }\n            \u003e\n              {data.repository.totalCount}\n              {isWatch(data.repository.viewerSubscription)\n                ? ' Unwatch'\n                : ' Watch'}\n            \u003c/button\u003e\n          )}\n        \u003c/Mutation\u003e\n      \u003c/li\u003e\n    ))}\n  \u003c/ul\u003e\n);\n```\n\nWithin the Mutation component the `data` object should be used to render relevant information. This data can be set with an initial value by using the `initial` prop on the Mutation component. Furthermore, after executing a mutation, a `resolveMutation` function as a prop can be provided to deal with the previous state and the mutation result. In the previous case, the new `totalCount` wasn't provided by the GraphQL API. So you can do it by yourself with this resolver function.\n\n## Contribute\n\nAs mentioned, if you are curious, checkout the _examples/_ folder to get a minimal working application. You need to fulfil the following installation instructions for it:\n\n* npm install\n* [add your own REACT_APP_GITHUB_PERSONAL_ACCESS_TOKEN in .env file](https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/)\n  * scopes/permissions you need to check: admin:org, repo, user, notifications\n* npm start\n* visit `http://localhost:3000`\n\nIn addition, checkout the _src/_ folder to see that there is not much to implement for a simple GraphQL client. I hope this helps you to build your own library on top of it by forking this repository.\n\nOtherwise, feel free to improve this repository and to fix bugs for it. However, I wouldn't want to grow it into a powerful GraphQL client library. Rather I would love to see this library and repository as inspiration for you and others to contribute to this new GraphQL ecosystem.\n\n## Want to learn more about React + GraphQL + Apollo?\n\n* Don't miss [upcoming Tutorials and Courses](https://www.getrevue.co/profile/rwieruch)\n* Check out current [React Courses](https://roadtoreact.com)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthe-road-to-graphql%2Freact-graphql-client-library","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthe-road-to-graphql%2Freact-graphql-client-library","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthe-road-to-graphql%2Freact-graphql-client-library/lists"}