An Interest In:
Web News this Week
- April 2, 2024
- April 1, 2024
- March 31, 2024
- March 30, 2024
- March 29, 2024
- March 28, 2024
- March 27, 2024
How to use GraphQL and React Query with GraphQL Code Generator (based on Next.Js)
Abstract
GraphQL
. REST API
schema
DB
sql
.
GQL
Query React Query
GQL
pain point Type
Schema
, GraphQL Code Generator
GQL
.
GQL
GQL ?: https://tech.kakao.com/2019/08/01/graphql-basic/
Getting Started
Next.Js TypeScript
Terminal
pnpm create next-app . --typescript
React Query
GQL
Note
React Query
TanStack Query
Sevelte Query
.
Terminal
pnpm add -S @tanstack/react-query graphql graphql-requestpnpm add -D @tanstack/react-query-devtools
dotenv
Terminal
pnpm add -S dotenv
.env.local
API URL
GraphQL
API Fake GraphQL GraphQLZero
.
GraphQLZero Link: https://graphqlzero.almansi.me/
.env.local
NEXT_PUBLIC_GRAPHQL_URL=https://graphqlzero.almansi.me/api
env Type Error next-constants.d.ts
default type
next-constants.d.ts
declare namespace NodeJS { export interface ProcessEnv { NEXT_PUBLIC_GRAPHQL_URL: string; }}
react query
+ gql
react query
_app.tsx
Note
SSR
SEO
UX
Hydration State
Hydration
pageProps.dehydratedState
Serverside Props
refetch
UX
const queryClient = new QueryClient({ defaultOptions: { queries: { refetchOnMount: false, refetchOnWindowFocus: false, refetchOnReconnect: false, }, },});
pages/_app.tsx
import '../styles/globals.css';import type { AppProps } from 'next/app';import { Hydrate, QueryClientProvider, QueryClient } from '@tanstack/react-query';import { ReactQueryDevtools } from '@tanstack/react-query-devtools';export const queryClient = new QueryClient({ defaultOptions: { queries: { refetchOnMount: false, refetchOnWindowFocus: false, refetchOnReconnect: false, }, },});function MyApp({ Component, pageProps }: AppProps) { return ( <QueryClientProvider client={queryClient}> <Hydrate state={pageProps.dehydratedState}> <Component {...pageProps} />; <ReactQueryDevtools initialIsOpen /> </Hydrate> </QueryClientProvider> );}export default MyApp;
GraphQlZero
album
Resolver Query react query
legacy.tsx
.
Note
type
schema
GraphQlZero
Docs
interface AlbumQuery { album: { id: string; title: string; user: { id: string; name: string; username: string; email: string; company: { name: string; bs: string; }; }; photos: { data: { id: string; title: string; url: string; }; }; };}const albumQueryDocument = gql` query album($id: ID!) { album(id: $id) { id title user { id name username email company { name bs } } photos { data { id title url } } } }`;
getStaticProps
Server
dehydratedState
.
export const getStaticProps = async () => { await queryClient.prefetchQuery(['album'], useAlbumFetcher); return { props: { dehydratedState: dehydrate(queryClient), }, };};
pages/legacy.tsx
import type { NextPage } from 'next';import { useQuery, dehydrate } from '@tanstack/react-query';import { request, gql } from 'graphql-request';import { queryClient } from './_app';interface AlbumQuery { album: { id: string; title: string; user: { id: string; name: string; username: string; email: string; company: { name: string; bs: string; }; }; photos: { data: { id: string; title: string; url: string; }; }; };}const albumQueryDocument = gql` query album($id: ID!) { album(id: $id) { id title user { id name username email company { name bs } } photos { data { id title url } } } }`;const useAlbumFetcher = async () => await request<AlbumQuery, { id: string }>( process.env.NEXT_PUBLIC_GRAPHQL_URL, albumQueryDocument, { id: '2', } );export const getStaticProps = async () => { await queryClient.prefetchQuery(['album'], useAlbumFetcher); return { props: { dehydratedState: dehydrate(queryClient), }, };};const Legacy: NextPage = () => { const { data } = useQuery<AlbumQuery>(['album'], useAlbumFetcher); const { album } = data!; return ( <> <header style={{ textAlign: 'center' }}> <h1>Hello GraphQL + React Query !</h1> </header> <hr /> <main> <p style={{ textAlign: 'center', color: 'grey' }}>{JSON.stringify(album)}</p> </main> </> );};export default Legacy;
preview
gql
+ react query
.
Pain Point .
schema
Type
schema
Type
Docs
Pain Point GraphQL Code Generator
.
GQL Code Generator
Terminal
# code generator core pnpm add -D @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-operations# code generator react query pnpm add -D @graphql-codegen/typescript-react-query @graphql-codegen/typescript-graphql-request# code generator yaml loader pnpm add -D yaml-loader
codegen.yml
Note
schema
graphql
[filename].graphql
. (ts )documents
gql schema
.
documents: 'graphql/**/!(*.generated).{graphql,ts}'
schema
GQL URL
.
schema: ${NEXT_PUBLIC_GRAPHQL_URL}
- . : https://www.graphql-code-generator.com/plugins/typescript/typescript-react-query
exposeFetcher
:GetStaticProps
,GetServerSideProps
prefetch query fetcher exportexposeQueryKey
:react quey
query key
exportfetcher
: fetcher .graphql-request
.
codegen.yml
documents: 'graphql/**/!(*.generated).{graphql,ts}'schema: ${NEXT_PUBLIC_GRAPHQL_URL}require: - ts-node/registergenerates: graphql/generated.ts: plugins: - typescript - typescript-operations - typescript-react-query config: interfacePrefix: 'I' typesPrefix: 'I' skipTypename: true declarationKind: 'interface' noNamespaces: true pureMagicComment: true exposeQueryKeys: true exposeFetcher: true withHooks: true fetcher: graphql-request
pakage.json
graphql-codegen
script
package.json
{ ... "scripts": { ... "generate:gql": "graphql-codegen --require dotenv/config --config codegen.yml dotenv_config_path=.env.local" }, ...}
graphql
schema
album
schema album.graphql
graphql/album.graphql
query album($id: ID!) { album(id: $id) { id title user { id name username email company { name bs } } photos { data { id title url } } }}
.
structure
. graphql/ album.graphql pages/ _app.tsx index.tsx legacy.tsx ... codegen.yml next-constants.d.ts package.json ...
GraphQL Generator
Type
, Method
script graphql
generated.ts
schema
Query Function
, Type
. ( )
Terminal
pnpm generate:gql Parse Configuration Generate outputs
Query Method
Type
album
pages
new.tsx
legacy.tsx
.
Note
useQuery
useAlbumQuery
const { data } = useAlbumQuery(gqlClient, { id: '3' });
prefetchQuery
key
,fetcher
useAlbumQuery.getKey()
,useAlbumQuery.fetcher()
await queryClient.prefetchQuery( useAlbumQuery.getKey({ id: '3' }), useAlbumQuery.fetcher(gqlClient, { id: '3' }) );
Type
-
server spec
schema
code generate
type
, .
pages/new.tsx
import type { NextPage } from 'next';import { dehydrate } from '@tanstack/react-query';import { GraphQLClient } from 'graphql-request';import { useAlbumQuery } from '../graphql/generated';import { queryClient } from './_app';const gqlClient = new GraphQLClient(process.env.NEXT_PUBLIC_GRAPHQL_URL);export const getStaticProps = async () => { await queryClient.prefetchQuery( useAlbumQuery.getKey({ id: '2' }), useAlbumQuery.fetcher(gqlClient, { id: '2' }) ); return { props: { dehydratedState: dehydrate(queryClient), }, };};const New: NextPage = () => { const { data } = useAlbumQuery(gqlClient, { id: '2' }); const { album } = data!; return ( <> <header style={{ textAlign: 'center' }}> <h1>Hello GraphQL + React Query !</h1> </header> <hr /> <main> <p style={{ textAlign: 'center', color: 'grey' }}>{JSON.stringify(album)}</p> </main> </> );};export default New;
preview
Stackblitz Sample
Conclusion
GraphQL Code Generator
Server Spec schema
type
GQL
Pain Point . SSR
hydration
technique .
REST API
. REST API
GQL
. Backend Frontend Communication Gap GQL
.
GQL
.
GQL Code Generator
.
Link: https://www.graphql-code-generator.com/
Original Link: https://dev.to/soom/how-to-use-graphql-and-react-query-with-graphql-code-generator-based-on-nextjs-23jj
Dev To
An online community for sharing and discovering great ideas, having debates, and making friendsMore About this Source Visit Dev To