/
index.html
982 lines (927 loc) · 121 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
<!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta http-equiv="X-UA-Compatible" content="IE=edge"/><title>API Reference · Relay</title><meta name="viewport" content="width=device-width"/><meta name="generator" content="Docusaurus"/><meta name="description" content="## Relay Hooks"/><meta name="docsearch:version" content="v1.7.0"/><meta name="docsearch:language" content="en"/><meta property="og:title" content="API Reference · Relay"/><meta property="og:type" content="website"/><meta property="og:url" content="https://relay.dev/"/><meta property="og:description" content="## Relay Hooks"/><meta property="og:image" content="https://relay.dev/img/relay.png"/><meta name="twitter:card" content="summary"/><meta name="twitter:image" content="https://relay.dev/img/relay.png"/><link rel="shortcut icon" href="/img/favicon.png"/><link rel="stylesheet" href="https://cdn.jsdelivr.net/docsearch.js/1/docsearch.min.css"/><link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css"/><script type="text/javascript" src="/js/redirect.js"></script><script src="https://unpkg.com/vanilla-back-to-top@7.1.14/dist/vanilla-back-to-top.min.js"></script><script>
document.addEventListener('DOMContentLoaded', function() {
addBackToTop(
{"zIndex":100}
)
});
</script><script src="/js/scrollSpy.js"></script><link rel="stylesheet" href="/css/main.css"/><script src="/js/codetabs.js"></script></head><body class="sideNavVisible separateOnPageNav"><div class="fixedHeaderContainer"><div class="headerWrapper wrapper"><header><a href="/en"><h2 class="headerTitle">Relay</h2></a><a href="/en/versions"><h3>v1.7.0</h3></a><div class="navigationWrapper navigationSlider"><nav class="slidingNav"><ul class="nav-site nav-site-internal"><li class=""><a href="/docs/en/v1.7.0/introduction-to-relay" target="_self">Docs</a></li><li class=""><a href="/en/help" target="_self">Help</a></li><li class="navSearchWrapper reactNavSearchWrapper"><input type="text" id="search_input_react" placeholder="Search" title="Search"/></li><li class=""><a href="https://github.com/facebook/relay" target="_self">GitHub</a></li><li class=""><a target="_self"></a></li></ul></nav></div></header></div></div><div class="navPusher"><div class="docMainWrapper wrapper"><div class="container mainContainer docsContainer"><div class="wrapper"><div class="post"><header class="postHeader"><a class="edit-page-link button" href="https://github.com/facebook/relay/edit/master/docs/RelayHooks-ApiReference.md" target="_blank" rel="noreferrer noopener">Edit</a><h1 id="__docusaurus" class="postHeaderTitle">API Reference</h1></header><article><div><span><h2><a class="anchor" aria-hidden="true" id="relay-hooks"></a><a href="#relay-hooks" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Relay Hooks</h2>
<p><strong>Relay Hooks</strong> APIs are fully compatible with <a href="https://reactjs.org/docs/concurrent-mode-intro.html">React Concurrent Mode</a>. They are also fully compatible with <a href="https://relay.dev/docs/en/introduction-to-relay">existing Relay APIs</a>, meaning that they can be used together in the same application; Relay components will interop correctly regardless of whether they were written as Relay Hooks or as Relay containers.</p>
<p>For a usage guide, see: <a href="a-guided-tour-of-relay"><strong>A Guided Tour of Relay</strong></a>.</p>
<p>For a full example using Relay Hooks and our integration with <a href="https://reactjs.org/docs/concurrent-mode-suspense.html">Suspense for Data Fetching</a>, check out <a href="https://github.com/relayjs/relay-examples/tree/master/issue-tracker">relay-examples/issue-tracker</a>.</p>
<h3><a class="anchor" aria-hidden="true" id="benefits"></a><a href="#benefits" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Benefits</h3>
<ul>
<li>Using Hooks in general make for a somewhat simpler API; our hope is that the fact that they are functions that have specific inputs and outputs might be more clear than the “magic” that happens in Higher Order Components, where the prop you pass from above is not the same as the prop you receive inside the component.</li>
<li>They also allow us to not pollute the React tree with multiple nested layers of Higher Order Components that wrap your actual components, which make them easier to inspect and debug in dev tools, and can help speed up React rendering.</li>
<li>Hooks are also a lot simpler to Flow type, and with Relay Hooks we were able to guarantee better type safety than we could with our HOC / Renderer APIs.</li>
<li>Relay Hooks have more capabilities compared to their container counterparts, for example by being integrated with <a href="a-guided-tour-of-relay#loading-states-with-suspense">Suspense</a> for loading states, and providing new capabilities such as directly rendering data that is cached in the Relay store, which were previously not available.</li>
<li>We also took the opportunity to simplify some of our APIs that were previously notoriously complicated, such as refetching and pagination. We've highlighted some of the main differences in those APIs in our documentation below (<a href="#differences-with-refetchcontainer">Differences with RefetchContainer</a>, <a href="#differences-with-paginationcontainer">Differences with PaginationContainer</a>).</li>
<li>Finally, Hooks were written to be compatible with React's Concurrent Mode, as opposed to our HOC / Renderer APIs which are unsafe to use in Concurrent Mode.</li>
</ul>
<h3><a class="anchor" aria-hidden="true" id="caveats"></a><a href="#caveats" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Caveats</h3>
<ul>
<li>Relay Hooks are integrated with <a href="https://reactjs.org/docs/concurrent-mode-intro.html">React Concurrent Mode</a> and <a href="a-guided-tour-of-relay#loading-states-with-suspense">Suspense</a>, which means that they are designed to work in conjunction with apis like <a href="https://reactjs.org/docs/concurrent-mode-patterns.html#transitions"><code>useTransition</code></a>. However, APIs like <code>useTransition</code> will not work as expected in React Legacy Mode (i.e. outside of Concurrent Mode), in particular when providing a timeout in a Suspense config; this affects apis like <a href="#useblockingpaginationfragment"><code>useBlockingPaginationFragment</code></a>. For this reason, we recommend using Relay Hooks apis in Concurrent Mode.</li>
</ul>
<hr>
<h3><a class="anchor" aria-hidden="true" id="relayenvironmentprovider"></a><a href="#relayenvironmentprovider" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><code>RelayEnvironmentProvider</code></h3>
<p>This component is used set a Relay environment in React Context. Usually, a <em>single</em> instance of this component should be rendered at the very root of the application, in order to set the Relay environment for the whole application:</p>
<pre><code class="hljs css language-javascript"><span class="hljs-keyword">const</span> React = <span class="hljs-built_in">require</span>(<span class="hljs-string">'React'</span>);
<span class="hljs-keyword">const</span> {RelayEnvironmentProvider} = <span class="hljs-built_in">require</span>(<span class="hljs-string">'react-relay/hooks'</span>);
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Root</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-keyword">return</span> (
<span class="xml"><span class="hljs-tag"><<span class="hljs-name">RelayEnvironmentProvider</span> <span class="hljs-attr">environment</span>=<span class="hljs-string">{environment}</span>></span>
<span class="hljs-tag"><<span class="hljs-name">App</span> /></span>
<span class="hljs-tag"></<span class="hljs-name">RelayEnvironmentProvider</span>></span></span>
);
}
<span class="hljs-built_in">module</span>.exports = Root;
</code></pre>
<h4><a class="anchor" aria-hidden="true" id="props"></a><a href="#props" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Props</h4>
<ul>
<li><code>environment</code>: The Relay environment to set in React Context. Any Relay Hooks (like <a href="#uselazyloadquery"><code>useLazyLoadQuery</code></a> or <a href="#usefragment">useFragment</a>) used as descendants of this provider component will use the Relay environment specified here</li>
</ul>
<h4><a class="anchor" aria-hidden="true" id="differences-with-current-apis"></a><a href="#differences-with-current-apis" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Differences with current APIs</h4>
<ul>
<li>In Relay Modern, we used the <code>QueryRenderer</code> component to both set an environment in Context and fetch a query. With Relay Hooks, these 2 concepts are separate: we use a single <code>RelayEnvironmentProvider</code> to set the environment in context for the whole application, and we can use one or more <code>useLazyLoadQuery</code> hooks to fetch any queries under the same environment set by the provider.</li>
</ul>
<h3><a class="anchor" aria-hidden="true" id="userelayenvironment"></a><a href="#userelayenvironment" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><code>useRelayEnvironment</code></h3>
<p>Hook used to access a Relay environment that was set by a <a href="#relayenvironmentprovider"><code>RelayEnvironmentProvider</code></a>:</p>
<pre><code class="hljs css language-javascript"><span class="hljs-keyword">const</span> React = <span class="hljs-built_in">require</span>(<span class="hljs-string">'React'</span>);
<span class="hljs-keyword">const</span> {useRelayEnvironment} = <span class="hljs-built_in">require</span>(<span class="hljs-string">'react-relay/hooks'</span>);
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MyComponent</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-keyword">const</span> environment = useRelayEnvironment();
<span class="hljs-keyword">const</span> handler = useCallback(<span class="hljs-function"><span class="hljs-params">()</span> =></span> {
<span class="hljs-comment">// For example, can be used to pass the environment to functions</span>
<span class="hljs-comment">// that require a Relay environment.</span>
commitMutation(environment, ...);
}, [environment])
<span class="hljs-keyword">return</span> (...);
}
<span class="hljs-built_in">module</span>.exports = Root;
</code></pre>
<h3><a class="anchor" aria-hidden="true" id="usequeryloader"></a><a href="#usequeryloader" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><code>useQueryLoader</code></h3>
<p>Hook used to make it easy to safely load queries, while avoiding data leaking into the Relay store. It will keep a query reference stored in state, and dispose of it when it is no longer accessible via state.</p>
<p>This hook is designed to be used with <a href="#usepreloadedquery"><code>usePreloadedQuery</code></a> to implement the <a href="https://reactjs.org/docs/concurrent-mode-suspense.html#approach-3-render-as-you-fetch-using-suspense">“render-as-you-fetch”</a> pattern.</p>
<pre><code class="hljs css language-javascript">const React = require('React');
const {useQueryLoader, usePreloadedQuery} = require('react-relay/hooks');
const query = graphql`
query AppQuery($id: ID!) {
user(id: $id) {
name
}
}
`;
function QueryFetcherExample(): React.MixedElement {
const [
queryReference,
loadQuery,
disposeQuery,
] = useQueryLoader(query);
return (<>
{
queryReference == null && (<Button
onClick={() => loadQuery({})}
>
Click to reveal the name
</Button>)
}
{
queryReference != null && (<>
<Button onClick={disposeQuery}>
Click to hide the name and dispose the query.
</Button>
<React.Suspense fallback="Loading">
<NameDisplay queryReference={queryReference} />
</React.Suspense>
</>)
}
</>);
}
function NameDisplay({ queryReference }) {
const data = usePreloadedQuery<AppQuery>(query, queryReference);
return <h1>{data.user?.name}</h1>;
}
</code></pre>
<h4><a class="anchor" aria-hidden="true" id="arguments"></a><a href="#arguments" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Arguments</h4>
<ul>
<li><code>query</code>: the graphql tagged node containing a query.</li>
</ul>
<h4><a class="anchor" aria-hidden="true" id="flow-type-parameters"></a><a href="#flow-type-parameters" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Flow Type Parameters</h4>
<ul>
<li><code>TQuery</code>: the type of the query</li>
</ul>
<h4><a class="anchor" aria-hidden="true" id="return-value"></a><a href="#return-value" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Return Value</h4>
<p>A tuple containing the following values:</p>
<ul>
<li><p><code>queryReference</code>: the query reference, or null.</p></li>
<li><p><code>loadQuery</code>: a callback that, when executed, will load a query, which will be accessible as <code>queryReference</code>. If a previous query was loaded, it will dispose of it. It will throw an error if called during React’s render phase.</p>
<ul>
<li>Parameters
<ul>
<li><code>variables</code>: the variables with which the query is loaded.</li>
<li><code>options</code>: LoadQueryOptions. An optional options object, containing the following keys:
<ul>
<li><code>fetchPolicy</code>: Optional. Determines if cached data should be used, and when to send a network request based on the cached data that is currently available in the Relay store (for more details, see our <a href="https://relay.dev/docs/en/a-guided-tour-of-relay#fetch-policies">Fetch Policies</a> and <a href="https://relay.dev/docs/en/a-guided-tour-of-relay#garbage-collection-in-relay">Garbage Collection</a> guides):
<ul>
<li><code>"store-or-network"</code>: (default) will reuse locally cached data and will only send a network request if any data for the query is missing. If the query is fully cached, a network request will not be made.</li>
<li><code>"store-and-network"</code>: will reuse locally cached data and will always send a network request, regardless of whether any data was missing from the local cache or not.</li>
<li><code>"network-only"</code>: will not reuse locally cached data, and will always send a network request to fetch the query, ignoring any data that might be locally cached in Relay.</li>
</ul></li>
<li><code>networkCacheConfig</code>: Optional. Object containing cache config options for the network layer. Note the the network layer contains a additional query response cache which will reuse network responses for identical queries. If you want to bypass this cache completely, pass <code>{force: true}</code> as the value for this option.</li>
<li><code>onQueryAstLoadTimeout</code>: Optional. Callback that is executed if the request to fetch the query AST does not complete in time.</li>
</ul></li>
</ul></li>
</ul></li>
<li><p><code>disposeQuery</code>: a callback that, when executed, will set queryReference to null and call <code>.dispose()</code> on it. It has type <code>() => void</code>. It should not be called during React’s render phase.</p></li>
</ul>
<h4><a class="anchor" aria-hidden="true" id="behavior"></a><a href="#behavior" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Behavior</h4>
<ul>
<li>The <code>loadQuery</code> callback will fetch data. Once the data are available, the data from the query will be written to the store. This differs from the behavior of <code>preloadQuery_DEPRECATED</code>, which would only write data to the store when the query was passed to <code>usePreloadedQuery</code>.</li>
<li>This query reference will be retained by the Relay store, preventing the data from being garbage collected. Once <code>.dispose()</code> is called on the query reference, the data is liable to be garbage collected.</li>
<li>The <code>loadQuery</code> will throw an error if it is called during React’s render phase.</li>
</ul>
<h3><a class="anchor" aria-hidden="true" id="usepreloadedquery"></a><a href="#usepreloadedquery" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><code>usePreloadedQuery</code></h3>
<p>Hook used to access data fetched by an earlier call to <code>loadQuery()</code>[#loadquery] or from <code>useQueryLoader</code>[#usequeryloader]. This implements the "Render-as-You-Fetch" pattern:</p>
<ul>
<li>Call the <code>loadQuery</code> callback returned from <code>useQueryLoader</code>. This will store a query reference in React state.
<ul>
<li>You can also call the imported <code>loadQuery</code> directly, which returns a query reference. In that case, store the item in state or in a React ref, and call <code>dispose()</code> on the value when you are no longer using it.</li>
</ul></li>
<li>Then, in your render method, consume the query reference with <code>usePreloadedQuery()</code>. This call will suspend if the query is still pending, throw an error if it failed, and otherwise return the query results.</li>
<li>This pattern is encouraged over <code>useLazyLoadQuery()</code> as it can allow fetching data earlier while not blocking rendering.</li>
</ul>
<pre><code class="hljs css language-javascript">const React = require('React');
const {useQueryLoader, usePreloadedQuery} = require('react-relay/hooks');
const query = graphql`
query AppQuery($id: ID!) {
user(id: $id) {
name
}
}
`;
function QueryFetcherExample(): React.MixedElement {
const [
queryReference,
loadQuery,
disposeQuery,
] = useQueryLoader(query);
return (<>
{
queryReference == null && (<Button
onClick={() => loadQuery({})}
>
Click to reveal the name
</Button>)
}
{
queryReference != null && (<>
<Button onClick={disposeQuery}>
Click to hide the name and dispose the query.
</Button>
<React.Suspense fallback="Loading">
<NameDisplay queryReference={queryReference} />
</React.Suspense>
</>)
}
</>);
}
function NameDisplay({ queryReference }) {
const data = usePreloadedQuery<AppQuery>(query, queryReference);
return <h1>{data.user?.name}</h1>;
}
</code></pre>
<h4><a class="anchor" aria-hidden="true" id="arguments-1"></a><a href="#arguments-1" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Arguments</h4>
<ul>
<li><code>query</code>: GraphQL query specified using a <code>graphql</code> template literal.</li>
<li><code>preloadedQuery</code>: The result of calling <a href="#preloadquery"><code>preloadQuery_DEPRECATED()</code></a>. Note that the same query should be used in the call to <code>preloadQuery_DEPRECATED()</code> and <code>usePreloadedQuery()</code>.</li>
</ul>
<h4><a class="anchor" aria-hidden="true" id="flow-type-parameters-1"></a><a href="#flow-type-parameters-1" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Flow Type Parameters</h4>
<ul>
<li><code>TQuery</code>: Type parameter that should correspond to the Flow type for the specified query. This type is available to import from the the auto-generated file: <code><query_name>.graphql.js</code>.</li>
</ul>
<h4><a class="anchor" aria-hidden="true" id="return-value-1"></a><a href="#return-value-1" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Return Value</h4>
<ul>
<li><code>data</code>: Object that contains data which has been read out from the Relay store; the object matches the shape of specified query.
<ul>
<li>The Flow type for data will also match this shape, and contain types derived from the GraphQL Schema. For example, the type of <code>data</code> above is: <code>{| user: ?{| name: ?string |} |}</code>.</li>
</ul></li>
</ul>
<h4><a class="anchor" aria-hidden="true" id="behavior-1"></a><a href="#behavior-1" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Behavior</h4>
<ul>
<li>It is expected for <code>usePreloadedQuery</code> to have been rendered under a <a href="#relayenvironmentprovider"><code>RelayEnvironmentProvider</code></a>, in order to access the correct Relay environment, otherwise an error will be thrown.</li>
<li>Calling <code>usePreloadedQuery</code> will return the data for this query if the <code>preloadQuery_DEPRECATED()</code> call has completed. It will <a href="a-guided-tour-of-relay#loading-states-with-suspense"><em><em>suspend</em></em></a> while the network request is in flight. If <code>usePreloadedQuery</code> causes the component to suspend, you'll need to make sure that there's a <code>Suspense</code> ancestor wrapping this component in order to show the appropriate loading state. This hook will throw an error if the <code>preloadQuery_DEPRECATED()</code> fetch fails.
<ul>
<li>For more details on Suspense, see our <a href="a-guided-tour-of-relay#loading-states-with-suspense">Loading States with Suspense</a> guide.</li>
</ul></li>
<li>The component is automatically subscribed to updates to the query data: if the data for this query is updated anywhere in the app, the component will automatically re-render with the latest updated data.</li>
</ul>
<h3><a class="anchor" aria-hidden="true" id="uselazyloadquery"></a><a href="#uselazyloadquery" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><code>useLazyLoadQuery</code></h3>
<p>Hook used to fetch a GraphQL query <em>during</em> render. This hook can trigger multiple round trips, thereby degrading performance. Instead, prefer <a href="#usequeryloader"><code>useQueryLoader()</code></a> and <a href="#usepreloadedquery"><code>usePreloadedQuery()</code></a> instead.</p>
<pre><code class="hljs css language-javascript"><span class="hljs-keyword">import</span> type {AppQuery} <span class="hljs-keyword">from</span> <span class="hljs-string">'AppQuery.graphql'</span>;
<span class="hljs-keyword">const</span> React = <span class="hljs-built_in">require</span>(<span class="hljs-string">'React'</span>);
<span class="hljs-keyword">const</span> {graphql, useLazyLoadQuery} = <span class="hljs-built_in">require</span>(<span class="hljs-string">'react-relay/hooks'</span>);
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-keyword">const</span> data = useLazyLoadQuery<AppQuery>(
graphql<span class="hljs-string">`
query AppQuery($id: ID!) {
user(id: $id) {
name
}
}
`</span>,
{<span class="hljs-attr">id</span>: <span class="hljs-number">4</span>},
{<span class="hljs-attr">fetchPolicy</span>: <span class="hljs-string">'store-or-network'</span>},
);
<span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag"><<span class="hljs-name">h1</span>></span>{data.user?.name}<span class="hljs-tag"></<span class="hljs-name">h1</span>></span></span>;
}
</code></pre>
<h4><a class="anchor" aria-hidden="true" id="arguments-2"></a><a href="#arguments-2" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Arguments</h4>
<ul>
<li><code>query</code>: GraphQL query specified using a <code>graphql</code> template literal.</li>
<li><code>variables</code>: Object containing the variable values to fetch the query. These variables need to match GraphQL variables declared inside the query.</li>
<li><code>options</code>: <em><em>[Optional]</em></em> options object
<ul>
<li><code>fetchPolicy</code>: Determines if cached data should be used, and when to send a network request based on the cached data that is currently available in the Relay store (for more details, see our <a href="a-guided-tour-of-relay#fetch-policies">Fetch Policies</a> and <a href="a-guided-tour-of-relay#garbage-collection-in-relay">Garbage Collection</a> guides):
<ul>
<li><strong>"store-or-network"</strong>: <em><em>(default)</em></em> <strong><em>will</em></strong> reuse locally cached data and will <strong><em>only</em></strong> send a network request if any data for the query is missing. If the query is fully cached, a network request will <strong><em>not</em></strong> be made.</li>
<li><strong>"store-and-network"</strong>: <strong><em>will</em></strong> reuse locally cached data and will <strong><em>always</em></strong> send a network request, regardless of whether any data was missing from the local cache or not.</li>
<li><strong>"network-only"</strong>: <strong><em>will not</em></strong> reuse locally cached data, and will <strong><em>always</em></strong> send a network request to fetch the query, ignoring any data that might be locally cached in Relay.</li>
<li><strong>"store-only"</strong>: <strong><em>will only</em></strong> reuse locally cached data, and will <strong><em>never</em></strong> send a network request to fetch the query. In this case, the responsibility of fetching the query falls to the caller, but this policy could also be used to read and operate and data that is entirely <a href="a-guided-tour-of-relay#local-data-updates">local</a>.</li>
</ul></li>
<li><code>fetchKey</code>: A <code>fetchKey</code> can be passed to force a refetch of the current query and variables when the component re-renders, even if the variables didn't change, or even if the component isn't remounted (similarly to how passing a different <code>key</code> to a React component will cause it to remount). If the fetchKey is different from the one used in the previous render, the current query and variables will be refetched.</li>
<li><code>networkCacheConfig</code>: <em><em>[Optional]</em></em> Object containing cache config options for the <strong><em>network layer.</em></strong> Note the the network layer may contain an <em>additional</em> query response cache which will reuse network responses for identical queries. If you want to bypass this cache completely, pass <code>{force: true}</code> as the value for this option.</li>
</ul></li>
</ul>
<h4><a class="anchor" aria-hidden="true" id="flow-type-parameters-2"></a><a href="#flow-type-parameters-2" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Flow Type Parameters</h4>
<ul>
<li><code>TQuery</code>: Type parameter that should correspond to the Flow type for the specified query. This type is available to import from the the auto-generated file: <code><query_name>.graphql.js</code>.</li>
</ul>
<h4><a class="anchor" aria-hidden="true" id="return-value-2"></a><a href="#return-value-2" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Return Value</h4>
<ul>
<li><code>data</code>: Object that contains data which has been read out from the Relay store; the object matches the shape of specified query.
<ul>
<li>The Flow type for data will also match this shape, and contain types derived from the GraphQL Schema. For example, the type of <code>data</code> above is: <code>{| user: ?{| name: ?string |} |}</code>.</li>
</ul></li>
</ul>
<h4><a class="anchor" aria-hidden="true" id="behavior-2"></a><a href="#behavior-2" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Behavior</h4>
<ul>
<li>It is expected for <code>useLazyLoadQuery</code> to have been rendered under a <a href="#relayenvironmentprovider"><code>RelayEnvironmentProvider</code></a>, in order to access the correct Relay environment, otherwise an error will be thrown.</li>
<li>Calling <code>useLazyLoadQuery</code> will fetch and render the data for this query, and it may <a href="a-guided-tour-of-relay#loading-states-with-suspense"><em><em>suspend</em></em></a> while the network request is in flight, depending on the specified <code>fetchPolicy</code>, and whether cached data is available, or if it needs to send and wait for a network request. If <code>useLazyLoadQuery</code> causes the component to suspend, you'll need to make sure that there's a <code>Suspense</code> ancestor wrapping this component in order to show the appropriate loading state.
<ul>
<li>For more details on Suspense, see our <a href="a-guided-tour-of-relay#loading-states-with-suspense">Loading States with Suspense</a> guide.</li>
</ul></li>
<li>The component is automatically subscribed to updates to the query data: if the data for this query is updated anywhere in the app, the component will automatically re-render with the latest updated data.</li>
<li>After a component using <code>useLazyLoadQuery</code> has committed, re-rendering/updating the component <strong>will not</strong> cause the query to be fetched again.
<ul>
<li>If the component is re-rendered with <strong><em>different query variables,</em></strong> that will cause the query to be fetched again with the new variables, and potentially re-render with different data.</li>
<li>If the component <strong><em>unmounts and remounts</em></strong>, that will cause the current query and variables to be refetched (depending on the <code>fetchPolicy</code>).</li>
</ul></li>
</ul>
<h4><a class="anchor" aria-hidden="true" id="differences-with-queryrenderer"></a><a href="#differences-with-queryrenderer" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Differences with <code>QueryRenderer</code></h4>
<ul>
<li><code>useLazyLoadQuery</code> no longer takes a Relay environment as a parameter, and thus no longer sets the environment in React Context, like <code>QueryRenderer</code> did. Instead, <code>useLazyLoadQuery</code> should be used as a descendant of a <a href="#relayenvironmentprovider"><strong><code>RelayEnvironmentProvider</code></strong></a>, which now sets the Relay environment in Context. Usually, you should render a single <code>RelayEnvironmentProvider</code> at the very root of the application, to set a single Relay environment for the whole application.</li>
<li><code>useLazyLoadQuery</code> will use <a href="a-guided-tour-of-relay#loading-states-with-suspense">Suspense</a> to allow developers to render loading states using Suspense boundaries, and will throw errors if network errors occur, which can be caught and rendered with Error Boundaries. This as opposed to providing error objects or null props to the <code>QueryRenderer</code> render function to indicate errors or loading states.</li>
<li><code>useLazyLoadQuery</code> fully supports fetch policies in order to reuse data that is cached in the Relay store instead of solely relying on the network response cache.</li>
<li><code>useLazyLoadQuery</code> has better type safety guarantees for the data it returns, which was not possible with QueryRenderer since we couldn't parametrize the type of the data with a renderer api.</li>
</ul>
<h3><a class="anchor" aria-hidden="true" id="usefragment"></a><a href="#usefragment" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><code>useFragment</code></h3>
<pre><code class="hljs css language-javascript"><span class="hljs-keyword">import</span> type {UserComponent_user$key} <span class="hljs-keyword">from</span> <span class="hljs-string">'UserComponent_user.graphql'</span>;
<span class="hljs-keyword">const</span> React = <span class="hljs-built_in">require</span>(<span class="hljs-string">'React'</span>);
<span class="hljs-keyword">const</span> {graphql, useFragment} = <span class="hljs-built_in">require</span>(<span class="hljs-string">'react-relay/hooks'</span>);
type Props = {|
user: UserComponent_user$key,
|};
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">UserComponent</span>(<span class="hljs-params">props: Props</span>) </span>{
<span class="hljs-keyword">const</span> data = useFragment(
graphql<span class="hljs-string">`
fragment UserComponent_user on User {
name
profile_picture(scale: 2) {
uri
}
}
`</span>,
props.user,
);
<span class="hljs-keyword">return</span> (
<span class="xml"><span class="hljs-tag"><></span>
<span class="hljs-tag"><<span class="hljs-name">h1</span>></span>{data.name}<span class="hljs-tag"></<span class="hljs-name">h1</span>></span>
<span class="hljs-tag"><<span class="hljs-name">div</span>></span>
<span class="hljs-tag"><<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{data.profile_picture?.uri}</span> /></span>
<span class="hljs-tag"></<span class="hljs-name">div</span>></span>
<span class="hljs-tag"></></span></span>
);
}
</code></pre>
<h4><a class="anchor" aria-hidden="true" id="arguments-3"></a><a href="#arguments-3" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Arguments</h4>
<ul>
<li><code>fragment</code>: GraphQL fragment specified using a <code>graphql</code> template literal.</li>
<li><code>fragmentReference</code>: The <strong><em>fragment reference</em></strong> is an opaque Relay object that Relay uses to read the data for the fragment from the store; more specifically, it contains information about which particular object instance the data should be read from.
<ul>
<li>The type of the fragment reference can be imported from the generated Flow types, from the file <code><fragment_name>.graphql.js</code>, and can be used to declare the type of your <code>Props</code>. The name of the fragment reference type will be: <code><fragment_name>$key</code>. We use our <a href="https://github.com/relayjs/eslint-plugin-relay">lint rule</a> to enforce that the type of the fragment reference prop is correctly declared.</li>
</ul></li>
</ul>
<h4><a class="anchor" aria-hidden="true" id="return-value-3"></a><a href="#return-value-3" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Return Value</h4>
<ul>
<li><code>data</code>: Object that contains data which has been read out from the Relay store; the object matches the shape of specified fragment.
<ul>
<li>The Flow type for data will also match this shape, and contain types derived from the GraphQL Schema. For example, the type of <code>data</code> above is: <code>{| name: ?string, profile_picture: ?{| uri: ?string |} |}</code>.</li>
</ul></li>
</ul>
<h4><a class="anchor" aria-hidden="true" id="behavior-3"></a><a href="#behavior-3" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Behavior</h4>
<ul>
<li>The component is automatically subscribed to updates to the fragment data: if the data for this particular <code>User</code> is updated anywhere in the app (e.g. via fetching new data, or mutating existing data), the component will automatically re-render with the latest updated data.</li>
<li>The component will suspend if any data for that specific fragment is missing, and the data is currently being fetched by a parent query.
<ul>
<li>For more details on Suspense, see our <a href="a-guided-tour-of-relay#loading-states-with-suspense">Loading States with Suspense</a> guide.</li>
</ul></li>
</ul>
<h3><a class="anchor" aria-hidden="true" id="userefetchablefragment"></a><a href="#userefetchablefragment" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><code>useRefetchableFragment</code></h3>
<p>You can use <code>useRefetchableFragment</code> when you want to fetch and re-render a fragment with different data:</p>
<pre><code class="hljs css language-javascript"><span class="hljs-keyword">import</span> type {CommentBodyRefetchQuery} <span class="hljs-keyword">from</span> <span class="hljs-string">'CommentBodyRefetchQuery.graphql'</span>;
<span class="hljs-keyword">import</span> type {CommentBody_comment$key} <span class="hljs-keyword">from</span> <span class="hljs-string">'CommentBody_comment.graphql'</span>;
<span class="hljs-keyword">const</span> React = <span class="hljs-built_in">require</span>(<span class="hljs-string">'React'</span>);
<span class="hljs-keyword">const</span> {useTransition} = <span class="hljs-built_in">require</span>(<span class="hljs-string">'React'</span>);
<span class="hljs-comment">// RN or WWW:</span>
<span class="hljs-keyword">const</span> {graphql, useRefetchableFragment} = <span class="hljs-built_in">require</span>(<span class="hljs-string">'react-relay/hooks'</span>);
type Props = {|
comment: CommentBody_comment$key,
|};
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">CommentBody</span>(<span class="hljs-params">props: Props</span>) </span>{
<span class="hljs-keyword">const</span> [startTransition] = useTransition();
<span class="hljs-keyword">const</span> [data, refetch] = useRefetchableFragment<CommentBodyRefetchQuery, _>(
graphql<span class="hljs-string">`
fragment CommentBody_comment on Comment
@refetchable(queryName: "CommentBodyRefetchQuery") {
body(lang: $lang) {
text
}
}
`</span>,
props.comment,
);
<span class="hljs-keyword">return</span> (
<span class="xml"><span class="hljs-tag"><></span>
<span class="hljs-tag"><<span class="hljs-name">p</span>></span>{data.body?.text}<span class="hljs-tag"></<span class="hljs-name">p</span>></span>
<span class="hljs-tag"><<span class="hljs-name">Button</span>
<span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =></span> {
startTransition(() => {
refetch({lang: 'SPANISH'}, {fetchPolicy: 'store-or-network'})}
});
}>
Translate Comment
<span class="hljs-tag"></<span class="hljs-name">Button</span>></span>
<span class="hljs-tag"></></span></span>
);
}
<span class="hljs-built_in">module</span>.exports = CommentBody;
</code></pre>
<h4><a class="anchor" aria-hidden="true" id="arguments-4"></a><a href="#arguments-4" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Arguments</h4>
<ul>
<li><code>fragment</code>: GraphQL fragment specified using a <code>graphql</code> template literal. This fragment must have a <strong><code>@refetchable</code></strong> directive, otherwise using it will throw an error. The <code>@refetchable</code> directive can only be added to fragments that are “refetchable”, that is, on fragments that are declared on <code>Viewer</code> or <code>Query</code> types, or on a type that implements <code>Node</code> (i.e. a type that has an <code>id</code>).
<ul>
<li>Note that you <strong><em>do not</em></strong> need to manually specify a refetch query yourself. The <code>@refetchable</code> directive will autogenerate a query with the specified <code>queryName</code>. This will also generate Flow types for the query, available to import from the generated file: <code><queryName>.graphql.js</code>.</li>
</ul></li>
<li><code>fragmentReference</code>: The <strong><em>fragment reference</em></strong> is an opaque Relay object that Relay uses to read the data for the fragment from the store; more specifically, it contains information about which particular object instance the data should be read from.
<ul>
<li>The type of the fragment reference can be imported from the generated Flow types, from the file <code><fragment_name>.graphql.js</code>, and can be used to declare the type of your <code>Props</code>. The name of the fragment reference type will be: <code><fragment_name>$key</code>. We use our <a href="https://github.com/relayjs/eslint-plugin-relay">lint rule</a> to enforce that the type of the fragment reference prop is correctly declared.</li>
</ul></li>
</ul>
<h4><a class="anchor" aria-hidden="true" id="flow-type-parameters-3"></a><a href="#flow-type-parameters-3" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Flow Type Parameters</h4>
<ul>
<li><code>TQuery</code>: Type parameter that should corresponds the Flow type for the <code>@refetchable</code> query. This type is available to import from the the auto-generated file: <code><queryName>.graphql.js</code>.</li>
<li><code>TFragmentRef</code>: Type parameter corresponds to the type of the fragment reference argument (i.e. <code><fragment_name>$key</code>). This type usually does not need to be explicitly specified, and can be passed as <code>_</code> to let Flow infer the concrete type.</li>
</ul>
<h4><a class="anchor" aria-hidden="true" id="return-value-4"></a><a href="#return-value-4" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Return Value</h4>
<p>Tuple containing the following values</p>
<ul>
<li>[0] <code>data</code>: Object that contains data which has been read out from the Relay store; the object matches the shape of specified fragment.
<ul>
<li>The Flow type for data will also match this shape, and contain types derived from the GraphQL Schema.</li>
</ul></li>
<li>[1] <code>refetch</code>: Function used to refetch the fragment with a potentially new set of variables.
<ul>
<li>Arguments:
<ul>
<li><code>variables</code>: Object containing the new set of variable values to be used to fetch the <code>@refetchable</code> query.
<ul>
<li>These variables need to match GraphQL variables referenced inside the fragment.</li>
<li>However, only the variables that are intended to change for the refetch request need to be specified; any variables referenced by the fragment that are omitted from this input will fall back to using the value specified in the original parent query. So for example, to refetch the fragment with the exact same variables as it was originally fetched, you can call <code>refetch({})</code>.</li>
<li>Similarly, passing an <code>id</code> value for the <code>$id</code> variable is <em><em>optional</em></em>, unless the fragment wants to be refetched with a different <code>id</code>. When refetching a <code>@refetchable</code> fragment, Relay will already know the id of the rendered object.</li>
</ul></li>
<li><code>options</code>: <em><em>[Optional]</em></em> options object
<ul>
<li><code>fetchPolicy</code>: Determines if cached data should be used, and when to send a network request based on cached data that is available. See the <a href="#uselazyloadquery"><code>useLazyLoadQuery</code></a> section for full specification.</li>
<li><code>onComplete</code>: Function that will be called whenever the refetch request has completed, including any incremental data payloads.</li>
</ul></li>
</ul></li>
<li>Return value:
<ul>
<li><code>disposable</code>: Object containing a <code>dispose</code> function. Calling <code>disposable.dispose()</code> will cancel the refetch request.</li>
</ul></li>
<li>Behavior:
<ul>
<li>Calling <code>refetch</code> with a new set of variables will fetch the fragment again <strong><em>with the newly provided variables</em></strong>. Note that the variables you need to provide are only the ones referenced inside the fragment. In this example, it means fetching the translated body of the currently rendered Comment, by passing a new value to the <code>lang</code> variable.</li>
<li>Calling <code>refetch</code> will re-render your component and may cause it to <em><em><a href="a-guided-tour-of-relay#loading-states-with-suspense">suspend</a></em></em>, depending on the specified <code>fetchPolicy</code> and whether cached data is available or if it needs to send and wait for a network request. If refetch causes the component to suspend, you'll need to make sure that there's a <code>Suspense</code> boundary wrapping this component from above, and/or that you are using <a href="https://reactjs.org/docs/concurrent-mode-patterns.html#transitions"><code>useTransition</code></a> with a Suspense Config (<a href="a-guided-tour-of-relay#transitions-and-updates-that-suspend">Transitions and Updates that Suspend</a>) in order to show the appropriate pending or loading state.
<ul>
<li>Note that since <code>refetch</code> may cause the component to suspend, regardless of whether we are rendering a pending state, we should use <code>startTransition</code> from <code>useTransition</code> to schedule that update; any update that may cause a component to suspend should be scheduled using this pattern.</li>
<li>For more details on Suspense, see our <a href="a-guided-tour-of-relay#loading-states-with-suspense">Loading States with Suspense</a> guide.</li>
</ul></li>
</ul></li>
</ul></li>
</ul>
<h4><a class="anchor" aria-hidden="true" id="behavior-4"></a><a href="#behavior-4" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Behavior</h4>
<ul>
<li>The component is automatically subscribed to updates to the fragment data: if the data for this particular <code>User</code> is updated anywhere in the app (e.g. via fetching new data, or mutating existing data), the component will automatically re-render with the latest updated data.</li>
<li>The component will suspend if any data for that specific fragment is missing, and the data is currently being fetched by a parent query.
<ul>
<li>For more details on Suspense, see our <a href="a-guided-tour-of-relay#loading-states-with-suspense">Loading States with Suspense</a> guide.</li>
</ul></li>
</ul>
<h4><a class="anchor" aria-hidden="true" id="differences-with-refetchcontainer"></a><a href="#differences-with-refetchcontainer" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Differences with <code>RefetchContainer</code></h4>
<ul>
<li>A refetch query no longer needs to be specified in this api, since it will be automatically generated by Relay by using a <code>@refetchable</code> fragment.</li>
<li>Refetching no longer has a distinction between <code>refetchVariables</code> and <code>renderVariables</code>, which were previously vaguely defined concepts. Refetching will always correctly refetch and render the fragment with the variables you provide (any variables omitted in the input will fallback to using the original values from the parent query).</li>
<li>Refetching will unequivocally update the component, which was not always true when calling refetch from <code>RefetchContainer</code> (it would depend on what you were querying for in the refetch query and if your fragment was defined on the right object type).</li>
</ul>
<h3><a class="anchor" aria-hidden="true" id="usepaginationfragment"></a><a href="#usepaginationfragment" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><code>usePaginationFragment</code></h3>
<p>You can use <code>usePaginationFragment</code> to render a fragment that uses a <code>@connection</code> and paginate over it:</p>
<pre><code class="hljs css language-javascript"><span class="hljs-keyword">import</span> type {FriendsListPaginationQuery} <span class="hljs-keyword">from</span> <span class="hljs-string">'FriendsListPaginationQuery.graphql'</span>;
<span class="hljs-keyword">import</span> type {FriendsList_user$key} <span class="hljs-keyword">from</span> <span class="hljs-string">'FriendsList_user.graphql'</span>;
<span class="hljs-keyword">const</span> React = <span class="hljs-built_in">require</span>(<span class="hljs-string">'React'</span>);
<span class="hljs-keyword">const</span> {graphql, usePaginationFragment} = <span class="hljs-built_in">require</span>(<span class="hljs-string">'react-relay/hooks'</span>);
type Props = {|
user: FriendsList_user$key,
|};
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">FriendsList</span>(<span class="hljs-params">props: Props</span>) </span>{
<span class="hljs-keyword">const</span> {
data,
loadNext,
loadPrevious,
hasNext,
hasPrevious,
isLoadingNext,
isLoadingPrevious,
refetch, <span class="hljs-comment">// For refetching connection</span>
} = usePaginationFragment<FriendsListPaginationQuery, _>(
graphql<span class="hljs-string">`
fragment FriendsListComponent_user on User
@refetchable(queryName: "FriendsListPaginationQuery") {
name
friends(first: $count, after: $cursor)
@connection(key: "FriendsList_user_friends") {
edges {
node {
name
age
}
}
}
}
`</span>,
props.user,
);
<span class="hljs-keyword">return</span> (
<span class="xml"><span class="hljs-tag"><></span>
<span class="hljs-tag"><<span class="hljs-name">h1</span>></span>Friends of {data.name}:<span class="hljs-tag"></<span class="hljs-name">h1</span>></span>
<span class="hljs-tag"><<span class="hljs-name">List</span> <span class="hljs-attr">items</span>=<span class="hljs-string">{data.friends?.edges.map(edge</span> =></span> edge.node)}>
{node => {
return (
<span class="hljs-tag"><<span class="hljs-name">div</span>></span>
{node.name} - {node.age}
<span class="hljs-tag"></<span class="hljs-name">div</span>></span>
);
}}
<span class="hljs-tag"></<span class="hljs-name">List</span>></span>
<span class="hljs-tag"><<span class="hljs-name">Button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =></span> loadNext(10)}>Load more friends<span class="hljs-tag"></<span class="hljs-name">Button</span>></span>
<span class="hljs-tag"></></span></span>
);
}
<span class="hljs-built_in">module</span>.exports = FriendsList;
</code></pre>
<h4><a class="anchor" aria-hidden="true" id="arguments-5"></a><a href="#arguments-5" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Arguments</h4>
<ul>
<li><code>fragment</code>: GraphQL fragment specified using a <code>graphql</code> template literal.
<ul>
<li>This fragment must have an <strong><code>@connection</code></strong> directive on a connection field, otherwise using it will throw an error.</li>
<li>This fragment must have a <strong><code>@refetchable</code></strong> directive, otherwise using it will throw an error. The <code>@refetchable</code> directive can only be added to fragments that are “refetchable”, that is, on fragments that are declared on <code>Viewer</code> or <code>Query</code> types, or on a type that implements <code>Node</code> (i.e. a type that has an <code>id</code>).
<ul>
<li>Note that you <strong><em>do not</em></strong> need to manually specify a pagination query yourself. The <code>@refetchable</code> directive will autogenerate a query with the specified <code>queryName</code>. This will also generate Flow types for the query, available to import from the generated file: <code><queryName>.graphql.js</code>.</li>
</ul></li>
</ul></li>
<li><code>fragmentReference</code>: The <strong><em>fragment reference</em></strong> is an opaque Relay object that Relay uses to read the data for the fragment from the store; more specifically, it contains information about which particular object instance the data should be read from.
<ul>
<li>The type of the fragment reference can be imported from the generated Flow types, from the file <code><fragment_name>.graphql.js</code>, and can be used to declare the type of your <code>Props</code>. The name of the fragment reference type will be: <code><fragment_name>$key</code>. We use our <a href="https://github.com/relayjs/eslint-plugin-relay">lint rule</a> to enforce that the type of the fragment reference prop is correctly declared.</li>
</ul></li>
</ul>
<h4><a class="anchor" aria-hidden="true" id="flow-type-parameters-4"></a><a href="#flow-type-parameters-4" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Flow Type Parameters</h4>
<ul>
<li><code>TQuery</code>: Type parameter that should corresponds the Flow type for the <code>@refetchable</code> pagination query. This type is available to import from the the auto-generated file: <code><queryName>.graphql.js</code>.</li>
<li><code>TFragmentRef</code>: Type parameter corresponds to the type of the fragment reference argument (i.e. <code><fragment_name>$key</code>). This type usually does not need to be explicitly specified, and can be passed as <code>_</code> to let Flow infer the concrete type.</li>
</ul>
<h4><a class="anchor" aria-hidden="true" id="return-value-5"></a><a href="#return-value-5" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Return Value</h4>
<p>Object containing the following properties:</p>
<ul>
<li><code>data</code>: Object that contains data which has been read out from the Relay store; the object matches the shape of specified fragment.
<ul>
<li>The Flow type for data will also match this shape, and contain types derived from the GraphQL Schema.</li>
</ul></li>
<li><code>isLoadingNext</code>: Boolean value which indicates if a pagination request for the <em>next</em> items in the connection is currently in flight, including any incremental data payloads.</li>
<li><code>isLoadingPrevious</code>: Boolean value which indicates if a pagination request for the <em>previous</em> items in the connection is currently in flight, including any incremental data payloads.</li>
<li><code>hasNext</code>: Boolean value which indicates if the end of the connection has been reached in the “forward” direction. It will be true if there are more items to query for available in that direction, or false otherwise.</li>
<li><code>hasPrevious</code>: Boolean value which indicates if the end of the connection has been reached in the “backward” direction. It will be true if there are more items to query for available in that direction, or false otherwise.</li>
<li><code>loadNext</code>: Function used to fetch more items in the connection in the “forward” direction.
<ul>
<li>Arguments:
<ul>
<li><code>count</code>: Number that indicates how many items to query for in the pagination request.</li>
<li><code>options</code>: <em><em>[Optional]</em></em> options object
<ul>
<li><code>onComplete</code>: Function that will be called whenever the refetch request has completed, including any incremental data payloads.</li>
</ul></li>
</ul></li>
<li>Return Value:
<ul>
<li><code>disposable</code>: Object containing a <code>dispose</code> function. Calling <code>disposable.dispose()</code> will cancel the pagination request.</li>
</ul></li>
<li>Behavior:
<ul>
<li>Calling <code>loadNext</code> <strong><em>will not</em></strong> cause the component to suspend. Instead, the <code>isLoadingNext</code> value will be set to true while the request is in flight, and the new items from the pagination request will be added to the connection, causing the component to re-render.</li>
<li>Pagination requests initiated from calling <code>loadNext</code> will <em>always</em> use the same variables that were originally used to fetch the connection, <em>except</em> pagination variables (which need to change in order to perform pagination); changing variables other than the pagination variables during pagination doesn't make sense, since that'd mean we'd be querying for a different connection.</li>
</ul></li>
</ul></li>
<li><code>loadPrevious</code>: Function used to fetch more items in the connection in the “backward” direction.
<ul>
<li>Arguments:
<ul>
<li><code>count</code>: Number that indicates how many items to query for in the pagination request.</li>
<li><code>options</code>: <em><em>[Optional]</em></em> options object
<ul>
<li><code>onComplete</code>: Function that will be called whenever the refetch request has completed, including any incremental data payloads.</li>
</ul></li>
</ul></li>
<li>Return Value:
<ul>
<li><code>disposable</code>: Object containing a <code>dispose</code> function. Calling <code>disposable.dispose()</code> will cancel the pagination request.</li>
</ul></li>
<li>Behavior:
<ul>
<li>Calling <code>loadPrevious</code> <strong><em>will not</em></strong> cause the component to suspend. Instead, the <code>isLoadingPrevious</code> value will be set to true while the request is in flight, and the new items from the pagination request will be added to the connection, causing the component to re-render.</li>
<li>Pagination requests initiated from calling <code>loadPrevious</code> will <em>always</em> use the same variables that were originally used to fetch the connection, <em>except</em> pagination variables (which need to change in order to perform pagination); changing variables other than the pagination variables during pagination doesn't make sense, since that'd mean we'd be querying for a different connection.</li>
</ul></li>
</ul></li>
<li><code>refetch</code>: Function used to refetch the connection fragment with a potentially new set of variables.
<ul>
<li>Arguments:
<ul>
<li><code>variables</code>: Object containing the new set of variable values to be used to fetch the <code>@refetchable</code> query.
<ul>
<li>These variables need to match GraphQL variables referenced inside the fragment.</li>
<li>However, only the variables that are intended to change for the refetch request need to be specified; any variables referenced by the fragment that are omitted from this input will fall back to using the value specified in the original parent query. So for example, to refetch the fragment with the exact same variables as it was originally fetched, you can call <code>refetch({})</code>.</li>
<li>Similarly, passing an <code>id</code> value for the <code>$id</code> variable is <em><em>optional</em></em>, unless the fragment wants to be refetched with a different <code>id</code>. When refetching a <code>@refetchable</code> fragment, Relay will already know the id of the rendered object.</li>
</ul></li>
<li><code>options</code>: <em><em>[Optional]</em></em> options object
<ul>
<li><code>fetchPolicy</code>: Determines if cached data should be used, and when to send a network request based on cached data that is available. See the <a href="#uselazyloadquery"><code>useLazyLoadQuery</code></a> section for full specification.</li>
<li><code>onComplete</code>: Function that will be called whenever the refetch request has completed, including any incremental data payloads.</li>
</ul></li>
</ul></li>
<li>Return value:
<ul>
<li><code>disposable</code>: Object containing a <code>dispose</code> function. Calling <code>disposable.dispose()</code> will cancel the refetch request.</li>
</ul></li>
<li>Behavior:
<ul>
<li>Calling <code>refetch</code> with a new set of variables will fetch the fragment again <strong><em>with the newly provided variables</em></strong>. Note that the variables you need to provide are only the ones referenced inside the fragment. In this example, it means fetching the translated body of the currently rendered Comment, by passing a new value to the <code>lang</code> variable.</li>
<li>Calling <code>refetch</code> will re-render your component and may cause it to <a href="a-guided-tour-of-relay#loading-states-with-suspense"><em><em>suspend</em></em></a>, depending on the specified <code>fetchPolicy</code> and whether cached data is available or if it needs to send and wait for a network request. If refetch causes the component to suspend, you'll need to make sure that there's a <code>Suspense</code> boundary wrapping this component from above, and/or that you are using <a href="https://reactjs.org/docs/concurrent-mode-patterns.html#transitions"><code>useTransition</code></a> with a Suspense Config (<a href="a-guided-tour-of-relay#transitions-and-updates">Transitions and Updates that Suspend</a>) in order to show the appropriate pending or loading state.
<ul>
<li>Note that since <code>refetch</code> may cause the component to suspend, regardless of whether we are rendering a pending state, we should use <code>startTransition</code> from <code>useTransition</code> to schedule that update; any update that may cause a component to suspend should be scheduled using this pattern.</li>
<li>For more details on Suspense, see our <a href="a-guided-tour-of-relay#loading-states-with-suspense">Loading States with Suspense</a> guide.</li>
</ul></li>
</ul></li>
</ul></li>
</ul>
<h4><a class="anchor" aria-hidden="true" id="behavior-5"></a><a href="#behavior-5" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Behavior</h4>
<ul>
<li>The component is automatically subscribed to updates to the fragment data: if the data for this particular <code>User</code> is updated anywhere in the app (e.g. via fetching new data, or mutating existing data), the component will automatically re-render with the latest updated data.</li>
<li>The component will suspend if any data for that specific fragment is missing, and the data is currently being fetched by a parent query.
<ul>
<li>For more details on Suspense, see our <a href="a-guided-tour-of-relay#loading-states-with-suspense">Loading States with Suspense</a> guide.</li>
</ul></li>
<li>Note that pagination (<code>loadNext</code> or <code>loadPrevious</code>), <strong><em>will not</em></strong> cause the component to suspend.</li>
</ul>
<h4><a class="anchor" aria-hidden="true" id="differences-with-paginationcontainer"></a><a href="#differences-with-paginationcontainer" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Differences with <code>PaginationContainer</code></h4>
<ul>
<li>A pagination query no longer needs to be specified in this api, since it will be automatically generated by Relay by using a <code>@refetchable</code> fragment.</li>
<li>This api supports simultaneous bi-directional pagination out of the box.</li>
<li>This api no longer requires passing a <code>getVariables</code> or <code>getFragmentVariables</code> configuration functions, like the <code>PaginationContainer</code> does.
<ul>
<li>This implies that pagination no longer has a between <code>variables</code> and <code>fragmentVariables</code>, which were previously vaguely defined concepts. Pagination requests will always use the same variables that were originally used to fetch the connection, <em>except</em> pagination variables (which need to change in order to perform pagination); changing variables other than the pagination variables during pagination doesn't make sense, since that'd mean we'd be querying for a different connection.</li>
</ul></li>
<li>This api no longer takes additional configuration like <code>direction</code> or <code>getConnectionFromProps</code> function (like Pagination Container does). These values will be automatically determined by Relay.</li>
<li>Refetching no longer has a distinction between <code>variables</code> and <code>fragmentVariables</code>, which were previously vaguely defined concepts. Refetching will always correctly refetch and render the fragment with the variables you provide (any variables omitted in the input will fallback to using the original values in the parent query).</li>
<li>Refetching will unequivocally update the component, which was not always true when calling <code>refetchConnection</code> from <code>PaginationContainer</code> (it would depend on what you were querying for in the refetch query and if your fragment was defined on the right object type).</li>
</ul>
<h3><a class="anchor" aria-hidden="true" id="useblockingpaginationfragment"></a><a href="#useblockingpaginationfragment" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><code>useBlockingPaginationFragment</code></h3>
<p><strong>NOTE:</strong> <code>useBlockingPaginationFragment</code> is meant to be used only in React Concurrent Mode, since it can't provide full Suspense capabilities outside of Concurrent Mode.</p>
<hr>
<blockquote>
<p>WIP</p>
</blockquote>
<p>In the meantime, see our <strong><a href="a-guided-tour-of-relay#blocking-all-at-once-pagination">Blocking ("all-at-once") Pagination Guide</a></strong>.</p>
<h3><a class="anchor" aria-hidden="true" id="usemutation"></a><a href="#usemutation" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><code>useMutation</code></h3>
<p>You can use <code>useMutation</code> to execute a mutation in a React component.</p>
<pre><code class="hljs css language-javascript"><span class="hljs-keyword">import</span> type {FeedbackLikeMutation} <span class="hljs-keyword">from</span> <span class="hljs-string">'FeedbackLikeMutation.graphql'</span>;
<span class="hljs-keyword">const</span> React = <span class="hljs-built_in">require</span>(<span class="hljs-string">'React'</span>);
<span class="hljs-keyword">const</span> {graphql, useMutation} = <span class="hljs-built_in">require</span>(<span class="hljs-string">'react-relay/hooks'</span>);
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">LikeButton</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-keyword">const</span> [commit, isInFlight] = useMutation<FeedbackLikeMutation>(graphql<span class="hljs-string">`
mutation FeedbackLikeMutation($input: FeedbackLikeData!) {
feedback_like(data: $input) {
feedback {
id
viewer_does_like
like_count
}
}
}
`</span>);
<span class="hljs-keyword">if</span> (isInFlight) {
<span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag"><<span class="hljs-name">Spinner</span> /></span></span>;
}
<span class="hljs-keyword">return</span> (
<span class="xml"><span class="hljs-tag"><<span class="hljs-name">button</span>
<span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =></span> {
commit({
variables: {
input: {
id: '123',
text: 'text',
},
},
onCompleted(data) {
console.log(data);
},
});
}}
/></span>
);
}
</code></pre>
<h4><a class="anchor" aria-hidden="true" id="arguments-6"></a><a href="#arguments-6" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Arguments</h4>
<ul>
<li><code>mutation</code>: GraphQL mutation specified using a <code>graphql</code> template literal.</li>
<li><code>commitMutationFn</code>: An optional function with the same signature as <code>commitMutation</code> to call in its stead.</li>
</ul>
<h4><a class="anchor" aria-hidden="true" id="flow-type-parameters-5"></a><a href="#flow-type-parameters-5" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Flow Type Parameters</h4>
<ul>
<li><code>TMutation</code>: Type parameter that should corresponds the Flow type for the mutation query. This type is available to import from the the auto-generated file: <code><mutationName>.graphql.js</code>.</li>
</ul>
<h4><a class="anchor" aria-hidden="true" id="return-value-6"></a><a href="#return-value-6" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Return Value</h4>
<p>Tuple containing the following values:</p>
<ul>
<li>[0] <code>commit</code>: The function that will execute the mutation
<ul>
<li>The parameter that <code>commit</code> accepts is almost the same as the second parameter to <code>commitMutation</code>.
<ul>
<li><code>variables</code>: Object containing the variables needed for the mutation. For example, if the mutation defines an <code>$input</code> variable, this object should contain an <code>input</code> key, whose shape must match the shape of the data expected by the mutation as defined by the GraphQL schema.</li>
<li><code>onCompleted</code>: Callback function executed when the request is completed and the in-memory Relay store is updated with the <code>updater</code> function. Takes a <code>response</code> object, which is the "raw" server response.</li>
<li><code>onError</code>: Callback function executed if Relay encounters an error while executing the request.</li>
<li><code>optimisticResponse</code>: Object containing the data to optimistically update the local in-memory store, i.e. immediately, before the mutation request has completed. This object must have the same shape as the mutation's response type, as defined by the GraphQL schema. If provided, Relay will use the <code>optimisticResponse</code> data to update the fields on the relevant records in the local data store, <em>before</em> <code>optimisticUpdater</code> is executed. If an error occurs during the mutation request, the optimistic update will be rolled back.</li>
<li><code>optimisticUpdater</code>: Function used to optimistically update the local in-memory store, i.e. immediately, before the mutation request has completed. If an error occurs during the mutation request, the optimistic update will be rolled back. This function takes a <code>store</code>, which is a proxy of the in-memory <a href="https://relay.dev/docs/en/relay-store.html">Relay Store</a>. In this function, the client defines how to update the local data via the store instance. For details on how to use the store, please refer to our <a href="https://relay.dev/docs/en/relay-store.html">Relay Store API Reference</a>. Please note:
<ul>
<li>It is usually preferable to just pass an <code>optimisticResponse</code> option instead of an <code>optimisticUpdater</code>, unless you need to perform updates on the local records that are more complicated than just updating fields (e.g. deleting records or adding items to collections).</li>
<li>If you do decide to use an <code>optimisticUpdater</code>, often times it can be the same function as <code>updater</code>.</li>
</ul></li>
<li><code>updater</code>: Function used to update the local in-memory store based on the real server response from the mutation. If <code>updater</code> is not provided, by default, Relay will know to automatically update the fields on the records referenced in the mutation response; however, you should pass an <code>updater</code> if you need to make more complicated updates than just updating fields (e.g. deleting records or adding items to collections). When the server response comes back, Relay first reverts any changes introduced by <code>optimisticUpdater</code> or <code>optimisticResponse</code> and will then execute updater. This function takes a store, which is a proxy of the in-memory <a href="https://relay.dev/docs/en/relay-store.html">Relay Store</a>. In this function, the client defines how to update the local data based on the server response via the store instance. For details on how to use the store, please refer to our <a href="https://relay.dev/docs/en/relay-store.html">Relay Store API</a>.</li>
<li>Note: there is no environment argument. <code>useMutation</code> will automatically use the current environment provided by <code>RelayEnvironmentProvider</code>.</li>
</ul></li>
<li>Return value:
<ul>
<li>disposable: Object containing a dispose function. Calling disposable.dispose() will revert the optimistic update, and Relay won’t update the store or call any success/error callback, but the network request is not guaranteed to be cancelled. If the dispose is called after the mutation has succeeded, it will not rollback the update in Relay store.</li>
</ul></li>
</ul></li>
<li>[1] <code>areMutationsInFlight</code>: Will be true if any mutation triggered by calling <code>commit</code> is still in flight. If you call <code>commit</code> multiple times, there can be multiple mutations in flight at once.</li>
</ul>
<h3><a class="anchor" aria-hidden="true" id="usesubscription"></a><a href="#usesubscription" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><code>useSubscription</code></h3>
<p>Hook used to subscribe and unsubscribe to a subscription.</p>
<pre><code class="hljs css language-javascript"><span class="hljs-keyword">import</span> {graphql, useSubscription} <span class="hljs-keyword">from</span> <span class="hljs-string">'RelayHooks'</span>;
<span class="hljs-keyword">import</span> {useMemo} <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">const</span> subscription = graphql<span class="hljs-string">`subscription ...`</span>;
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MyFunctionalComponent</span>(<span class="hljs-params">{ id }</span>) </span>{
<span class="hljs-comment">// IMPORTANT: your config should be memoized, or at least not re-computed</span>
<span class="hljs-comment">// every render. Otherwise, useSubscription will re-render too frequently.</span>
<span class="hljs-keyword">const</span> config = useMemo(<span class="hljs-function"><span class="hljs-params">()</span> =></span> { <span class="hljs-attr">variables</span>: { id }, subscription }, [id]);
useSubscription(config);
<span class="hljs-keyword">return</span> (
<span class="xml"><span class="hljs-tag"><<span class="hljs-name">div</span>></span>Move Fast<span class="hljs-tag"></<span class="hljs-name">div</span>></span></span>
);
}
</code></pre>
<p>This is a thin wrapper around the <code>requestSubscription</code> API. Its behavior:</p>
<ul>
<li>Create a subscription when the component is mounted with the given config</li>
<li>Unsubscribe from that subscription when the component is unmounted</li>
</ul>
<p>If you have the need to do something more complicated, such as imperatively requesting a subscription, please use the <code>requestSubscription</code> API directly.</p>
<h4><a class="anchor" aria-hidden="true" id="arguments-7"></a><a href="#arguments-7" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Arguments</h4>
<ul>
<li><code>config</code>: the same config passed to <code>requestSubscription</code></li>
</ul>
<h2><a class="anchor" aria-hidden="true" id="non-react-apis"></a><a href="#non-react-apis" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Non-React APIs</h2>
<h3><a class="anchor" aria-hidden="true" id="loadquery"></a><a href="#loadquery" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><code>loadQuery</code></h3>
<p>This function is designed to be used with the <a href="#usepreloadedquery"><code>usePreloadedQuery()</code></a> hook to implement the "render-as-you-fetch".</p>
<p>Query references returned from <code>loadQuery</code> will leak data into the Relay store if <code>.dispose()</code> is not called on them once they are no longer referenced. <em>As such, prefer calling <a href="#usequeryloader"><code>useQueryLoader</code></a> when possible</em>, which ensures that query references are disposed for you.</p>
<pre><code class="hljs css language-javascript"><span class="hljs-keyword">const</span> React = <span class="hljs-built_in">require</span>(<span class="hljs-string">'React'</span>);
<span class="hljs-keyword">const</span> {loadQuery, useRelayEnvironment} = <span class="hljs-built_in">require</span>(<span class="hljs-string">'react-relay/hooks'</span>);
<span class="hljs-keyword">const</span> query = graphql<span class="hljs-string">`
query AppQuery($id: ID!) {
user(id: $id) {
name
}
}
`</span>;
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MyComponent</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-comment">// Do not call this during render</span>
<span class="hljs-keyword">const</span> onClick = React.useCallback(<span class="hljs-function"><span class="hljs-params">()</span> =></span> {
<span class="hljs-keyword">const</span> queryReference = loadQuery(
RelayFBEnvironment,
query,
{<span class="hljs-attr">id</span>: <span class="hljs-string">'4'</span>},
{<span class="hljs-attr">fetchPolicy</span>: <span class="hljs-string">'store-or-network'</span>},
);
processQuery(queryQeference);
<span class="hljs-comment">// the processQuery function must ensure that `queryReference.dispose()` is called.</span>
});
<span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{onClick}</span>></span>Click me<span class="hljs-tag"></<span class="hljs-name">div</span>></span></span>;
}
</code></pre>
<h4><a class="anchor" aria-hidden="true" id="arguments-8"></a><a href="#arguments-8" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Arguments</h4>
<ul>
<li><code>environment</code>: A Relay Environment instance on which to execute the request. If you're starting this request somewhere within a React component, you probably want to use the environment you obtain from using <a href="#userelayenvironment">useRelayEnvironment</a>.</li>
<li><code>query</code>: GraphQL query to fetch, specified using a graphql template literal.</li>
<li><code>variables</code>: Object containing the variable values to fetch the query. These variables need to match GraphQL variables declared inside the query.</li>
<li><code>options</code>: <em><em>[Optional]</em></em> options object
<ul>
<li><code>fetchPolicy</code>: Determines if cached data should be used, and when to send a network request based on the cached data that is currently available in the Relay store (for more details, see our <a href="a-guided-tour-of-relay#fetch-policies">Fetch Policies</a> and <a href="a-guided-tour-of-relay#garbage-collection-in-relay">Garbage Collection</a> guides):
<ul>
<li><strong>"store-or-network"</strong>: <em><em>(default)</em></em> <strong><em>will</em></strong> reuse locally cached data and will <strong><em>only</em></strong> send a network request if any data for the query is missing. If the query is fully cached, a network request will <strong><em>not</em></strong> be made.</li>
<li><strong>"store-and-network"</strong>: <strong><em>will</em></strong> reuse locally cached data and will <strong><em>always</em></strong> send a network request, regardless of whether any data was missing from the local cache or not.</li>
<li><strong>"network-only"</strong>: <strong><em>will not</em></strong> reuse locally cached data, and will <strong><em>always</em></strong> send a network request to fetch the query, ignoring any data that might be locally cached in Relay.</li>
</ul></li>
<li>networkCacheConfig: <em><em>[Optional]</em></em> Object containing cache config options for the <em>network layer.</em> Note the the network layer may contain an additional query response cache which will reuse network responses for identical queries. If you want to bypass this cache completely, pass <code>{force: true}</code> as the value for this option.</li>
</ul></li>
<li><code>environmentProviderOptions</code>: <em><em>[Optional]</em></em> options object. Will be part of the returned query reference. <strong><em>However, this parameter is likely to be removed in a future release. You should not rely on it.</em></strong></li>
</ul>
<h4><a class="anchor" aria-hidden="true" id="flow-type-parameters-6"></a><a href="#flow-type-parameters-6" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Flow Type Parameters</h4>
<ul>
<li><code>TQuery</code>: Type parameter that should correspond to the Flow type for the specified query. This type is available to import from the the auto-generated file: <code><query_name>.graphql.js</code>.</li>
<li><code>TEnvironmentProviderOptions</code>: The type of the <code>environmentProviderOptions</code> parameter.</li>
</ul>
<h4><a class="anchor" aria-hidden="true" id="return-value-7"></a><a href="#return-value-7" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Return Value</h4>
<p>A query reference with the following properties:</p>
<ul>
<li><code>dispose</code>: a method that will release the query reference from being retained by the store. This can cause the data referenced by the query reference to be garbage collected.</li>
</ul>
<p>The exact format of the return value is unstable and highly likely to change. We strongly recommend not using any other properties of the return value, as such code would be highly likely to break when upgrading to future versions of Relay. Instead, pass the result of <code>loadQuery()</code> to <code>usePreloadedQuery()</code>.</p>
<h4><a class="anchor" aria-hidden="true" id="behavior-6"></a><a href="#behavior-6" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Behavior</h4>
<ul>
<li><code>loadQuery()</code> will fetch data. Once available, the data from the query will be written to the store. This differs from the behavior of <code>preloadQuery_DEPRECATED</code>, which would only write data to the store if the query was passed to <code>usePreloadedQuery</code>.</li>
<li>the query reference returned from loadQuery will be retained by the relay store, preventing it the data from being garbage collected. Once you call <code>.dispose()</code> on the query reference, it can be garbage collected.</li>
<li><code>loadQuery()</code> will throw an error if it is called during React’s render phase.</li>
</ul>
<h3><a class="anchor" aria-hidden="true" id="preloadquery_deprecated"></a><a href="#preloadquery_deprecated" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><code>preloadQuery_DEPRECATED</code></h3>
<p>This function is designed to be used with the <code>usePreloadedQuery()</code> hook to implement the "render-as-you-fetch" pattern in conjunction with <code>usePreloadedQuery</code>. See the <a href="#usepreloadedquery"><code>usePreloadedQuery()</code></a> docs for a more complete example.</p>
<pre><code class="hljs css language-javascript"><span class="hljs-keyword">const</span> {graphql, preloadQuery_DEPRECATED} = <span class="hljs-built_in">require</span>(<span class="hljs-string">'react-relay/hooks'</span>);
<span class="hljs-keyword">const</span> AppEnvironment = <span class="hljs-built_in">require</span>(<span class="hljs-string">'./AppEnvironment'</span>); <span class="hljs-comment">// user-defined</span>
<span class="hljs-keyword">const</span> query = graphql<span class="hljs-string">`
query AppQuery($id: ID!) {
user(id: $id) {
name
}
}
`</span>;
<span class="hljs-keyword">const</span> result = preloadQuery_DEPRECATED(
AppEnvironment,
query,
{<span class="hljs-attr">id</span>: <span class="hljs-string">'4'</span>},
{<span class="hljs-attr">fetchPolicy</span>: <span class="hljs-string">'store-or-network'</span>},
);
<span class="hljs-comment">// later: pass result to usePreloadedQuery()</span>
</code></pre>
<h4><a class="anchor" aria-hidden="true" id="arguments-9"></a><a href="#arguments-9" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Arguments</h4>
<ul>
<li><code>environment</code>: A Relay Environment instance to execute the request on. If you're starting this request somewhere within a React component, you probably want to use the environment you obtain from using <a href="#userelayenvironment"><code>useRelayEnvironment</code></a>.</li>
<li><code>query</code>: GraphQL query to fetch, specified using a <code>graphql</code> template literal.</li>
<li><code>variables</code>: Object containing the variable values to fetch the query. These variables need to match GraphQL variables declared inside the query.</li>
<li><code>options</code>: <em><em>[Optional]</em></em> options object
<ul>
<li><code>fetchPolicy</code>: Determines if cached data should be used, and when to send a network request based on the cached data that is currently available in the Relay store (for more details, see our <a href="a-guided-tour-of-relay#fetch-policies">Fetch Policies</a> and <a href="a-guided-tour-of-relay#garbage-collection-in-relay">Garbage Collection</a> guides):
<ul>
<li><strong>"store-or-network"</strong>: <em><em>(default)</em></em> <strong><em>will</em></strong> reuse locally cached data and will <strong><em>only</em></strong> send a network request if any data for the query is missing. If the query is fully cached, a network request will <strong><em>not</em></strong> be made.</li>
<li><strong>"store-and-network"</strong>: <strong><em>will</em></strong> reuse locally cached data and will <strong><em>always</em></strong> send a network request, regardless of whether any data was missing from the local cache or not.</li>
<li><strong>"network-only"</strong>: <strong><em>will not</em></strong> reuse locally cached data, and will <strong><em>always</em></strong> send a network request to fetch the query, ignoring any data that might be locally cached in Relay.</li>
</ul></li>
<li><code>fetchKey</code>: A <code>fetchKey</code> can be passed to force a refetch of the query and variables. <code>preloadQuery_DEPRECATED()</code> will cache requests while they are in-flight and for a brief duration afterwards, but using a distinct <code>fetchKey</code> can ensure that data is refetched (generally when used in conjunction with fetchPolicy=network-only).</li>
<li><code>networkCacheConfig</code>: <em><em>[Optional]</em></em> Object containing cache config options for the <strong><em>network layer.</em></strong> Note the the network layer may contain an <em>additional</em> query response cache which will reuse network responses for identical queries. If you want to bypass this cache completely, pass <code>{force: true}</code> as the value for this option.</li>
</ul></li>
</ul>
<h4><a class="anchor" aria-hidden="true" id="flow-type-parameters-7"></a><a href="#flow-type-parameters-7" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Flow Type Parameters</h4>
<ul>
<li><code>TQuery</code>: Type parameter that should correspond to the Flow type for the specified query. This type is available to import from the the auto-generated file: <code><query_name>.graphql.js</code>.</li>
</ul>
<h4><a class="anchor" aria-hidden="true" id="return-value-8"></a><a href="#return-value-8" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Return Value</h4>
<p>The exact format of the return value is <em>unstable and highly likely to change</em>. We strongly recommend not inspecting the contents in your code, as such code would be highly likely to break when upgrading to future versions of Relay. Instead, pass the result of <code>preloadQuery_DEPRECATED()</code> to <code>usePreloadedQuery()</code>.</p>
<h3><a class="anchor" aria-hidden="true" id="fetchquery"></a><a href="#fetchquery" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><code>fetchQuery</code></h3>
<p>If you want to fetch a query outside of React, you can use the <strong><code>fetchQuery</code></strong> function from <code>react-relay/hooks</code>:</p>
<pre><code class="hljs css language-javascript"><span class="hljs-keyword">import</span> type {AppQuery} <span class="hljs-keyword">from</span> <span class="hljs-string">'AppQuery.graphql'</span>;
<span class="hljs-keyword">const</span> {fetchQuery} = <span class="hljs-built_in">require</span>(<span class="hljs-string">'react-relay/hooks'</span>);
fetchQuery<AppQuery>(
environment,
graphql<span class="hljs-string">`
query AppQuery($id: ID!) {
user(id: $id) {
name
}
}
`</span>,
{<span class="hljs-attr">id</span>: <span class="hljs-number">4</span>},
)
.subscribe({
<span class="hljs-attr">start</span>: <span class="hljs-function"><span class="hljs-params">()</span> =></span> {...},
<span class="hljs-attr">complete</span>: <span class="hljs-function"><span class="hljs-params">()</span> =></span> {...},
<span class="hljs-attr">error</span>: <span class="hljs-function">(<span class="hljs-params">error</span>) =></span> {...},
<span class="hljs-attr">next</span>: <span class="hljs-function">(<span class="hljs-params">data</span>) =></span> {...}
});
</code></pre>
<h4><a class="anchor" aria-hidden="true" id="arguments-10"></a><a href="#arguments-10" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Arguments</h4>
<ul>
<li><code>environment</code>: A Relay Environment instance to execute the request on. If you're starting this request somewhere within a React component, you probably want to use the environment you obtain from using <a href="#userelayenvironment"><code>useRelayEnvironment</code></a>.</li>
<li><code>query</code>: GraphQL query to fetch, specified using a <code>graphql</code> template literal.</li>
<li><code>variables</code>: Object containing the variable values to fetch the query. These variables need to match GraphQL variables declared inside the query.</li>
<li><code>options</code>: <em><em>[Optional]</em></em> options object
<ul>
<li><code>networkCacheConfig</code>: <em>_[Optional] _</em>Object containing cache config options
<ul>
<li><code>force</code>: Boolean value. If true, will bypass the network response cache.</li>
</ul></li>
</ul></li>
</ul>
<h4><a class="anchor" aria-hidden="true" id="flow-type-parameters-8"></a><a href="#flow-type-parameters-8" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Flow Type Parameters</h4>
<ul>
<li><code>TQuery</code>: Type parameter that should correspond to the Flow type for the specified query. This type is available to import from the the auto-generated file: <code><query_name>.graphql.js</code>.</li>
</ul>
<h4><a class="anchor" aria-hidden="true" id="return-value-9"></a><a href="#return-value-9" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Return Value</h4>
<ul>
<li><code>observable</code>: Returns an observable instance. To start the request, <code>subscribe</code> or <code>toPromise</code> must be called on the observable. Exposes the following methods:
<ul>
<li><code>susbcribe</code>: Function that can be called to subscribe to the observable for the network request
<ul>
<li>Arguments:
<ul>
<li><code>observer</code>: Object that specifies observer functions for different events occurring on the network request observable. May specify the following event handlers as keys in the observer object:
<ul>
<li><code>start</code>: Function that will be called when the network requests starts. It will receive a single <code>subscription</code> argument, which represents the subscription on the network observable.</li>
<li><code>complete</code>: Function that will be called when the network request is complete</li>
<li><code>next</code>: Function that will be called every time a payload is received from the network. It will receive a single <code>data</code> argument, which represents a snapshot of the query data read from the Relay store at the moment a payload was received from the server. The <code>next</code> function may be called multiple times when using Relay's <a href="#">Incremental Data Delivery</a> capabilities to receive multiple payloads from the server.</li>
<li><code>error</code>: Function that will be called if an error occurs during the network request. It will receive a single <code>error</code> argument, containing the error that occurred.</li>
<li><code>unsubscribe</code>: Function that will be called whenever the subscription is unsubscribed. It will receive a single <code>subscription</code> argument, which represents the subscription on the network observable.</li>
</ul></li>
</ul></li>
<li>Return Value:
<ul>
<li><code>subscription</code>: Object representing a subscription to the observable. Calling <code>subscription.unsubscribe()</code> will cancel the network request.</li>
</ul></li>
</ul></li>
<li><code>toPromise</code>:
<ul>
<li>Return Value:
<ul>
<li><code>promise</code>: Returns a promise that will resolve when the network request fully completes. Cannot be canceled.</li>
</ul></li>
</ul></li>
</ul></li>
</ul>
<h4><a class="anchor" aria-hidden="true" id="behavior-7"></a><a href="#behavior-7" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Behavior</h4>
<ul>
<li><code>fetchQuery</code> will automatically save the fetched data to the in-memory Relay store, and notify any components subscribed to the relevant data.</li>
<li><code>fetchQuery</code> will <strong><em>NOT</em></strong> retain the data for the query, meaning that it is not guaranteed that the data will remain saved in the Relay store at any point after the request completes. If you wish to make sure that the data is retained outside of the scope of the request, you need to call <code>environment.retain()</code> directly on the query to ensure it doesn't get deleted. See our section on <a href="a-guided-tour-of-relay/#controlling-relays-garbage-collection-policy">Controlling Relay's GC Policy</a> for more details.</li>
</ul>
</span></div></article></div><div class="docLastUpdate"><em>Last updated on 7/10/2020 by Robert Balicki</em></div><div class="docs-prevnext"></div></div></div><nav class="onPageNav"><ul class="toc-headings"><li><a href="#relay-hooks">Relay Hooks</a><ul class="toc-headings"><li><a href="#benefits">Benefits</a></li><li><a href="#caveats">Caveats</a></li><li><a href="#relayenvironmentprovider"><code>RelayEnvironmentProvider</code></a></li><li><a href="#userelayenvironment"><code>useRelayEnvironment</code></a></li><li><a href="#usequeryloader"><code>useQueryLoader</code></a></li><li><a href="#usepreloadedquery"><code>usePreloadedQuery</code></a></li><li><a href="#uselazyloadquery"><code>useLazyLoadQuery</code></a></li><li><a href="#usefragment"><code>useFragment</code></a></li><li><a href="#userefetchablefragment"><code>useRefetchableFragment</code></a></li><li><a href="#usepaginationfragment"><code>usePaginationFragment</code></a></li><li><a href="#useblockingpaginationfragment"><code>useBlockingPaginationFragment</code></a></li><li><a href="#usemutation"><code>useMutation</code></a></li><li><a href="#usesubscription"><code>useSubscription</code></a></li></ul></li><li><a href="#non-react-apis">Non-React APIs</a><ul class="toc-headings"><li><a href="#loadquery"><code>loadQuery</code></a></li><li><a href="#preloadquery_deprecated"><code>preloadQuery_DEPRECATED</code></a></li><li><a href="#fetchquery"><code>fetchQuery</code></a></li></ul></li></ul></nav></div><footer class="nav-footer" id="footer"><section class="sitemap"><a href="/" class="nav-home"><img src="/img/relay.svg" alt="Relay" width="66" height="58"/></a><div><h5>Docs</h5><a href="/docs/en/introduction-to-relay.html">Introduction</a></div><div><h5>Community</h5><a href="/en/users.html">User Showcase</a></div><div><h5>More</h5><a href="https://github.com/facebook/relay">GitHub</a><a class="github-button" href="https://github.com/facebook/relay" data-icon="octicon-star" data-count-href="/facebook/relay/stargazers" data-count-api="/repos/facebook/relay#stargazers_count" data-count-aria-label="# stargazers on GitHub" aria-label="Star this project on GitHub">Star</a></div></section><a href="https://code.facebook.com/projects/" target="_blank" class="fbOpenSource"><img src="/img/oss_logo.png" alt="Facebook Open Source" width="170" height="45"/></a><section class="copyright">Copyright © 2020 Facebook Inc.</section></footer></div><script type="text/javascript" src="https://cdn.jsdelivr.net/docsearch.js/1/docsearch.min.js"></script><script>
document.addEventListener('keyup', function(e) {
if (e.target !== document.body) {
return;
}
// keyCode for '/' (slash)
if (e.keyCode === 191) {
const search = document.getElementById('search_input_react');
search && search.focus();
}
});
</script><script>
var search = docsearch({
apiKey: '3d7d5825d50ea36bca0e6ad06c926f06',
indexName: 'relay',
inputSelector: '#search_input_react',
algoliaOptions: {"facetFilters":["version:v1.7.0"]}
});
</script></body></html>