react-relay 15.0.0 → 16.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ReactRelayContext.js +1 -1
- package/ReactRelayQueryFetcher.js.flow +1 -5
- package/ReactRelayQueryRenderer.js.flow +9 -36
- package/ReactRelayTypes.js.flow +1 -0
- package/buildReactRelayContainer.js.flow +3 -1
- package/hooks.js +1 -1
- package/index.js +1 -1
- package/legacy.js +1 -1
- package/lib/ReactRelayContainerUtils.js +0 -11
- package/lib/ReactRelayContext.js +0 -11
- package/lib/ReactRelayFragmentContainer.js +6 -78
- package/lib/ReactRelayFragmentMockRenderer.js +0 -11
- package/lib/ReactRelayLocalQueryRenderer.js +0 -17
- package/lib/ReactRelayPaginationContainer.js +5 -208
- package/lib/ReactRelayQueryFetcher.js +2 -51
- package/lib/ReactRelayQueryRenderer.js +6 -94
- package/lib/ReactRelayQueryRendererContext.js +0 -11
- package/lib/ReactRelayRefetchContainer.js +5 -91
- package/lib/ReactRelayTestMocker.js +9 -85
- package/lib/ReactRelayTypes.js +0 -11
- package/lib/RelayContext.js +0 -21
- package/lib/assertFragmentMap.js +0 -15
- package/lib/buildReactRelayContainer.js +0 -19
- package/lib/getRootVariablesForFragments.js +0 -14
- package/lib/hooks.js +0 -15
- package/lib/index.js +0 -17
- package/lib/isRelayEnvironment.js +1 -18
- package/lib/jest-react/enqueueTask.js +0 -20
- package/lib/jest-react/internalAct.js +0 -38
- package/lib/legacy.js +0 -15
- package/lib/multi-actor/ActorChange.js +0 -11
- package/lib/multi-actor/index.js +0 -11
- package/lib/multi-actor/useRelayActorEnvironment.js +0 -11
- package/lib/relay-hooks/EntryPointContainer.react.js +0 -11
- package/lib/relay-hooks/EntryPointTypes.flow.js +1 -14
- package/lib/relay-hooks/FragmentResource.js +76 -132
- package/lib/relay-hooks/HooksImplementation.js +1 -12
- package/lib/relay-hooks/InternalLogger.js +0 -11
- package/lib/relay-hooks/LRUCache.js +0 -22
- package/lib/relay-hooks/LazyLoadEntryPointContainer_DEPRECATED.react.js +0 -18
- package/lib/relay-hooks/MatchContainer.js +0 -94
- package/lib/relay-hooks/NestedRelayEntryPointBuilderUtils.js +9 -0
- package/lib/relay-hooks/ProfilerContext.js +0 -15
- package/lib/relay-hooks/QueryResource.js +2 -68
- package/lib/relay-hooks/RelayEnvironmentProvider.js +0 -11
- package/lib/relay-hooks/SuspenseResource.js +0 -34
- package/lib/relay-hooks/{react-cache/readFragmentInternal_REACT_CACHE.js → experimental/readFragmentInternal_EXPERIMENTAL.js} +5 -29
- package/lib/relay-hooks/{react-cache/useFragmentInternal_REACT_CACHE.js → experimental/useFragmentInternal_EXPERIMENTAL.js} +35 -100
- package/lib/relay-hooks/{react-cache/useFragment_REACT_CACHE.js → experimental/useFragment_EXPERIMENTAL.js} +1 -16
- package/lib/relay-hooks/{react-cache/usePaginationFragment_REACT_CACHE.js → experimental/usePaginationFragment_EXPERIMENTAL.js} +2 -24
- package/lib/relay-hooks/{react-cache/useRefetchableFragmentInternal_REACT_CACHE.js → experimental/useRefetchableFragmentInternal_EXPERIMENTAL.js} +14 -98
- package/lib/relay-hooks/{react-cache/useRefetchableFragment_REACT_CACHE.js → experimental/useRefetchableFragment_EXPERIMENTAL.js} +1 -15
- package/lib/relay-hooks/loadEntryPoint.js +1 -24
- package/lib/relay-hooks/loadQuery.js +2 -106
- package/lib/relay-hooks/preloadQuery_DEPRECATED.js +2 -27
- package/lib/relay-hooks/prepareEntryPoint_DEPRECATED.js +0 -13
- package/lib/relay-hooks/useBlockingPaginationFragment.js +0 -42
- package/lib/relay-hooks/useClientQuery.js +0 -18
- package/lib/relay-hooks/useEntryPointLoader.js +0 -69
- package/lib/relay-hooks/useFetchTrackingRef.js +0 -26
- package/lib/relay-hooks/useFragment.js +0 -17
- package/lib/relay-hooks/useFragmentNode.js +2 -32
- package/lib/relay-hooks/useIsMountedRef.js +0 -11
- package/lib/relay-hooks/useIsOperationNodeActive.js +0 -11
- package/lib/relay-hooks/useIsParentQueryActive.js +0 -11
- package/lib/relay-hooks/useLazyLoadQuery.js +0 -18
- package/lib/relay-hooks/useLazyLoadQueryNode.js +12 -37
- package/lib/relay-hooks/useLoadMoreFunction.js +9 -34
- package/lib/relay-hooks/useMemoOperationDescriptor.js +0 -11
- package/lib/relay-hooks/useMemoVariables.js +0 -17
- package/lib/relay-hooks/useMutation.js +0 -11
- package/lib/relay-hooks/usePaginationFragment.js +1 -26
- package/lib/relay-hooks/usePreloadedQuery.js +0 -27
- package/lib/relay-hooks/useQueryLoader.js +0 -74
- package/lib/relay-hooks/useRefetchableFragment.js +0 -16
- package/lib/relay-hooks/useRefetchableFragmentNode.js +14 -97
- package/lib/relay-hooks/useRelayEnvironment.js +0 -11
- package/lib/relay-hooks/useStaticFragmentNodeWarning.js +0 -15
- package/lib/relay-hooks/useSubscribeToInvalidationState.js +0 -25
- package/lib/relay-hooks/useSubscription.js +0 -15
- package/lib/relay-hooks/useUnsafeRef_DEPRECATED.js +0 -17
- package/package.json +2 -2
- package/react-relay-hooks.js +2 -2
- package/react-relay-hooks.min.js +2 -2
- package/react-relay-legacy.js +2 -2
- package/react-relay-legacy.min.js +2 -2
- package/react-relay.js +2 -2
- package/react-relay.min.js +2 -2
- package/relay-hooks/EntryPointContainer.react.js.flow +5 -0
- package/relay-hooks/EntryPointTypes.flow.js.flow +34 -35
- package/relay-hooks/FragmentResource.js.flow +114 -26
- package/relay-hooks/HooksImplementation.js.flow +3 -1
- package/relay-hooks/LazyLoadEntryPointContainer_DEPRECATED.react.js.flow +4 -2
- package/relay-hooks/NestedRelayEntryPointBuilderUtils.js.flow +51 -0
- package/relay-hooks/__flowtests__/EntryPointTypes/NestedEntrypoints-flowtest.js.flow +7 -5
- package/relay-hooks/__flowtests__/useBlockingPaginationFragment-flowtest.js.flow +5 -0
- package/relay-hooks/__flowtests__/usePaginationFragment-flowtest.js.flow +5 -0
- package/relay-hooks/__flowtests__/useRefetchableFragment-flowtest.js.flow +2 -0
- package/relay-hooks/{react-cache/readFragmentInternal_REACT_CACHE.js.flow → experimental/readFragmentInternal_EXPERIMENTAL.js.flow} +4 -3
- package/relay-hooks/{react-cache/useFragmentInternal_REACT_CACHE.js.flow → experimental/useFragmentInternal_EXPERIMENTAL.js.flow} +32 -14
- package/relay-hooks/{react-cache/useFragment_REACT_CACHE.js.flow → experimental/useFragment_EXPERIMENTAL.js.flow} +4 -10
- package/relay-hooks/{react-cache/usePaginationFragment_REACT_CACHE.js.flow → experimental/usePaginationFragment_EXPERIMENTAL.js.flow} +30 -59
- package/relay-hooks/{react-cache/useRefetchableFragmentInternal_REACT_CACHE.js.flow → experimental/useRefetchableFragmentInternal_EXPERIMENTAL.js.flow} +30 -23
- package/relay-hooks/experimental/useRefetchableFragment_EXPERIMENTAL.js.flow +49 -0
- package/relay-hooks/loadEntryPoint.js.flow +4 -2
- package/relay-hooks/loadQuery.js.flow +21 -1
- package/relay-hooks/prepareEntryPoint_DEPRECATED.js.flow +4 -2
- package/relay-hooks/useBlockingPaginationFragment.js.flow +10 -17
- package/relay-hooks/useClientQuery.js.flow +2 -2
- package/relay-hooks/useFragmentNode.js.flow +2 -2
- package/relay-hooks/useLazyLoadQueryNode.js.flow +17 -1
- package/relay-hooks/useLoadMoreFunction.js.flow +15 -9
- package/relay-hooks/useMutation.js.flow +26 -9
- package/relay-hooks/usePaginationFragment.js.flow +7 -15
- package/relay-hooks/useQueryLoader.js.flow +2 -8
- package/relay-hooks/useRefetchableFragment.js.flow +14 -16
- package/relay-hooks/useRefetchableFragmentNode.js.flow +33 -20
- package/lib/relay-hooks/react-cache/RelayReactCache.js +0 -32
- package/lib/relay-hooks/react-cache/getQueryResultOrFetchQuery_REACT_CACHE.js +0 -290
- package/lib/relay-hooks/react-cache/useLazyLoadQuery_REACT_CACHE.js +0 -49
- package/lib/relay-hooks/react-cache/usePreloadedQuery_REACT_CACHE.js +0 -110
- package/relay-hooks/react-cache/RelayReactCache.js.flow +0 -40
- package/relay-hooks/react-cache/getQueryResultOrFetchQuery_REACT_CACHE.js.flow +0 -430
- package/relay-hooks/react-cache/useLazyLoadQuery_REACT_CACHE.js.flow +0 -70
- package/relay-hooks/react-cache/usePreloadedQuery_REACT_CACHE.js.flow +0 -150
- package/relay-hooks/react-cache/useRefetchableFragment_REACT_CACHE.js.flow +0 -65
|
@@ -50,7 +50,12 @@ type FragmentResourceCache = Cache<
|
|
|
50
50
|
promise: Promise<mixed>,
|
|
51
51
|
result: FragmentResult,
|
|
52
52
|
}
|
|
53
|
-
| {kind: 'done', result: FragmentResult}
|
|
53
|
+
| {kind: 'done', result: FragmentResult}
|
|
54
|
+
| {
|
|
55
|
+
kind: 'missing',
|
|
56
|
+
result: FragmentResult,
|
|
57
|
+
snapshot: SingularOrPluralSnapshot,
|
|
58
|
+
},
|
|
54
59
|
>;
|
|
55
60
|
|
|
56
61
|
const WEAKMAP_SUPPORTED = typeof WeakMap === 'function';
|
|
@@ -348,16 +353,28 @@ class FragmentResourceImpl {
|
|
|
348
353
|
componentDisplayName,
|
|
349
354
|
);
|
|
350
355
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
356
|
+
let fragmentResult = null;
|
|
357
|
+
let snapshot = null;
|
|
358
|
+
// Fall through to existing logic if it's 'missing' state so it would check and save promise into cache.
|
|
359
|
+
if (
|
|
360
|
+
RelayFeatureFlags.ENABLE_RELAY_OPERATION_TRACKER_SUSPENSE &&
|
|
361
|
+
cachedValue != null &&
|
|
362
|
+
cachedValue.kind === 'missing'
|
|
363
|
+
) {
|
|
364
|
+
fragmentResult = cachedValue.result;
|
|
365
|
+
snapshot = cachedValue.snapshot;
|
|
366
|
+
} else {
|
|
367
|
+
snapshot =
|
|
368
|
+
fragmentSelector.kind === 'PluralReaderSelector'
|
|
369
|
+
? fragmentSelector.selectors.map(s => environment.lookup(s))
|
|
370
|
+
: environment.lookup(fragmentSelector);
|
|
355
371
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
372
|
+
fragmentResult = getFragmentResult(
|
|
373
|
+
fragmentIdentifier,
|
|
374
|
+
snapshot,
|
|
375
|
+
storeEpoch,
|
|
376
|
+
);
|
|
377
|
+
}
|
|
361
378
|
if (!fragmentResult.isMissingData) {
|
|
362
379
|
this._throwOrLogErrorsInSnapshot(snapshot);
|
|
363
380
|
|
|
@@ -483,6 +500,17 @@ class FragmentResourceImpl {
|
|
|
483
500
|
}
|
|
484
501
|
}
|
|
485
502
|
|
|
503
|
+
// set it as done if has missing data and no pending operations
|
|
504
|
+
if (
|
|
505
|
+
RelayFeatureFlags.ENABLE_RELAY_OPERATION_TRACKER_SUSPENSE &&
|
|
506
|
+
fragmentResult.isMissingData
|
|
507
|
+
) {
|
|
508
|
+
this._cache.set(fragmentIdentifier, {
|
|
509
|
+
kind: 'done',
|
|
510
|
+
result: fragmentResult,
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
|
|
486
514
|
this._throwOrLogErrorsInSnapshot(snapshot);
|
|
487
515
|
|
|
488
516
|
// At this point, there's nothing we can do. We don't have all the expected
|
|
@@ -617,10 +645,26 @@ class FragmentResourceImpl {
|
|
|
617
645
|
disposables.push(
|
|
618
646
|
environment.subscribe(currentSnapshot, latestSnapshot => {
|
|
619
647
|
const storeEpoch = environment.getStore().getEpoch();
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
648
|
+
const result = getFragmentResult(
|
|
649
|
+
cacheKey,
|
|
650
|
+
latestSnapshot,
|
|
651
|
+
storeEpoch,
|
|
652
|
+
);
|
|
653
|
+
if (
|
|
654
|
+
RelayFeatureFlags.ENABLE_RELAY_OPERATION_TRACKER_SUSPENSE &&
|
|
655
|
+
result.isMissingData
|
|
656
|
+
) {
|
|
657
|
+
this._cache.set(cacheKey, {
|
|
658
|
+
kind: 'missing',
|
|
659
|
+
result: result,
|
|
660
|
+
snapshot: latestSnapshot,
|
|
661
|
+
});
|
|
662
|
+
} else {
|
|
663
|
+
this._cache.set(cacheKey, {
|
|
664
|
+
kind: 'done',
|
|
665
|
+
result: getFragmentResult(cacheKey, latestSnapshot, storeEpoch),
|
|
666
|
+
});
|
|
667
|
+
}
|
|
624
668
|
callback();
|
|
625
669
|
}),
|
|
626
670
|
);
|
|
@@ -696,10 +740,26 @@ class FragmentResourceImpl {
|
|
|
696
740
|
// Only update the cache when the data is changed to avoid
|
|
697
741
|
// returning different `data` instances
|
|
698
742
|
if (didMissUpdates) {
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
743
|
+
const result = getFragmentResult(
|
|
744
|
+
cacheKey,
|
|
745
|
+
currentSnapshots,
|
|
746
|
+
storeEpoch,
|
|
747
|
+
);
|
|
748
|
+
if (
|
|
749
|
+
RelayFeatureFlags.ENABLE_RELAY_OPERATION_TRACKER_SUSPENSE &&
|
|
750
|
+
result.isMissingData
|
|
751
|
+
) {
|
|
752
|
+
this._cache.set(cacheKey, {
|
|
753
|
+
kind: 'missing',
|
|
754
|
+
result,
|
|
755
|
+
snapshot: currentSnapshots,
|
|
756
|
+
});
|
|
757
|
+
} else {
|
|
758
|
+
this._cache.set(cacheKey, {
|
|
759
|
+
kind: 'done',
|
|
760
|
+
result,
|
|
761
|
+
});
|
|
762
|
+
}
|
|
703
763
|
}
|
|
704
764
|
return [didMissUpdates, currentSnapshots];
|
|
705
765
|
}
|
|
@@ -718,10 +778,26 @@ class FragmentResourceImpl {
|
|
|
718
778
|
relayResolverErrors: currentSnapshot.relayResolverErrors,
|
|
719
779
|
};
|
|
720
780
|
if (updatedData !== renderData) {
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
781
|
+
const result = getFragmentResult(
|
|
782
|
+
cacheKey,
|
|
783
|
+
updatedCurrentSnapshot,
|
|
784
|
+
storeEpoch,
|
|
785
|
+
);
|
|
786
|
+
if (
|
|
787
|
+
RelayFeatureFlags.ENABLE_RELAY_OPERATION_TRACKER_SUSPENSE &&
|
|
788
|
+
result.isMissingData
|
|
789
|
+
) {
|
|
790
|
+
this._cache.set(cacheKey, {
|
|
791
|
+
kind: 'missing',
|
|
792
|
+
result: result,
|
|
793
|
+
snapshot: updatedCurrentSnapshot,
|
|
794
|
+
});
|
|
795
|
+
} else {
|
|
796
|
+
this._cache.set(cacheKey, {
|
|
797
|
+
kind: 'done',
|
|
798
|
+
result,
|
|
799
|
+
});
|
|
800
|
+
}
|
|
725
801
|
}
|
|
726
802
|
return [updatedData !== renderData, updatedCurrentSnapshot];
|
|
727
803
|
}
|
|
@@ -799,10 +875,22 @@ class FragmentResourceImpl {
|
|
|
799
875
|
? [...currentSnapshot]
|
|
800
876
|
: [...baseSnapshots];
|
|
801
877
|
nextSnapshots[idx] = latestSnapshot;
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
878
|
+
const result = getFragmentResult(cacheKey, nextSnapshots, storeEpoch);
|
|
879
|
+
if (
|
|
880
|
+
RelayFeatureFlags.ENABLE_RELAY_OPERATION_TRACKER_SUSPENSE &&
|
|
881
|
+
result.isMissingData
|
|
882
|
+
) {
|
|
883
|
+
this._cache.set(cacheKey, {
|
|
884
|
+
kind: 'missing',
|
|
885
|
+
result,
|
|
886
|
+
snapshot: nextSnapshots,
|
|
887
|
+
});
|
|
888
|
+
} else {
|
|
889
|
+
this._cache.set(cacheKey, {
|
|
890
|
+
kind: 'done',
|
|
891
|
+
result,
|
|
892
|
+
});
|
|
893
|
+
}
|
|
806
894
|
}
|
|
807
895
|
}
|
|
808
896
|
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
'use strict';
|
|
13
13
|
|
|
14
|
+
import typeof useFragmentInternal from './experimental/useFragmentInternal_EXPERIMENTAL';
|
|
14
15
|
import typeof useFragment from './useFragment';
|
|
15
16
|
import type {UsePaginationFragmentType} from './usePaginationFragment';
|
|
16
17
|
import type {UseRefetchableFragmentType} from './useRefetchableFragment';
|
|
@@ -21,13 +22,14 @@ type HooksImplementation = {
|
|
|
21
22
|
useFragment: useFragment,
|
|
22
23
|
usePaginationFragment: UsePaginationFragmentType,
|
|
23
24
|
useRefetchableFragment: UseRefetchableFragmentType,
|
|
25
|
+
useFragment__internal?: useFragmentInternal,
|
|
24
26
|
};
|
|
25
27
|
|
|
26
28
|
let implementation: HooksImplementation | null = null;
|
|
27
29
|
|
|
28
30
|
function inject(impl: HooksImplementation): void {
|
|
29
31
|
warning(
|
|
30
|
-
implementation
|
|
32
|
+
implementation === null,
|
|
31
33
|
'Relay HooksImplementation was injected twice.',
|
|
32
34
|
);
|
|
33
35
|
implementation = impl;
|
|
@@ -85,8 +85,10 @@ function prepareEntryPoint<
|
|
|
85
85
|
}
|
|
86
86
|
const preloadProps = entryPoint.getPreloadProps(entryPointParams);
|
|
87
87
|
const {queries, entryPoints, extraProps} = preloadProps;
|
|
88
|
-
|
|
89
|
-
const
|
|
88
|
+
// $FlowFixMe[incompatible-type]
|
|
89
|
+
const preloadedQueries: Partial<TPreloadedQueries> = {};
|
|
90
|
+
// $FlowFixMe[incompatible-type]
|
|
91
|
+
const preloadedEntryPoints: Partial<TPreloadedEntryPoints> = {};
|
|
90
92
|
if (queries != null) {
|
|
91
93
|
const queriesPropNames = Object.keys(queries);
|
|
92
94
|
queriesPropNames.forEach(queryPropName => {
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @flow strict-local
|
|
8
|
+
* @format
|
|
9
|
+
* @oncall relay
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
'use strict';
|
|
13
|
+
|
|
14
|
+
import type {
|
|
15
|
+
InternalEntryPointRepresentation,
|
|
16
|
+
ThinNestedEntryPointParams,
|
|
17
|
+
} from './EntryPointTypes.flow';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* This is an identity function to construct a type safe nested entrypoint.
|
|
21
|
+
* By calling this function, we ensure that the type of entryPointParams matches
|
|
22
|
+
* exactly the type of preloadProps of the entrypoint.
|
|
23
|
+
*
|
|
24
|
+
* We make the type of `ThinNestedEntryPointParams` opaque, so that the only way
|
|
25
|
+
* to construct a `ThinNestedEntryPointParams` is by calling this function.
|
|
26
|
+
*/
|
|
27
|
+
declare function NestedRelayEntryPoint<
|
|
28
|
+
TEntryPointParams,
|
|
29
|
+
TPreloadedQueries,
|
|
30
|
+
TPreloadedEntryPoints,
|
|
31
|
+
TRuntimeProps,
|
|
32
|
+
TExtraProps,
|
|
33
|
+
>(
|
|
34
|
+
$ReadOnly<{
|
|
35
|
+
entryPoint: InternalEntryPointRepresentation<
|
|
36
|
+
TEntryPointParams,
|
|
37
|
+
TPreloadedQueries,
|
|
38
|
+
TPreloadedEntryPoints,
|
|
39
|
+
TRuntimeProps,
|
|
40
|
+
TExtraProps,
|
|
41
|
+
>,
|
|
42
|
+
entryPointParams: TEntryPointParams,
|
|
43
|
+
}>,
|
|
44
|
+
): ThinNestedEntryPointParams;
|
|
45
|
+
|
|
46
|
+
// eslint-disable-next-line no-redeclare
|
|
47
|
+
function NestedRelayEntryPoint<P>(params: P): P {
|
|
48
|
+
return params;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export {NestedRelayEntryPoint};
|
|
@@ -18,6 +18,8 @@ import type {
|
|
|
18
18
|
} from '../../EntryPointTypes.flow';
|
|
19
19
|
import type {JSResourceReference} from 'JSResourceReference';
|
|
20
20
|
|
|
21
|
+
import {NestedRelayEntryPoint} from '../../NestedRelayEntryPointBuilderUtils';
|
|
22
|
+
|
|
21
23
|
declare function mockJSResource<TModule>(
|
|
22
24
|
module: TModule,
|
|
23
25
|
): JSResourceReference<TModule>;
|
|
@@ -65,14 +67,14 @@ type BadParentEntrypointParams = $ReadOnly<{}>;
|
|
|
65
67
|
getPreloadProps(_params: BadParentEntrypointParams) {
|
|
66
68
|
return {
|
|
67
69
|
entryPoints: {
|
|
68
|
-
nestedComponent: {
|
|
69
|
-
entryPoint: NestedEntryPoint,
|
|
70
|
+
nestedComponent: NestedRelayEntryPoint({
|
|
70
71
|
/**
|
|
71
72
|
$FlowExpectedError The entryPointParams here should be of type
|
|
72
73
|
NestedEntrypointPreloadParams, but it does not contain subEntrypointPreloadParam
|
|
73
74
|
*/
|
|
75
|
+
entryPoint: NestedEntryPoint,
|
|
74
76
|
entryPointParams: Object.freeze({}),
|
|
75
|
-
},
|
|
77
|
+
}),
|
|
76
78
|
},
|
|
77
79
|
};
|
|
78
80
|
},
|
|
@@ -90,13 +92,13 @@ type GoodParentEntrypointParams = $ReadOnly<{}>;
|
|
|
90
92
|
getPreloadProps(_params: GoodParentEntrypointParams) {
|
|
91
93
|
return {
|
|
92
94
|
entryPoints: {
|
|
93
|
-
nestedComponent: {
|
|
95
|
+
nestedComponent: NestedRelayEntryPoint({
|
|
94
96
|
entryPoint: NestedEntryPoint,
|
|
95
97
|
// No flow error since this matches NestedEntrypointPreloadParams
|
|
96
98
|
entryPointParams: {
|
|
97
99
|
subEntrypointPreloadParam: 'test',
|
|
98
100
|
},
|
|
99
|
-
},
|
|
101
|
+
}),
|
|
100
102
|
},
|
|
101
103
|
};
|
|
102
104
|
},
|
|
@@ -45,6 +45,8 @@ type ExpectedReturnType<
|
|
|
45
45
|
/* eslint-disable react-hooks/rules-of-hooks */
|
|
46
46
|
|
|
47
47
|
// Nullability of returned data type is correct
|
|
48
|
+
// $FlowFixMe[prop-missing]
|
|
49
|
+
// $FlowFixMe[incompatible-cast]
|
|
48
50
|
(useBlockingPaginationFragment(
|
|
49
51
|
refetchableFragmentInput,
|
|
50
52
|
keyNonNullable,
|
|
@@ -112,9 +114,12 @@ const {loadNext} = useBlockingPaginationFragment(
|
|
|
112
114
|
);
|
|
113
115
|
// Accepts extraVariables
|
|
114
116
|
loadNext(10, {
|
|
117
|
+
// $FlowFixMe[prop-missing]
|
|
118
|
+
// $FlowFixMe[incompatible-call]
|
|
115
119
|
UNSTABLE_extraVariables: extraVariables,
|
|
116
120
|
});
|
|
117
121
|
|
|
122
|
+
// $FlowFixMe[prop-missing]
|
|
118
123
|
loadNext(10, {
|
|
119
124
|
// $FlowExpectedError: doesn't accept variables not available in the Flow type
|
|
120
125
|
UNSTABLE_extraVariables: invalidVariables,
|
|
@@ -47,6 +47,8 @@ type ExpectedReturnType<
|
|
|
47
47
|
/* eslint-disable react-hooks/rules-of-hooks */
|
|
48
48
|
|
|
49
49
|
// Nullability of returned data type is correct
|
|
50
|
+
// $FlowFixMe[prop-missing]
|
|
51
|
+
// $FlowFixMe[incompatible-cast]
|
|
50
52
|
(usePaginationFragment(
|
|
51
53
|
refetchableFragmentInput,
|
|
52
54
|
keyNonNullable,
|
|
@@ -113,9 +115,12 @@ const {loadNext} = usePaginationFragment(
|
|
|
113
115
|
);
|
|
114
116
|
// Accepts extraVariables
|
|
115
117
|
loadNext(10, {
|
|
118
|
+
// $FlowFixMe[prop-missing]
|
|
119
|
+
// $FlowFixMe[incompatible-call]
|
|
116
120
|
UNSTABLE_extraVariables: extraVariables,
|
|
117
121
|
});
|
|
118
122
|
|
|
123
|
+
// $FlowFixMe[prop-missing]
|
|
119
124
|
loadNext(10, {
|
|
120
125
|
// $FlowExpectedError: doesn't accept variables not available in the Flow type
|
|
121
126
|
UNSTABLE_extraVariables: invalidVariables,
|
|
@@ -31,6 +31,8 @@ import {
|
|
|
31
31
|
/* eslint-disable react-hooks/rules-of-hooks */
|
|
32
32
|
|
|
33
33
|
// Nullability of returned data type is correct
|
|
34
|
+
// $FlowFixMe[prop-missing]
|
|
35
|
+
// $FlowFixMe[incompatible-cast]
|
|
34
36
|
(useRefetchableFragment(refetchableFragmentInput, keyNonNullable): [
|
|
35
37
|
NonNullableData,
|
|
36
38
|
FetchFn<QueryVariablesSubset>,
|
|
@@ -27,6 +27,7 @@ const {getQueryResourceForEnvironment} = require('../QueryResource');
|
|
|
27
27
|
const invariant = require('invariant');
|
|
28
28
|
const {
|
|
29
29
|
__internal: {fetchQuery: fetchQueryInternal},
|
|
30
|
+
RelayFeatureFlags,
|
|
30
31
|
createOperationDescriptor,
|
|
31
32
|
getPendingOperationsForFragment,
|
|
32
33
|
getSelector,
|
|
@@ -156,7 +157,7 @@ function getFragmentState(
|
|
|
156
157
|
}
|
|
157
158
|
|
|
158
159
|
// fragmentNode cannot change during the lifetime of the component, though fragmentRef may change.
|
|
159
|
-
function
|
|
160
|
+
function readFragmentInternal_EXPERIMENTAL(
|
|
160
161
|
environment: IEnvironment,
|
|
161
162
|
fragmentNode: ReaderFragment,
|
|
162
163
|
fragmentRef: mixed,
|
|
@@ -268,7 +269,7 @@ function readFragmentInternal_REACT_CACHE(
|
|
|
268
269
|
data = state.snapshots.map(s => s.data);
|
|
269
270
|
}
|
|
270
271
|
|
|
271
|
-
if (__DEV__) {
|
|
272
|
+
if (RelayFeatureFlags.LOG_MISSING_RECORDS_IN_PROD || __DEV__) {
|
|
272
273
|
if (
|
|
273
274
|
fragmentRef != null &&
|
|
274
275
|
(data === undefined ||
|
|
@@ -294,4 +295,4 @@ function readFragmentInternal_REACT_CACHE(
|
|
|
294
295
|
return {data, clientEdgeQueries};
|
|
295
296
|
}
|
|
296
297
|
|
|
297
|
-
module.exports =
|
|
298
|
+
module.exports = readFragmentInternal_EXPERIMENTAL;
|
|
@@ -32,6 +32,7 @@ const invariant = require('invariant');
|
|
|
32
32
|
const {useDebugValue, useEffect, useMemo, useRef, useState} = require('react');
|
|
33
33
|
const {
|
|
34
34
|
__internal: {fetchQuery: fetchQueryInternal},
|
|
35
|
+
RelayFeatureFlags,
|
|
35
36
|
areEqualSelectors,
|
|
36
37
|
createOperationDescriptor,
|
|
37
38
|
getPendingOperationsForFragment,
|
|
@@ -256,7 +257,17 @@ function subscribeToSnapshot(
|
|
|
256
257
|
prevState.kind !== 'singular' ||
|
|
257
258
|
prevState.snapshot.selector !== latestSnapshot.selector
|
|
258
259
|
) {
|
|
259
|
-
|
|
260
|
+
const updates = handleMissedUpdates(environment, prevState);
|
|
261
|
+
if (updates != null) {
|
|
262
|
+
const [dataChanged, nextState] = updates;
|
|
263
|
+
environment.__log({
|
|
264
|
+
name: 'useFragment.subscription.missedUpdates',
|
|
265
|
+
hasDataChanges: dataChanged,
|
|
266
|
+
});
|
|
267
|
+
return dataChanged ? nextState : prevState;
|
|
268
|
+
} else {
|
|
269
|
+
return prevState;
|
|
270
|
+
}
|
|
260
271
|
}
|
|
261
272
|
return {
|
|
262
273
|
kind: 'singular',
|
|
@@ -279,7 +290,17 @@ function subscribeToSnapshot(
|
|
|
279
290
|
prevState.kind !== 'plural' ||
|
|
280
291
|
prevState.snapshots[index]?.selector !== latestSnapshot.selector
|
|
281
292
|
) {
|
|
282
|
-
|
|
293
|
+
const updates = handleMissedUpdates(environment, prevState);
|
|
294
|
+
if (updates != null) {
|
|
295
|
+
const [dataChanged, nextState] = updates;
|
|
296
|
+
environment.__log({
|
|
297
|
+
name: 'useFragment.subscription.missedUpdates',
|
|
298
|
+
hasDataChanges: dataChanged,
|
|
299
|
+
});
|
|
300
|
+
return dataChanged ? nextState : prevState;
|
|
301
|
+
} else {
|
|
302
|
+
return prevState;
|
|
303
|
+
}
|
|
283
304
|
}
|
|
284
305
|
const updated = [...prevState.snapshots];
|
|
285
306
|
updated[index] = latestSnapshot;
|
|
@@ -323,12 +344,11 @@ function getFragmentState(
|
|
|
323
344
|
}
|
|
324
345
|
|
|
325
346
|
// fragmentNode cannot change during the lifetime of the component, though fragmentRef may change.
|
|
326
|
-
function
|
|
347
|
+
function useFragmentInternal_EXPERIMENTAL(
|
|
327
348
|
fragmentNode: ReaderFragment,
|
|
328
349
|
fragmentRef: mixed,
|
|
329
350
|
hookDisplayName: string,
|
|
330
351
|
queryOptions?: FragmentQueryOptions,
|
|
331
|
-
fragmentKey?: string,
|
|
332
352
|
): ?SelectorData | Array<?SelectorData> {
|
|
333
353
|
const fragmentSelector = useMemo(
|
|
334
354
|
() => getSelector(fragmentNode, fragmentRef),
|
|
@@ -343,7 +363,6 @@ function useFragmentInternal_REACT_CACHE(
|
|
|
343
363
|
'Relay: Expected fragment pointer%s for fragment `%s` to be ' +
|
|
344
364
|
'an array, instead got `%s`. Remove `@relay(plural: true)` ' +
|
|
345
365
|
'from fragment `%s` to allow the prop to be an object.',
|
|
346
|
-
fragmentKey != null ? ` for key \`${fragmentKey}\`` : '',
|
|
347
366
|
fragmentNode.name,
|
|
348
367
|
typeof fragmentRef,
|
|
349
368
|
fragmentNode.name,
|
|
@@ -354,7 +373,6 @@ function useFragmentInternal_REACT_CACHE(
|
|
|
354
373
|
'Relay: Expected fragment pointer%s for fragment `%s` not to be ' +
|
|
355
374
|
'an array, instead got `%s`. Add `@relay(plural: true)` ' +
|
|
356
375
|
'to fragment `%s` to allow the prop to be an array.',
|
|
357
|
-
fragmentKey != null ? ` for key \`${fragmentKey}\`` : '',
|
|
358
376
|
fragmentNode.name,
|
|
359
377
|
typeof fragmentRef,
|
|
360
378
|
fragmentNode.name,
|
|
@@ -378,7 +396,6 @@ function useFragmentInternal_REACT_CACHE(
|
|
|
378
396
|
fragmentNode.name,
|
|
379
397
|
hookDisplayName,
|
|
380
398
|
fragmentNode.name,
|
|
381
|
-
fragmentKey == null ? 'a fragment reference' : `the \`${fragmentKey}\``,
|
|
382
399
|
hookDisplayName,
|
|
383
400
|
);
|
|
384
401
|
|
|
@@ -418,7 +435,7 @@ function useFragmentInternal_REACT_CACHE(
|
|
|
418
435
|
// The purpose of this is to detect whether we have ever committed, because we
|
|
419
436
|
// don't suspend on store updates, only when the component either is first trying
|
|
420
437
|
// to mount or when the our selector changes. The selector change in particular is
|
|
421
|
-
// how we suspend for pagination and
|
|
438
|
+
// how we suspend for pagination and refetch. Also, fragment selector can be null
|
|
422
439
|
// or undefined, so we use false as a special value to distinguish from all fragment
|
|
423
440
|
// selectors; false means that the component hasn't mounted yet.
|
|
424
441
|
const committedFragmentSelectorRef = useRef<false | ?ReaderSelector>(false);
|
|
@@ -505,11 +522,12 @@ function useFragmentInternal_REACT_CACHE(
|
|
|
505
522
|
throw pendingOperationsResult.promise;
|
|
506
523
|
}
|
|
507
524
|
}
|
|
508
|
-
// Report required fields only if we're not suspending, since that means
|
|
509
|
-
// they're missing even though we are out of options for possibly fetching them:
|
|
510
|
-
handlePotentialSnapshotErrorsForState(environment, state);
|
|
511
525
|
}
|
|
512
526
|
|
|
527
|
+
// Report required fields only if we're not suspending, since that means
|
|
528
|
+
// they're missing even though we are out of options for possibly fetching them:
|
|
529
|
+
handlePotentialSnapshotErrorsForState(environment, state);
|
|
530
|
+
|
|
513
531
|
useEffect(() => {
|
|
514
532
|
// Check for updates since the state was rendered
|
|
515
533
|
let currentState = subscribedState;
|
|
@@ -533,7 +551,7 @@ function useFragmentInternal_REACT_CACHE(
|
|
|
533
551
|
|
|
534
552
|
let data: ?SelectorData | Array<?SelectorData>;
|
|
535
553
|
if (isPlural) {
|
|
536
|
-
// Plural fragments require allocating an array of the
|
|
554
|
+
// Plural fragments require allocating an array of the snapshot data values,
|
|
537
555
|
// which has to be memoized to avoid triggering downstream re-renders.
|
|
538
556
|
//
|
|
539
557
|
// Note that isPlural is a constant property of the fragment and does not change
|
|
@@ -565,7 +583,7 @@ function useFragmentInternal_REACT_CACHE(
|
|
|
565
583
|
data = state.snapshot.data;
|
|
566
584
|
}
|
|
567
585
|
|
|
568
|
-
if (__DEV__) {
|
|
586
|
+
if (RelayFeatureFlags.LOG_MISSING_RECORDS_IN_PROD || __DEV__) {
|
|
569
587
|
if (
|
|
570
588
|
fragmentRef != null &&
|
|
571
589
|
(data === undefined ||
|
|
@@ -596,4 +614,4 @@ function useFragmentInternal_REACT_CACHE(
|
|
|
596
614
|
return data;
|
|
597
615
|
}
|
|
598
616
|
|
|
599
|
-
module.exports =
|
|
617
|
+
module.exports = useFragmentInternal_EXPERIMENTAL;
|
|
@@ -15,7 +15,7 @@ import type {Fragment, FragmentType, GraphQLTaggedNode} from 'relay-runtime';
|
|
|
15
15
|
|
|
16
16
|
const {useTrackLoadQueryInRender} = require('../loadQuery');
|
|
17
17
|
const useStaticFragmentNodeWarning = require('../useStaticFragmentNodeWarning');
|
|
18
|
-
const useFragmentInternal = require('./
|
|
18
|
+
const useFragmentInternal = require('./useFragmentInternal_EXPERIMENTAL');
|
|
19
19
|
const {useDebugValue} = require('react');
|
|
20
20
|
const {getFragment} = require('relay-runtime');
|
|
21
21
|
|
|
@@ -30,23 +30,17 @@ declare function useFragment<TFragmentType: FragmentType, TData>(
|
|
|
30
30
|
key: HasSpread<TFragmentType>,
|
|
31
31
|
): TData;
|
|
32
32
|
|
|
33
|
-
// if the key is nullable, return nullable value
|
|
34
|
-
declare function useFragment<TFragmentType: FragmentType, TData>(
|
|
35
|
-
fragment: Fragment<TFragmentType, TData>,
|
|
36
|
-
key: ?HasSpread<TFragmentType>,
|
|
37
|
-
): ?TData;
|
|
38
|
-
|
|
39
33
|
// if the key is a non-nullable array of keys, return non-nullable array
|
|
40
34
|
declare function useFragment<TFragmentType: FragmentType, TData>(
|
|
41
35
|
fragment: Fragment<TFragmentType, TData>,
|
|
42
36
|
key: $ReadOnlyArray<HasSpread<TFragmentType>>,
|
|
43
37
|
): TData;
|
|
44
38
|
|
|
45
|
-
// if the key is
|
|
39
|
+
// if the key is null/void, return null/void value
|
|
46
40
|
declare function useFragment<TFragmentType: FragmentType, TData>(
|
|
47
41
|
fragment: Fragment<TFragmentType, TData>,
|
|
48
|
-
key:
|
|
49
|
-
):
|
|
42
|
+
key: null | void,
|
|
43
|
+
): null | void;
|
|
50
44
|
|
|
51
45
|
function useFragment(fragment: GraphQLTaggedNode, key: mixed): mixed {
|
|
52
46
|
// We need to use this hook in order to be able to track if
|