1
1
import 'regenerator-runtime/runtime.js' ;
2
- import * as React from 'react' ;
2
+ import React , { useState , useEffect , useMemo } from 'react' ;
3
3
import { createRoot } from 'react-dom/client' ;
4
4
import { GraphiQL } from 'graphiql' ;
5
5
import { explorerPlugin } from '@graphiql/plugin-explorer' ;
6
6
import { getSnippets } from './snippets' ;
7
7
import { codeExporterPlugin } from '@graphiql/plugin-code-exporter' ;
8
- import 'graphiql/style.css' ;
9
- import '@graphiql/plugin-explorer/style.css' ;
10
- import '@graphiql/plugin-code-exporter/style.css' ;
11
8
import { createGraphiQLFetcher } from '@graphiql/toolkit' ;
12
9
import { useStorage } from '@graphiql/react' ;
13
-
14
- export const STARTING_URL =
15
- 'https://swapi-graphql.netlify.app/.netlify/functions/index' ;
16
-
17
- import './index.css' ;
18
10
import { serverSelectPlugin , LAST_URL_KEY } from './select-server-plugin' ;
11
+ import './index.css' ;
12
+
13
+ export const STARTING_URL = 'https://countries.trevorblades.com' ;
19
14
20
15
if ( 'serviceWorker' in navigator ) {
21
16
window . addEventListener ( 'load' , ( ) => {
22
17
navigator . serviceWorker
23
18
. register ( '/service-worker.js' )
24
19
. then ( registration => {
25
- console . log ( 'SW registered: ' , registration ) ;
20
+ console . log ( 'SW registered:' , registration ) ;
26
21
} )
27
22
. catch ( registrationError => {
28
- console . log ( 'SW registration failed: ' , registrationError ) ;
23
+ console . error ( 'SW registration failed:' , registrationError ) ;
29
24
} ) ;
30
25
} ) ;
31
26
}
@@ -59,24 +54,21 @@ const style = { height: '100vh' };
59
54
*/
60
55
const explorer = explorerPlugin ( ) ;
61
56
62
- const App = ( ) => {
63
- // TODO: `storage` will be always `null`, fix it to have access outside `StorageContextProvider` after zustand migration
64
- const storage = useStorage ( ) ;
65
- const lastUrl = storage ?. get ( LAST_URL_KEY ) ;
66
- const [ currentUrl , setUrl ] = React . useState ( lastUrl ?? STARTING_URL ) ;
57
+ function App ( ) {
58
+ const [ currentUrl , setUrl ] = useState ( '' ) ;
67
59
// TODO: a breaking change where we make URL an internal state concern, and then expose hooks
68
60
// so that you can handle/set URL state internally from a plugin
69
61
// fetcher could then pass a dynamic URL config object to the fetcher internally
70
- const exporter = React . useMemo (
62
+ const exporter = useMemo (
71
63
( ) =>
72
64
codeExporterPlugin ( { snippets : getSnippets ( { serverUrl : currentUrl } ) } ) ,
73
65
[ currentUrl ] ,
74
66
) ;
75
- const fetcher = React . useMemo (
67
+ const fetcher = useMemo (
76
68
( ) => createGraphiQLFetcher ( { url : currentUrl } ) ,
77
69
[ currentUrl ] ,
78
70
) ;
79
- const serverSelect = React . useMemo (
71
+ const serverSelect = useMemo (
80
72
( ) => serverSelectPlugin ( { url : currentUrl , setUrl } ) ,
81
73
[ currentUrl ] ,
82
74
) ;
@@ -87,9 +79,26 @@ const App = () => {
87
79
plugins = { [ serverSelect , explorer , exporter ] }
88
80
fetcher = { fetcher }
89
81
shouldPersistHeaders
90
- />
82
+ >
83
+ < GraphiQLStorageBound setUrl = { setUrl } />
84
+ </ GraphiQL >
91
85
) ;
92
- } ;
86
+ }
87
+
88
+ /**
89
+ * `useStorage` is a context hook that's only available within the `<GraphiQL>`
90
+ * provider tree. `<GraphiQLStorageBound>` must be rendered as a child of `<GraphiQL>`.
91
+ */
92
+ function GraphiQLStorageBound ( { setUrl } ) {
93
+ const storage = useStorage ( ) ;
94
+ const lastUrl = storage . get ( LAST_URL_KEY ) ?? STARTING_URL ;
95
+
96
+ useEffect ( ( ) => {
97
+ setUrl ( lastUrl ) ;
98
+ } , [ lastUrl , setUrl ] ) ;
99
+
100
+ return null ;
101
+ }
93
102
94
103
const root = createRoot ( document . getElementById ( 'root' ) ) ;
95
104
root . render ( < App /> ) ;
0 commit comments