{"id":13475692,"url":"https://github.com/nksaraf/magiql","last_synced_at":"2025-04-10T04:56:36.494Z","repository":{"id":44344365,"uuid":"252979462","full_name":"nksaraf/magiql","owner":"nksaraf","description":"🌐 💫 Simple and powerful GraphQL Client, love child of react-query ❤️ relay ","archived":false,"fork":false,"pushed_at":"2021-12-31T03:05:22.000Z","size":9881,"stargazers_count":203,"open_issues_count":26,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-03T03:09:08.236Z","etag":null,"topics":["babel-plugin","codegen","data-fetching","graphql","graphql-client","magic","react","react-query","recoiljs","relay","relay-hooks"],"latest_commit_sha":null,"homepage":"https://magiql.vercel.app","language":"TypeScript","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/nksaraf.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-04-04T11:31:56.000Z","updated_at":"2025-03-23T10:17:48.000Z","dependencies_parsed_at":"2022-09-15T18:41:12.168Z","dependency_job_id":null,"html_url":"https://github.com/nksaraf/magiql","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nksaraf%2Fmagiql","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nksaraf%2Fmagiql/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nksaraf%2Fmagiql/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nksaraf%2Fmagiql/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nksaraf","download_url":"https://codeload.github.com/nksaraf/magiql/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248161261,"owners_count":21057554,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["babel-plugin","codegen","data-fetching","graphql","graphql-client","magic","react","react-query","recoiljs","relay","relay-hooks"],"created_at":"2024-07-31T16:01:22.647Z","updated_at":"2025-04-10T04:56:36.469Z","avatar_url":"https://github.com/nksaraf.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":" \n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"/public/hat2.png\" width=\"120\" /\u003e\u003ch1  align=\"center\"\u003e\u003ccode margin=\"0\"\u003emagiql\u003c/code\u003e\u003c/h1\u003e\u003cp align=\"center\"\u003e\u003ci\u003eA bunch of simple but magical React hooks to work with GraphQL.\u003cbr\u003epowered by \u003ccode\u003e\u003ca href=\"https://github.com/tannerlinsley/react-query\"\u003ereact-query\u003c/a\u003e\u003c/code\u003e, inspired by \u003ccode\u003e\u003ca href=\"https://github.com/facebook/relay\"\u003erelay\u003c/a\u003e\u003c/code\u003e and \u003ccode\u003e\u003ca href=\"https://github.com/FormidableLabs/urql\"\u003eurql\u003c/a\u003e\u003c/code\u003e\u003c/i\u003e\u003c/p\u003e\n\u003c/p\u003e\n\nA set of React hooks to work with GraphQL data. `magiql` stands on the shoulders of massive giants in the data-synchronization and state-management space, both conceputally and some as actual dependencies. It uses the amazing [`react-query`](https://github.com/tannerlinsley/react-query) library as its data-fetching and synchronization layer which forms the foundation of this library. Seriously, without [`react-query`](https://github.com/tannerlinsley/react-query), this won't be any good. The API is also very similar to [`react-query`](https://github.com/tannerlinsley/react-query) and will be familiar to the users. It's just slightly tweaked to make it easier to work with GraphQL. On top of the these great synchronization primitives, we add normalized caching which allows us to enable the amazing developer experience that `relay` provides without any of the restrictions and buy-in required. \n\n`magiql` is designed to be easy to adopt (moving from vanilla `react-query` or other GraphQL clients). Most features (like normalized caching, `recoil`-based store implementation, `relay-compiler` and build-time optimizations) are completely optional and configurable. But everything is included under one installed dependency so that you don't have to install things again and again (don't worry, the different entry-points are code-split and you will only include things that you actually use). You can start using `magiql` as a GraphQL Client immediately and it grows to cater to your needs as they arise by allowing extensive customization and incrementally adoption of more speciliazed features.\n\n# Features\n\nMost of the features that we are providing are thanks to [`react-query`](https://github.com/tannerlinsley/react-query). Using inspiration from `relay` and `urql`, we are able to provide a bunch of additional awesome GraphQL-specific features that you can find below\n\n* Auto Caching + Refetching (stale-while-revalidate, Window Refocus, Polling/Realtime)\n* Parallel + Dependent Queries\n* \"Lazy\" Queries\n* Request Deduplication\n* Paginated + Cursor-based Queries\n* Load-More + Infinite Scroll Queries w/ Scroll Recovery\n* Normalized caching + Entity Manipulation (multiple store implementations ([`recoil`](https://github.com/facebookexperimental/Recoil), [`react-query`](https://github.com/tannerlinsley/react-query))\n* Fragment-first GraphQL approach (`relay`-style `useFragment` hook)\n* Request Cancellation\n* Mutations + Reactive Query Refetching\n* Optimistic Updates\n* Exchanges API to customize execution (logging, persisted queries, authentication, JWT token refresh)\n* React Suspense Support (must be enabled with React Concurrent Mode)\n* Dedicated Devtools\n\nUsing the [`relay-compiler`](https://github.com/facebook/relay) (via `magiql/babel` or `magiql` cli) is required to unlock some more awesome features,\n\n* Schema-aware Normalized caching\n* Typescript Support + Code generation\n* Build-time GraphQL optimizations\n* Skip parsing at runtime\n\n**Note: You don't need a Relay-compliant server to get all these features in `magiql`. It will work with any GraphQL server. It also doesn't require you to commit to React Concurrent Mode which the new [`relay`](https://github.com/facebook/relay) hooks require.**\n\nThere is an example for this: [https://magiql.vercel.app](https://magiql.vercel.app). You can see the [components](/components) and [pages](/pages) folder for example code.\n\n\u003cimg src='/public/example.gif' /\u003e\n\n**Warning**: This is still in alpha stage and docs and examples are in the works\n\n# Documentation\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cbig\u003e\u003cstrong\u003eBasic Usage\u003c/strong\u003e\u003c/big\u003e\u003c/summary\u003e\n\n```tsx\nimport {\n  GraphQLClientProvider,\n  GraphQLClient,\n  useQuery,\n  graphql,\n} from \"magiql\";\n\nconst client = new GraphQLClient({\n  endpoint: \"https://swapi-graphql.netlify.app/.netlify/functions/index\",\n});\n\nconst People = () =\u003e {\n  const { data, status, error } = useQuery(\n    graphql`\n      query PeopleQuery($limit: Int) {\n        allPeople(first: $limit) {\n          edges {\n            node {\n              id\n              name\n              homeworld {\n                name\n              }\n            }\n          }\n        }\n      }\n    `,\n    {\n      variables: {\n        limit: 10,\n      },\n    }\n  );\n\n  if (status === \"loading\") {\n    return \u003cdiv\u003eLoading...\u003c/div\u003e;\n  }\n\n  if (error) {\n    return \u003cdiv\u003e{error.message}\u003c/div\u003e;\n  }\n\n  return (\n    \u003cdiv\u003e\n      {data\n        ? data.allPeople?.edges?.map((edge) =\u003e (\n            \u003cdiv key={edge.node.id}\u003e\n              \u003cb\u003e{edge.node.name}\u003c/b\u003e ({edge.node.homeworld?.name})\n            \u003c/div\u003e\n          ))\n        : null}\n    \u003c/div\u003e\n  );\n};\n\nconst App = () =\u003e {\n  return (\n    \u003cGraphQLClientProvider client={client}\u003e\n      \u003cPeople /\u003e\n    \u003c/GraphQLClientProvider\u003e\n  );\n};\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cbig\u003e\u003cstrong\u003eInstallation\u003c/strong\u003e\u003c/big\u003e\u003c/summary\u003e\n \nTo install `magiql` with all its features to your project, run the following commands based on if you use `yarn` or `npm`. The single dependency includes multiple entry points to code-split features and not require user to install more dependencies.\n\n```sh\nyarn add magiql graphql\n\n# or\nnpm install magiql graphql --save\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cbig\u003e\u003cstrong\u003eUsing the Relay compiler\u003c/strong\u003e\u003c/big\u003e\u003c/summary\u003e\n\n_This is required to use fragments and normalized caching_\n\nTo use the [`relay-compiler`](https://github.com/facebook/relay), add `magiql/babel` to your Babel config as a plugin, eg. in `babel.config.js`. The `magiql` Babel plugin is just a wrapper around [`babel-plugin-relay`](https://github.com/facebook/relay) to include everything in one dependency. It also runs the [`relay-compiler`](https://github.com/facebook/relay) in watch mode by default.\n\n```javascript\nmodule.exports {\n  presets: [ ... ],\n  plugins: [\"magiql/babel\", ... ]\n}\n```\n\nOr, you can run the compiler from cli using the `magiql` command (use `magiql --watch` for watch mode, recommended for development). This is also just a wrapper around the [`relay-compiler`](https://github.com/facebook/relay). You still need to add the Babel plugin, but can disable running the compiler with Babel, but setting `runWithBabel` to `false` in `magiql.config.js`.\n\n#### `magiql.config.js`\n\nIf need to customize the Relay compiler away from the defaults (specified below), add a `magiql.config.js` file in the root directory. It is very similar to `relay.config.js`, but tailored a little for `magiql`.\n\n```javascript\nmodule.exports = {\n  schema: \"./schema.graphql\",\n  src: \"./\",\n  artifactDirectory: \"generated\",\n  extensions: [\"ts\", \"tsx\", \"js\", \"jsx\", \"graphql\"],\n  quiet: false,\n  watch: boolean,\n  runWithBabel: true,\n  language: \"typescript\",\n  include: [\"**\"],\n  exclude: [\n      \"**/node_modules/**\",\n      \"**/__mocks__/**\",\n      `**/generated/**`,\n    ];\n }\n\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cbig\u003e\u003cstrong\u003eWorking with fragments\u003c/strong\u003e\u003c/big\u003e\u003c/summary\u003e\n\nWith GraphQL, the biggest game changer when used with React are **fragments**. The `useFragment` hook introduced by [`relay`](https://github.com/facebook/relay) makes it delightful to declare the data needs of your components. These are some of the advantages:\n\n- Date requirements completely localized and encapsulated in your component\n- Declarative, modular and composable\n- Fragments can include nest more fragments and fits naturally with the React component model\n- Don't need to add everything to the top level query\n- Easy to ensure type safety (using [`relay-compiler`](https://github.com/facebook/relay) generated files)\n- Data available independent of how the data is fetched by some parent component\n- Components only subscribe to the precise part of the data store that it cares about (down to the field level).\n\n#### Usage (with fragments)\n\n```tsx\n// Person.tsx\nimport React from \"react\";\nimport { useFragment, graphql } from \"magiql\";\nimport { Person_person } from \"generated/Person_person.graphql\";\n\nexport function Person({ person }: { person: Person_person }) {\n  const data = useFragment(\n    graphql`\n      fragment Person_person on Person {\n        name\n        homeworld {\n          name\n        }\n      }\n    `,\n    person\n  );\n\n  return (\n    \u003cdiv\u003e\n      \u003cb\u003e{data.name}\u003c/b\u003e ({data.homeworld?.name})\n    \u003c/div\u003e\n  );\n}\n```\n\n```tsx\n// People.tsx\nimport React from \"react\";\nimport { useQuery, graphql } from \"magiql\";\nimport { PeopleQuery } from \"generated/PeopleQuery.graphql\";\nimport { Person } from \"./Person\";\n\nexport const People = () =\u003e {\n  const { data, status, error } = useQuery\u003cPeopleQuery\u003e(\n    graphql`\n      query PeopleQuery($limit: Int) {\n        allPeople(first: $limit) {\n          edges {\n            node {\n              id\n              ...Person_person\n            }\n          }\n        }\n      }\n    `,\n    {\n      variables: {\n        limit: 10,\n      },\n    }\n  );\n\n  return (\n    \u003cdiv\u003e\n      {data\n        ? data.allPeople?.edges?.map((edge) =\u003e \u003cPerson person={edge.node} /\u003e)\n        : null}\n    \u003c/div\u003e\n  );\n};\n```\n\n```tsx\nimport { GraphQLClientProvider, GraphQLClient } from \"magiql\";\nimport { createRecoilStore } from \"magiql/recoil-store\";\nimport { People } from \"./People\";\n\nconst client = new GraphQLClient({\n  endpoint: \"https://swapi-graphql.netlify.app/.netlify/functions/index\",\n  useStore: createRecoilStore(),\n});\n\nconst App = () =\u003e {\n  return (\n    \u003cGraphQLClientProvider client={client}\u003e\n      \u003cPeople /\u003e\n    \u003c/GraphQLClientProvider\u003e\n  );\n};\n```\n\nThese features and accompanying restrictions provide an excellent authoring experience that almost seems magical when it works.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cbig\u003e\u003cstrong\u003eTypescript Support\u003c/strong\u003e\u003c/big\u003e\u003c/summary\u003e\n \nUsing the Relay compiler, `magiql` can generate types for all your operations since it has access to your schema as well. These types are generated and updated by the compiler, so ensure that it's running in watch mode (either through Babel or the cli) when you are developing.\n  \nIf the name of query is `HomeQuery`, then import type as such:\n\n```typescript\nimport { HomeQuery } from \"generated/HomeQuery.graphql\";\nimport { useQuery } from \"magiql\";\n\nconst { data, error } = useQuery\u003cHomeQuery\u003e(graphql`\n  query HomeQuery {\n    currentHome {\n      name\n    }\n  }\n`);\n```\n\n- Types are imported from the folder specified as `artifactDirectory` in `magiql.config.js` (Default: `generated`).\n- Typescript support is enabled by default. To disable it, set `language` to `javascript` in `magiql.config.js`.\n- If not using the compiler, you can provide type parameters to each operation with the following sample signature\n\n```tsx\ntype HomeQuery = {\n  response: {\n    currentHome: {\n      name: string;\n    };\n  };\n  variables: {};\n};\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cbig\u003e\u003cstrong\u003eCustomizing the GraphQL Client\u003c/strong\u003e\u003c/big\u003e\u003c/summary\u003e\n\nComing soon\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cbig\u003e\u003cstrong\u003eExchanges\u003c/strong\u003e\u003c/big\u003e\u003c/summary\u003e\n\nComing soon\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cbig\u003e\u003cstrong\u003eNormalized caching\u003c/strong\u003e\u003c/big\u003e\u003c/summary\u003e\n\nTo fully unlock fragments, including optimistic responses and cache manipulation of entities, we needed a normalized cache of our data. We call this cache, the **`store`** in `magiql`.\n\n- Each entity is identified and stored once.\n- Component that access entities subscribe to changes to that entity\n- Implementation can be customized when creating a `GraphQLClient` via the `useStore` option, we provide three implementations of our own (using [`recoil`](https://github.com/facebookexperimental/Recoil) and [`react-query`](https://github.com/tannerlinsley/react-query)'s `QueryCache`)\n- Provide your own `getDataID` to these stores to control how id's are determined and then let `magiql` handle the rest for managing access.\n\n```typescript\nimport { GraphQLClient } from \"magiql\";\nimport { createRecoilStore } from \"magiql/recoil-store\";\n\nconst client = new GraphQLClient({\n  endpoint: \"...\",\n  useStore: createRecoilStore({\n    // optional, by default it uses the `id` field if available otherwise falls back to an unnormalized id\n    // this is the default function\n    getDataID: (record, type) =\u003e (record.id ? `${type}:${record.id}` : null),\n  }),\n});\n```\n\n#### Store Implementations\n\n- Recoil `createRecoilStore`\n  - **Recommended** if already working with the compiler and the Babel plugin\n  - Each field of an entity is stored as atom, entities and fragments are both selectors on the atoms\n  - Components subscribe to fields on entities (very granular and precise)\n  - Customize how to determine `id` for each entity\n- React Query's `QueryCache` as store `createNormalizedQueryCacheStore`\n  - Each entity is a query with the entity's id as the key\n  - Components subscribe to entities (not field-level subscriptions)\n  - Same API as `createRecoilStore`\n- React Query's QueryCache (unnormalized) `createQueryCacheStore`\n  - Client's QueryCache stores data attached to queries, and doesnt identify entities\n  - Doesn't allow cache manipulation with entities\n  - No options required since doesn't actually normally, but will still work with Fragments\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cbig\u003e\u003cstrong\u003eNaming convention for operations\u003c/strong\u003e\u003c/big\u003e\u003c/summary\u003e\n  \nRelay allows us to use fragments in queries and mutations without importing them as modules. For this to work, the names must be globally unique. It is also good habit to name the fragments and queries based on the components and props that use them. Thus, relay enforces a few conventions when it comes to naming your operations. These conventions are quite helpful and make your lives easier:\n  \n \n* Queries must be named `query ${ModuleName}Query { ... }`, eg, a query in file `Home.tsx` can be named `HomeQuery` or `HomeRoomsQuery`\n* Mutations must be named `mutation ${ModuleName}Mutation { ... }`, eg, a mutation in file `Home.tsx` can be named `HomeMutation` or `HomeDestroyMutation`\n* Fragments must be named `fragment ${ModuleName}_${propName} on type { ... }`, eg, a fragment in file `HomeDetails.tsx` where the prop for the fragment ref is `home` can be named `HomeDetails_home`\n  \n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cbig\u003e\u003cstrong\u003eDevtools\u003c/strong\u003e\u003c/big\u003e\u003c/summary\u003e\n \nYou can use the `magiql` Devtools which are inspired by `react-query-devtools` as follows:\n\n```tsx\nimport React from \"react\";\nimport { GraphQLClient, GraphQLClientProvider } from \"magiql\";\nimport GraphQLDevtools from \"magiql/devtools\";\n\nexport default function App({ children }) {\n  return (\n    \u003cGraphQLClientProvider client={client}\u003e\n      {children}\n      \u003cGraphQLDevtools defaultIsOpen defaultTab=\"store\" /\u003e\n    \u003c/GraphQLClientProvider\u003e\n  );\n}\n```\n\n\u003c/details\u003e\n\n# API\n\nThe following is the core API for `magiql`. With the help of amazing libraries like [`react-query`](https://github.com/tannerlinsley/react-query), [`relay-compiler`](https://github.com/facebook/relay) and [`recoil`](https://github.com/facebookexperimental/Recoil), we are able to provide the following features as a GraphQL client. The runtime is your familiar [`react-query`](https://github.com/tannerlinsley/react-query) api. There is also an optional build time setup that unlocks fragments and normalized store.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cbig\u003e\u003ccode\u003euseQuery\u003c/code\u003e\u003c/big\u003e\u003c/summary\u003e\n \nYou can use the `magiql` Devtools which are inspired by `react-query-devtools` as follows:\n\n```tsx\nimport React from \"react\";\nimport { GraphQLClient, GraphQLClientProvider } from \"magiql\";\nimport GraphQLDevtools from \"magiql/devtools\";\n\nexport default function App({ children }) {\n  return (\n    \u003cGraphQLClientProvider client={client}\u003e\n      {children}\n      \u003cGraphQLDevtools defaultIsOpen defaultTab=\"store\" /\u003e\n    \u003c/GraphQLClientProvider\u003e\n  );\n}\n```\n\n\u003c/details\u003e\n\n### Runtime\n\n- `useQuery(query, { variables, ...options })`, `usePaginatedQuery` and `useInfiniteQuery`: Data fetching patterns for GraphQL queries with numerous ways to customize them for refetching on different events\n  - All `options` from [`react-query`](https://github.com/tannerlinsley/react-query) are valid in the second argument\n  - No fetch function or query key required\n  - Stale-while-revalidate caching strategy\n  - Request deduplication\n  - Infinite queries\n  - Paginated queries\n  - Parallel and dependent queries\n  - Lazy queries\n  - Window Focus refetching\n  - Network Status refetching\n  - Polling/interval refetching\n  - Normalized caching (uses [`relay-compiler`](https://github.com/facebook/relay))\n- `useMutation`: a hook that provides a way to run GraphQL mutations (updates) on the server state conviniently with optmistic updates from your React app\n  - Optimistic updates\n  - Cache manipulation for entities in store\n- `useFragment`: a hook that allows you to properly encapsulate the date requirements of a component within it by subscribing to a GraphQL Fragment which resolves when provided a ref from the parent component via props\n  - Field-level subscription for fragments, only rerenders when that changes\n  - Allows nesting of fragments, great deal of composability and reusability\n  - Doesn't need to be responsible for fetching data (gets reference from parent component)\n  - **Requires that you run the [`relay-compiler`](https://github.com/facebook/relay) with either the Babel plugin or the cli command.**\n- `useGraphQLClient`: Access the underlying GraphQLClient\n  - Create new client using `GraphQLClient` class\n  - Add the `GraphQLClientProvider` with an instance of a `GraphQLClient`\n  - Can customize [`react-query`](https://github.com/tannerlinsley/react-query) config by using `new GraphQLClient({ endpoint: \"...\", queryConfig: {...} })\n- Exchanges based API for customizing query execution behaviour, allows for,\n  - logging, authentication, refreshing tokens, normalization, error handling\n- React Suspense support\n  - prowered by [`react-query`](https://github.com/tannerlinsley/react-query) (must be enabled)\n- React Native support\n  - Should work out of the box in `expo` or wherever the `react-native` `package.json` property is resolved\n\n## Foundation and inspirations\n\nHere are some of the big dependencies and inspirations for `magiql`:\n\n- [react-query](https://github.com/tannerlinsley/react-query)\n\n  - Data-fetching (network) layer\n  - Stale-while-revalidate caching strategy\n  - Request deduplication\n  - Window Focus refetching\n  - Network Status refetching\n  - Infinite queries\n  - Paginated queries\n  - Parallel and dependent queries\n  - Lazy queries\n  - Polling/interval refetching\n  - React Suspense support\n  - Normalized caching (with the help of the relay compiler)\n  - Differences:\n    - No query key required (GraphQL document name + variables form the key)\n    - No query fetch function required (provided by the client with customization options)\n    - Pass GraphQL document as first argument\n\n- [relay-compiler](https://github.com/facebook/relay)\n  - Build time optimizations (flatten fragments, add id fields, etc.)\n  - Code-generation for types (for full typescript support)\n  - Using fragments effectively with optimizations\n  - Concept: `useFragment` hook (game changer!) to declaratively define data needs for components independent of the fetching of the data\n  - Implementation: `relay-runtime` inspiration for (de)normalizating data\n  - `magiql` allows us to use the [`relay`](https://github.com/facebook/relay) hooks API without jumping to React Suspense (can't use the new relay hooks without that)\n  - **Do not need relay compliant server (will work with any GraphQL server)**\n- [recoil](https://github.com/facebookexperimental/Recoil) (opt-in)\n  - Alternative implementation for normalized cache for data\n  - Granular subscription (field-level) to data for fragments and queries based on exactly what they ask\n  - _similar implementation for jotai is also being worked on_\n- [urql](https://github.com/FormidableLabs/urql) (inspiration)\n  - Concept: `exchange` API to customize execution of graphql request\n  - Allowed easy ways to add logging, persisted queries, auth (with token refresh support)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnksaraf%2Fmagiql","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnksaraf%2Fmagiql","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnksaraf%2Fmagiql/lists"}