Skip to content

Commit 3d41e11

Browse files
authored
add new example Usage GraphiQL 5 with Vite, React Router and ssr: true (#4077)
* add * upd * tsconfig * more * more * more * more * add new example [`Usage GraphiQL 5 with Vite, React Router and `ssr: true`](https://github.com/graphql/graphiql/tree/main/examples/example-graphiql-vite-react-router) * prettier * Update .changeset/pretty-camels-sniff.md * fix lint
1 parent fd3f9e6 commit 3d41e11

File tree

18 files changed

+1011
-30
lines changed

18 files changed

+1011
-30
lines changed

.changeset/chilled-peaches-wonder.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,3 @@ When using GraphiQL in Next.js app, you no longer need to use `next/dynamic`:
1717
-})
1818
+import { GraphiQL } from 'graphiql'
1919
```
20-
21-
When using GraphiQL with [React Router’s SSR mode](https://reactrouter.com/api/framework-conventions/react-router.config.ts#ssr),
22-
you no longer need to add `.client` to the file name to mark the GraphiQL component as a [client module](https://reactrouter.com/api/framework-conventions/client-modules).

.changeset/config.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"baseBranch": "main",
88
"ignore": [
99
"example-graphiql-vite",
10+
"example-graphiql-vite-react-router",
1011
"example-graphiql-webpack",
1112
"example-monaco-graphql-nextjs",
1213
"example-monaco-graphql-react-vite",

.changeset/pretty-camels-sniff.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
'graphiql': minor
3+
'@graphiql/plugin-code-exporter': minor
4+
'@graphiql/plugin-doc-explorer': minor
5+
'@graphiql/plugin-explorer': minor
6+
'@graphiql/plugin-history': minor
7+
'@graphiql/react': minor
8+
---
9+
10+
add new example [Usage GraphiQL 5 with Vite, React Router and `ssr: true`](https://github.com/graphql/graphiql/tree/main/examples/example-graphiql-vite-react-router)

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,5 @@ packages/graphiql/cypress/downloads/
5151
packages/graphiql/cypress/videos/
5252
packages/graphiql/typedoc/
5353
packages/graphiql/webpack/
54+
55+
.react-router/
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Usage GraphiQL with Vite, React Router and `ssr: true`
2+
3+
When using GraphiQL with [React Router’s SSR mode](https://reactrouter.com/api/framework-conventions/react-router.config.ts#ssr),
4+
you need to mark the GraphiQL component as a [client module](https://reactrouter.com/api/framework-conventions/client-modules)
5+
by adding `.client` to the file name.
6+
7+
```tsx
8+
// graphiql.client.tsx
9+
import { GraphiQL } from 'graphiql';
10+
import { createGraphiQLFetcher } from '@graphiql/toolkit';
11+
12+
const fetcher = createGraphiQLFetcher({ url: 'https://my.backend/graphql' });
13+
14+
export const graphiql = <GraphiQL fetcher={fetcher} />;
15+
```
16+
17+
```ts
18+
// route.ts
19+
import type { FC } from 'react';
20+
import type { LinksFunction, MetaFunction } from 'react-router';
21+
import graphiqlStyles from 'graphiql/style.css?url';
22+
import { graphiql } from './graphiql.client';
23+
24+
export const meta: MetaFunction = () => {
25+
return [{ title: 'API Explorer' }];
26+
};
27+
28+
export const links: LinksFunction = () => {
29+
return [{ rel: 'stylesheet', href: graphiqlStyles }];
30+
};
31+
32+
const Route: FC = () => {
33+
return graphiql;
34+
};
35+
36+
export default Route;
37+
```
38+
39+
## Setup
40+
41+
1. `yarn dev` to start Vite dev server.
42+
1. `yarn build` to build production ready transpiled files. Find the output in `dist` folder.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import type { FC } from 'react';
2+
import { Links, Meta, Outlet, Scripts, ScrollRestoration } from 'react-router';
3+
4+
const Root: FC = () => {
5+
return (
6+
<html lang="en">
7+
<head>
8+
<meta charSet="utf-8" />
9+
<meta name="viewport" content="width=device-width,initial-scale=1" />
10+
<Meta />
11+
<Links />
12+
</head>
13+
<body>
14+
<noscript>You need to enable JavaScript to run this app.</noscript>
15+
<Outlet />
16+
<ScrollRestoration />
17+
<Scripts />
18+
</body>
19+
</html>
20+
);
21+
};
22+
23+
export default Root;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { flatRoutes } from '@react-router/fs-routes';
2+
3+
export default flatRoutes();
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import type { GraphiQLProps } from 'graphiql';
2+
3+
export function createFetcher(apiUrl: string): GraphiQLProps['fetcher'] {
4+
return async function (graphQLParams, opts) {
5+
const response = await fetch(apiUrl, {
6+
method: 'POST',
7+
headers: {
8+
...opts?.headers,
9+
'Content-Type': 'application/json',
10+
},
11+
body: JSON.stringify(graphQLParams),
12+
});
13+
14+
return response.json();
15+
};
16+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
body {
2+
margin: 0;
3+
}
4+
5+
.graphiql-container {
6+
height: 100dvh;
7+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import type { FC } from 'react';
2+
import { GraphiQL } from 'graphiql';
3+
import { ToolbarButton, useGraphiQL } from '@graphiql/react';
4+
import { createFetcher } from './create-fetcher';
5+
import 'graphiql/setup-workers/esm.sh';
6+
7+
export const graphiql = (
8+
<GraphiQL
9+
dangerouslyAssumeSchemaIsValid
10+
defaultEditorToolsVisibility="variables"
11+
fetcher={createFetcher('https://graphql.earthdata.nasa.gov/api')}
12+
isHeadersEditorEnabled={false}
13+
>
14+
<GraphiQL.Logo>API Explorer</GraphiQL.Logo>
15+
<GraphiQL.Toolbar>
16+
{({ prettify, copy, merge }) => (
17+
<>
18+
{prettify}
19+
{copy}
20+
{merge}
21+
<Button />
22+
</>
23+
)}
24+
</GraphiQL.Toolbar>
25+
</GraphiQL>
26+
);
27+
28+
const Button: FC = () => {
29+
const { queryEditor, variableEditor } = useGraphiQL(state => ({
30+
queryEditor: state.queryEditor,
31+
variableEditor: state.variableEditor,
32+
}));
33+
34+
async function onShareExplorer(): Promise<void> {
35+
const shareableURL = new URL('/explorer', location.origin);
36+
const operations = queryEditor!.getValue();
37+
const variables = variableEditor!.getValue();
38+
if (operations) {
39+
shareableURL.searchParams.set('query', encodeURIComponent(operations));
40+
}
41+
if (variables) {
42+
shareableURL.searchParams.set('variables', encodeURIComponent(variables));
43+
}
44+
const url = shareableURL.toString();
45+
await navigator.clipboard.writeText(url);
46+
}
47+
48+
return (
49+
<ToolbarButton
50+
label="Share your Explorer query"
51+
onClick={onShareExplorer}
52+
style={{ textAlign: 'center' }}
53+
title="Share your Explorer query"
54+
>
55+
S
56+
</ToolbarButton>
57+
);
58+
};

0 commit comments

Comments
 (0)