qwik-graphql-request
Simple GraphQL client and hook for Qwik applications built upon Apollo Client.
Highlights
- Simple GraphQL client for Qwik applications.
- Built on top of the Apollo Client core.
- Fully typesafe with GraphQL Typed Document Nodes.
- Creates one reusable GraphQL client per application.
- Built in
useQuery
hook to simplify GraphQL requests in Qwik. - Works seamlessly with Qwik's
<Resource>
component. - Reactive to variables passed into the query.
Installation
npm add qwik-graphql-client
pnpm add qwik-graphql-client
yarn add qwik-graphql-client
Qwik Start
Provide a GraphQL client context to child components. The context will be used by hooks to make GraphQL requests. To reuse your client throughout your entire application you can provide it in the root component as shown here.
import {
GraphQLClientProvider,
ApolloClient,
InMemoryCache,
} from "qwik-graphql-client";
export default component$(() => {
return (
<GraphQLClientProvider
clientGenerator$={$(
() =>
new ApolloClient({
cache: new InMemoryCache(),
uri: "http://localhost:2003/graphql",
})
)}
>
<Slot />
</GraphQLClientProvider>
);
});
Then, in child components you can use the useQuery
hook to make GraphQL requests and consume them using Qwik's <Resource>
component.
import { useQuery, gql } from "qwik-graphql-client";
export default component$(() => {
const variables = useStore({
artistID: "1",
});
const artist = useQuery(
gql`
query GetArtist($artistID: ID!) {
artist(artistID: $artistID) {
stageName
name
}
}
`,
variables
);
return (
<Resource
value={artist}
onResolved={(value) => <pre>{artist.stageName}</pre>}
onPending={...}
onRejected={...}
/>
)
});
Examples
Provide Context To Entire Application
To reuse your client throughout your entire application you can provide it in the root component.
import {
GraphQLClientProvider,
ApolloClient,
InMemoryCache,
} from "qwik-graphql-client";
export default component$(() => {
return (
<QwikCityProvider>
<head>...</head>
<body>
<GraphQLClientProvider
clientGenerator$={$(
() =>
new ApolloClient({
cache: new InMemoryCache(),
uri: "http://localhost:2003/graphql",
})
)}
>
<RouterOutlet />
</GraphQLClientProvider>
<ServiceWorkerRegistry />
</body>
</QwikCityProvider>
);
});
Using a Client Without the Context Provider
You can use a separate GraphQL client independent of the context provider by passing a clientGenerator$
function into hooks. Note: This only works with useLazyQuery
and useMutation
hooks.
import {
QwikGraphQLClient,
ApolloClient,
InMemoryCache,
} from "qwik-graphql-client";
export const useHero = (artistID: string) => {
return useLazyQuery(
gql`
query GetArtist($artistID: ID!) {
artist(artistID: $artistID) {
stageName
name
}
}
`,
{ artistID },
{
clientGenerator$: $(
() =>
new ApolloClient({
cache: new InMemoryCache(),
uri: "http://localhost:2003/graphql",
})
),
}
);
};
useLazyQuery
Using The useLazyQuery
hook is also available to use. It works the same as the useQuery
hook except it does not automatically execute the query. Instead, it returns a function that can be called to execute the query.
import { useLazyQuery, gql } from "qwik-graphql-client";
export default component$(() => {
const {executeQuery$, data} = useLazyQuery(
gql`
query GetArtist($artistID: ID!) {
artist(artistID: $artistID) {
stageName
name
}
}
`,
{ artistID: "1" }
);
return (
<div>
<button onClick={() => executeQuery()}>Get Hero</button>
<Resource
value={data}
onResolved={(value) => <div>{value.stageName}</div>}
onPending={...}
onRejected={...}
/>
</div>
})
useMutation
Using The useMutation
hook allows creating mutations to graphql servers. It works similar to the useLazyQuery
hook in that it returns a function that can be called to execute the mutation.
import { useMutation, gql } from "qwik-graphql-client";
export default component$(() => {
const variables = useStore({
name: "Stefani Joanne Angelina Germanotta",
stageName: "Lady Gaga"
})
const {executeMutation$, data} = useMutation(
gql`
mutation AddArtist($name: String!, $stageName: String!) {
hero(name: $name, stageName: $stageName) {
id
}
},
variables
`,
);
return (
<div>
<button onClick={() => getHero()}>Get Hero</button>
<Resource
value={data}
onResolved={(value) => <div>{value.name}</div>}
onPending={...}
onRejected={...}
/>
</div>
})
Passing in default headers and middleware to the client
You can pass in default headers and middleware that will be sent with every request in the useQuery hook.
import {
GraphQLClientProvider,
ApolloClient,
InMemoryCache,
HttpLink,
ApolloLink,
concat,
} from "qwik-graphql-client";
export default component$(() => {
const clientGenerator$ = $(() => {
const httpLink = new HttpLink({
uri: "http://localhost:2003/graphql",
});
const requestMiddleware = new ApolloLink((operation, forward) => {
console.log("request", operation);
return forward(operation);
});
const responseMiddleware = new ApolloLink((operation, forward) => {
console.log("response", operation);
return forward(operation);
});
return new ApolloClient({
cache: new InMemoryCache(),
link: requestMiddleware.concat(concat(middleware, httpLink)),
headers: {
Authorization: "Bearer 123",
},
});
});
return (
<GraphQLClientProvider clientGenerator$={clientGenerator$}>
<Slot />
</GraphQLClientProvider>
);
});
Enabling Apollo Client Devtools
To enable linking to the Apollo Client Devtools browser extension (Chrome, Firefox), add the following line to the Apollo Client returned from the clientGenerator$
.
new ApolloClient({
// Enable in development only.
connectToDevTools: import.meta.env.DEV,
// Enable always.
connectToDevTools: true,
...
});
Limitations
While this library is built on top of Apollo Client Core and the Apollo Client docs can be used for further documentation, this package does not support all of the features and some features are likely not to work as expected. This is very much a work in progress. If you find a bug or would like to see a feature added please open an issue or create a pull request.
Contributing
Contributions are welcome and appreciated, please open an issue and/or create a pull request.