react-relay 11.0.2 → 13.0.0-rc.2
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/README.md +47 -0
- package/ReactRelayContainerUtils.js.flow +1 -1
- package/ReactRelayContext.js +1 -1
- package/ReactRelayContext.js.flow +3 -4
- package/ReactRelayFragmentContainer.js.flow +25 -25
- package/ReactRelayFragmentMockRenderer.js.flow +2 -2
- package/ReactRelayLocalQueryRenderer.js.flow +7 -8
- package/ReactRelayPaginationContainer.js.flow +112 -59
- package/ReactRelayQueryFetcher.js.flow +10 -11
- package/ReactRelayQueryRenderer.js.flow +116 -82
- package/ReactRelayQueryRendererContext.js.flow +1 -1
- package/ReactRelayRefetchContainer.js.flow +42 -39
- package/ReactRelayTestMocker.js.flow +17 -15
- package/ReactRelayTypes.js.flow +11 -11
- package/RelayContext.js.flow +4 -4
- package/__flowtests__/ReactRelayFragmentContainer-flowtest.js.flow +2 -3
- package/__flowtests__/ReactRelayPaginationContainer-flowtest.js.flow +12 -8
- package/__flowtests__/ReactRelayRefetchContainer-flowtest.js.flow +11 -7
- package/__flowtests__/RelayModern-flowtest.js.flow +79 -47
- package/__flowtests__/RelayModernFlowtest_badref.graphql.js.flow +6 -5
- package/__flowtests__/RelayModernFlowtest_notref.graphql.js.flow +6 -5
- package/__flowtests__/RelayModernFlowtest_user.graphql.js.flow +5 -4
- package/__flowtests__/RelayModernFlowtest_users.graphql.js.flow +5 -4
- package/__flowtests__/__generated__/ReactRelayFragmentContainerFlowtest_viewer.graphql.js.flow +72 -0
- package/__flowtests__/__generated__/ReactRelayFragmentContainerFlowtest_viewer2.graphql.js.flow +72 -0
- package/__flowtests__/__generated__/ReactRelayPaginationContainerFlowtestQuery.graphql.js.flow +227 -0
- package/__flowtests__/__generated__/ReactRelayPaginationContainerFlowtest_viewer.graphql.js.flow +164 -0
- package/__flowtests__/__generated__/ReactRelayRefetchContainerFlowtestQuery.graphql.js.flow +227 -0
- package/__flowtests__/__generated__/ReactRelayRefetchContainerFlowtest_viewer.graphql.js.flow +164 -0
- package/__flowtests__/__generated__/RelayModernFlowtest_badref.graphql.js.flow +66 -0
- package/__flowtests__/__generated__/RelayModernFlowtest_notref.graphql.js.flow +66 -0
- package/__flowtests__/__generated__/RelayModernFlowtest_user.graphql.js.flow +59 -0
- package/__flowtests__/__generated__/RelayModernFlowtest_users.graphql.js.flow +61 -0
- package/assertFragmentMap.js.flow +3 -3
- package/buildReactRelayContainer.js.flow +12 -11
- package/getRootVariablesForFragments.js.flow +3 -5
- package/hooks.js +1 -1
- package/hooks.js.flow +6 -7
- package/index.js +1 -1
- package/index.js.flow +7 -8
- package/isRelayEnvironment.js.flow +1 -1
- package/jest-react/enqueueTask.js.flow +56 -0
- package/jest-react/index.js.flow +12 -0
- package/jest-react/internalAct.js.flow +138 -0
- package/legacy.js +1 -1
- package/legacy.js.flow +1 -1
- package/lib/ReactRelayContainerUtils.js +1 -1
- package/lib/ReactRelayContext.js +1 -1
- package/lib/ReactRelayFragmentContainer.js +22 -16
- package/lib/ReactRelayFragmentMockRenderer.js +3 -3
- package/lib/ReactRelayLocalQueryRenderer.js +8 -9
- package/lib/ReactRelayPaginationContainer.js +97 -39
- package/lib/ReactRelayQueryFetcher.js +3 -3
- package/lib/ReactRelayQueryRenderer.js +87 -54
- package/lib/ReactRelayQueryRendererContext.js +1 -1
- package/lib/ReactRelayRefetchContainer.js +39 -26
- package/lib/ReactRelayTestMocker.js +8 -9
- package/lib/ReactRelayTypes.js +1 -1
- package/lib/RelayContext.js +4 -3
- package/lib/assertFragmentMap.js +3 -2
- package/lib/buildReactRelayContainer.js +8 -8
- package/lib/getRootVariablesForFragments.js +2 -3
- package/lib/hooks.js +6 -6
- package/lib/index.js +8 -8
- package/lib/isRelayEnvironment.js +1 -1
- package/lib/jest-react/enqueueTask.js +53 -0
- package/lib/jest-react/index.js +13 -0
- package/lib/jest-react/internalAct.js +115 -0
- package/lib/legacy.js +1 -1
- package/lib/multi-actor/ActorChange.js +30 -0
- package/lib/multi-actor/index.js +11 -0
- package/lib/multi-actor/useRelayActorEnvironment.js +29 -0
- package/lib/readContext.js +1 -1
- package/lib/relay-hooks/EntryPointContainer.react.js +4 -4
- package/lib/relay-hooks/EntryPointTypes.flow.js +1 -1
- package/lib/relay-hooks/FragmentResource.js +342 -89
- package/lib/relay-hooks/InternalLogger.js +1 -1
- package/lib/relay-hooks/LRUCache.js +1 -1
- package/lib/relay-hooks/LazyLoadEntryPointContainer_DEPRECATED.react.js +5 -5
- package/lib/relay-hooks/MatchContainer.js +2 -2
- package/lib/relay-hooks/ProfilerContext.js +1 -1
- package/lib/relay-hooks/QueryResource.js +172 -29
- package/lib/relay-hooks/RelayEnvironmentProvider.js +6 -4
- package/lib/relay-hooks/SuspenseResource.js +130 -0
- package/lib/relay-hooks/loadEntryPoint.js +1 -1
- package/lib/relay-hooks/loadQuery.js +42 -20
- package/lib/relay-hooks/preloadQuery_DEPRECATED.js +25 -16
- package/lib/relay-hooks/prepareEntryPoint_DEPRECATED.js +1 -1
- package/lib/relay-hooks/useBlockingPaginationFragment.js +5 -6
- package/lib/relay-hooks/useEntryPointLoader.js +3 -3
- package/lib/relay-hooks/useFetchTrackingRef.js +3 -2
- package/lib/relay-hooks/useFragment.js +7 -7
- package/lib/relay-hooks/useFragmentNode.js +5 -5
- package/lib/relay-hooks/useIsMountedRef.js +1 -1
- package/lib/relay-hooks/useIsOperationNodeActive.js +3 -3
- package/lib/relay-hooks/useIsParentQueryActive.js +1 -1
- package/lib/relay-hooks/useLazyLoadQuery.js +4 -4
- package/lib/relay-hooks/useLazyLoadQueryNode.js +11 -5
- package/lib/relay-hooks/useLoadMoreFunction.js +9 -13
- package/lib/relay-hooks/useMemoOperationDescriptor.js +3 -3
- package/lib/relay-hooks/useMemoVariables.js +3 -3
- package/lib/relay-hooks/useMutation.js +18 -7
- package/lib/relay-hooks/usePaginationFragment.js +3 -4
- package/lib/relay-hooks/usePreloadedQuery.js +6 -6
- package/lib/relay-hooks/useQueryLoader.js +31 -11
- package/lib/relay-hooks/useRefetchableFragment.js +1 -1
- package/lib/relay-hooks/useRefetchableFragmentNode.js +14 -18
- package/lib/relay-hooks/useRelayEnvironment.js +3 -3
- package/lib/relay-hooks/useStaticFragmentNodeWarning.js +3 -3
- package/lib/relay-hooks/useSubscribeToInvalidationState.js +3 -2
- package/lib/relay-hooks/useSubscription.js +11 -8
- package/multi-actor/ActorChange.js.flow +58 -0
- package/multi-actor/index.js.flow +14 -0
- package/multi-actor/useRelayActorEnvironment.js.flow +49 -0
- package/package.json +3 -3
- 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/readContext.js.flow +1 -1
- package/relay-hooks/EntryPointContainer.react.js.flow +9 -16
- package/relay-hooks/EntryPointTypes.flow.js.flow +25 -26
- package/relay-hooks/FragmentResource.js.flow +359 -93
- package/relay-hooks/InternalLogger.js.flow +1 -1
- package/relay-hooks/LRUCache.js.flow +1 -1
- package/relay-hooks/LazyLoadEntryPointContainer_DEPRECATED.react.js.flow +33 -47
- package/relay-hooks/MatchContainer.js.flow +4 -3
- package/relay-hooks/ProfilerContext.js.flow +1 -1
- package/relay-hooks/QueryResource.js.flow +217 -26
- package/relay-hooks/RelayEnvironmentProvider.js.flow +15 -5
- package/relay-hooks/SuspenseResource.js.flow +115 -0
- package/relay-hooks/__flowtests__/EntryPointTypes/EntryPointElementConfig-flowtest.js.flow +5 -4
- package/relay-hooks/__flowtests__/EntryPointTypes/NestedEntrypoints-flowtest.js.flow +2 -2
- package/relay-hooks/__flowtests__/__generated__/useFragmentFlowtest_user.graphql.js.flow +59 -0
- package/relay-hooks/__flowtests__/__generated__/useFragmentFlowtest_users.graphql.js.flow +61 -0
- package/relay-hooks/__flowtests__/useBlockingPaginationFragment-flowtest.js.flow +11 -10
- package/relay-hooks/__flowtests__/useFragment-flowtest.js.flow +55 -32
- package/relay-hooks/__flowtests__/usePaginationFragment-flowtest.js.flow +11 -10
- package/relay-hooks/__flowtests__/useRefetchableFragment-flowtest.js.flow +11 -10
- package/relay-hooks/__flowtests__/utils.js.flow +21 -32
- package/relay-hooks/loadEntryPoint.js.flow +7 -13
- package/relay-hooks/loadQuery.js.flow +50 -32
- package/relay-hooks/preloadQuery_DEPRECATED.js.flow +31 -22
- package/relay-hooks/prepareEntryPoint_DEPRECATED.js.flow +7 -13
- package/relay-hooks/useBlockingPaginationFragment.js.flow +14 -12
- package/relay-hooks/useEntryPointLoader.js.flow +8 -11
- package/relay-hooks/useFetchTrackingRef.js.flow +3 -3
- package/relay-hooks/useFragment.js.flow +31 -62
- package/relay-hooks/useFragmentNode.js.flow +6 -8
- package/relay-hooks/useIsMountedRef.js.flow +1 -1
- package/relay-hooks/useIsOperationNodeActive.js.flow +4 -6
- package/relay-hooks/useIsParentQueryActive.js.flow +4 -5
- package/relay-hooks/useLazyLoadQuery.js.flow +14 -16
- package/relay-hooks/useLazyLoadQueryNode.js.flow +20 -14
- package/relay-hooks/useLoadMoreFunction.js.flow +21 -30
- package/relay-hooks/useMemoOperationDescriptor.js.flow +6 -8
- package/relay-hooks/useMemoVariables.js.flow +7 -7
- package/relay-hooks/useMutation.js.flow +27 -27
- package/relay-hooks/usePaginationFragment.js.flow +39 -45
- package/relay-hooks/usePreloadedQuery.js.flow +14 -20
- package/relay-hooks/useQueryLoader.js.flow +42 -23
- package/relay-hooks/useRefetchableFragment.js.flow +8 -9
- package/relay-hooks/useRefetchableFragmentNode.js.flow +25 -33
- package/relay-hooks/useRelayEnvironment.js.flow +3 -5
- package/relay-hooks/useStaticFragmentNodeWarning.js.flow +3 -4
- package/relay-hooks/useSubscribeToInvalidationState.js.flow +4 -7
- package/relay-hooks/useSubscription.js.flow +21 -11
- package/lib/relay-hooks/getPaginationMetadata.js +0 -41
- package/lib/relay-hooks/getPaginationVariables.js +0 -67
- package/lib/relay-hooks/getRefetchMetadata.js +0 -36
- package/lib/relay-hooks/getValueAtPath.js +0 -51
- package/relay-hooks/getPaginationMetadata.js.flow +0 -74
- package/relay-hooks/getPaginationVariables.js.flow +0 -110
- package/relay-hooks/getRefetchMetadata.js.flow +0 -80
- package/relay-hooks/getValueAtPath.js.flow +0 -46
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright (c)
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
@@ -12,19 +12,6 @@
|
|
|
12
12
|
|
|
13
13
|
'use strict';
|
|
14
14
|
|
|
15
|
-
const React = require('react');
|
|
16
|
-
const ReactRelayContext = require('./ReactRelayContext');
|
|
17
|
-
const ReactRelayQueryFetcher = require('./ReactRelayQueryFetcher');
|
|
18
|
-
const ReactRelayQueryRendererContext = require('./ReactRelayQueryRendererContext');
|
|
19
|
-
|
|
20
|
-
const areEqual = require('areEqual');
|
|
21
|
-
|
|
22
|
-
const {
|
|
23
|
-
createOperationDescriptor,
|
|
24
|
-
deepFreeze,
|
|
25
|
-
getRequest,
|
|
26
|
-
} = require('relay-runtime');
|
|
27
|
-
|
|
28
15
|
import type {ReactRelayQueryRendererContext as ReactRelayQueryRendererContextType} from './ReactRelayQueryRendererContext';
|
|
29
16
|
import type {
|
|
30
17
|
CacheConfig,
|
|
@@ -35,7 +22,20 @@ import type {
|
|
|
35
22
|
Snapshot,
|
|
36
23
|
Variables,
|
|
37
24
|
} from 'relay-runtime';
|
|
38
|
-
|
|
25
|
+
|
|
26
|
+
const ReactRelayContext = require('./ReactRelayContext');
|
|
27
|
+
const ReactRelayQueryFetcher = require('./ReactRelayQueryFetcher');
|
|
28
|
+
const ReactRelayQueryRendererContext = require('./ReactRelayQueryRendererContext');
|
|
29
|
+
const areEqual = require('areEqual');
|
|
30
|
+
const React = require('react');
|
|
31
|
+
const {
|
|
32
|
+
RelayFeatureFlags,
|
|
33
|
+
createOperationDescriptor,
|
|
34
|
+
deepFreeze,
|
|
35
|
+
getRequest,
|
|
36
|
+
} = require('relay-runtime');
|
|
37
|
+
|
|
38
|
+
type RetryCallbacks = {|
|
|
39
39
|
handleDataChange:
|
|
40
40
|
| null
|
|
41
41
|
| (({
|
|
@@ -44,8 +44,7 @@ type RetryCallbacks = {
|
|
|
44
44
|
...
|
|
45
45
|
}) => void),
|
|
46
46
|
handleRetryAfterError: null | ((error: Error) => void),
|
|
47
|
-
|
|
48
|
-
};
|
|
47
|
+
|};
|
|
49
48
|
|
|
50
49
|
export type RenderProps<T> = {|
|
|
51
50
|
error: ?Error,
|
|
@@ -96,6 +95,8 @@ type State = {|
|
|
|
96
95
|
* - Subscribes for updates to the root data and re-renders with any changes.
|
|
97
96
|
*/
|
|
98
97
|
class ReactRelayQueryRenderer extends React.Component<Props, State> {
|
|
98
|
+
_maybeHiddenOrFastRefresh: boolean;
|
|
99
|
+
|
|
99
100
|
constructor(props: Props) {
|
|
100
101
|
super(props);
|
|
101
102
|
|
|
@@ -124,6 +125,8 @@ class ReactRelayQueryRenderer extends React.Component<Props, State> {
|
|
|
124
125
|
queryFetcher = new ReactRelayQueryFetcher();
|
|
125
126
|
}
|
|
126
127
|
|
|
128
|
+
this._maybeHiddenOrFastRefresh = false;
|
|
129
|
+
|
|
127
130
|
this.state = {
|
|
128
131
|
prevPropsEnvironment: props.environment,
|
|
129
132
|
prevPropsVariables: props.variables,
|
|
@@ -148,77 +151,37 @@ class ReactRelayQueryRenderer extends React.Component<Props, State> {
|
|
|
148
151
|
prevState.prevPropsEnvironment !== nextProps.environment ||
|
|
149
152
|
!areEqual(prevState.prevPropsVariables, nextProps.variables)
|
|
150
153
|
) {
|
|
151
|
-
|
|
152
|
-
const prevSelectionReferences = prevState.queryFetcher.getSelectionReferences();
|
|
153
|
-
prevState.queryFetcher.disposeRequest();
|
|
154
|
-
|
|
155
|
-
let queryFetcher;
|
|
156
|
-
if (query) {
|
|
157
|
-
const request = getRequest(query);
|
|
158
|
-
const requestCacheKey = getRequestCacheKey(
|
|
159
|
-
request.params,
|
|
160
|
-
nextProps.variables,
|
|
161
|
-
);
|
|
162
|
-
queryFetcher = requestCache[requestCacheKey]
|
|
163
|
-
? requestCache[requestCacheKey].queryFetcher
|
|
164
|
-
: new ReactRelayQueryFetcher(prevSelectionReferences);
|
|
165
|
-
} else {
|
|
166
|
-
queryFetcher = new ReactRelayQueryFetcher(prevSelectionReferences);
|
|
167
|
-
}
|
|
168
|
-
return {
|
|
169
|
-
prevQuery: nextProps.query,
|
|
170
|
-
prevPropsEnvironment: nextProps.environment,
|
|
171
|
-
prevPropsVariables: nextProps.variables,
|
|
172
|
-
queryFetcher: queryFetcher,
|
|
173
|
-
...fetchQueryAndComputeStateFromProps(
|
|
174
|
-
nextProps,
|
|
175
|
-
queryFetcher,
|
|
176
|
-
prevState.retryCallbacks,
|
|
177
|
-
// passing no requestCacheKey will cause it to be recalculated internally
|
|
178
|
-
// and we want the updated requestCacheKey, since variables may have changed
|
|
179
|
-
),
|
|
180
|
-
};
|
|
154
|
+
return resetQueryStateForUpdate(nextProps, prevState);
|
|
181
155
|
}
|
|
182
|
-
|
|
183
156
|
return null;
|
|
184
157
|
}
|
|
185
158
|
|
|
186
159
|
componentDidMount() {
|
|
160
|
+
if (
|
|
161
|
+
RelayFeatureFlags.ENABLE_QUERY_RENDERER_OFFSCREEN_SUPPORT === true &&
|
|
162
|
+
this._maybeHiddenOrFastRefresh === true
|
|
163
|
+
) {
|
|
164
|
+
// This block only runs if the component has previously "unmounted"
|
|
165
|
+
// due to it being hidden by the Offscreen API, or during fast refresh.
|
|
166
|
+
// At this point, the current cached resource will have been disposed
|
|
167
|
+
// by the previous cleanup, so instead of attempting to
|
|
168
|
+
// do our regular commit setup, so that the query is re-evaluated
|
|
169
|
+
// (and potentially cause a refetch).
|
|
170
|
+
this._maybeHiddenOrFastRefresh = false;
|
|
171
|
+
// eslint-disable-next-line react/no-did-mount-set-state
|
|
172
|
+
this.setState(prevState => {
|
|
173
|
+
return resetQueryStateForUpdate(this.props, prevState);
|
|
174
|
+
});
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
|
|
187
178
|
const {retryCallbacks, queryFetcher, requestCacheKey} = this.state;
|
|
179
|
+
// We don't need to cache the request after the component commits
|
|
188
180
|
if (requestCacheKey) {
|
|
189
181
|
delete requestCache[requestCacheKey];
|
|
190
182
|
}
|
|
191
183
|
|
|
192
|
-
retryCallbacks.handleDataChange =
|
|
193
|
-
error?: Error,
|
|
194
|
-
snapshot?: Snapshot,
|
|
195
|
-
...
|
|
196
|
-
}): void => {
|
|
197
|
-
const error = params.error == null ? null : params.error;
|
|
198
|
-
const snapshot = params.snapshot == null ? null : params.snapshot;
|
|
199
|
-
|
|
200
|
-
this.setState(prevState => {
|
|
201
|
-
const {requestCacheKey: prevRequestCacheKey} = prevState;
|
|
202
|
-
if (prevRequestCacheKey) {
|
|
203
|
-
delete requestCache[prevRequestCacheKey];
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
// Don't update state if nothing has changed.
|
|
207
|
-
if (snapshot === prevState.snapshot && error === prevState.error) {
|
|
208
|
-
return null;
|
|
209
|
-
}
|
|
210
|
-
return {
|
|
211
|
-
renderProps: getRenderProps(
|
|
212
|
-
error,
|
|
213
|
-
snapshot,
|
|
214
|
-
prevState.queryFetcher,
|
|
215
|
-
prevState.retryCallbacks,
|
|
216
|
-
),
|
|
217
|
-
snapshot,
|
|
218
|
-
requestCacheKey: null,
|
|
219
|
-
};
|
|
220
|
-
});
|
|
221
|
-
};
|
|
184
|
+
retryCallbacks.handleDataChange = this._handleDataChange;
|
|
222
185
|
|
|
223
186
|
retryCallbacks.handleRetryAfterError = (error: Error) =>
|
|
224
187
|
this.setState(prevState => {
|
|
@@ -236,22 +199,27 @@ class ReactRelayQueryRenderer extends React.Component<Props, State> {
|
|
|
236
199
|
// Re-initialize the ReactRelayQueryFetcher with callbacks.
|
|
237
200
|
// If data has changed since constructions, this will re-render.
|
|
238
201
|
if (this.props.query) {
|
|
239
|
-
queryFetcher.setOnDataChange(
|
|
202
|
+
queryFetcher.setOnDataChange(this._handleDataChange);
|
|
240
203
|
}
|
|
241
204
|
}
|
|
242
205
|
|
|
243
|
-
componentDidUpdate(): void {
|
|
206
|
+
componentDidUpdate(_prevProps: Props, prevState: State): void {
|
|
244
207
|
// We don't need to cache the request after the component commits
|
|
245
|
-
const {requestCacheKey} = this.state;
|
|
208
|
+
const {queryFetcher, requestCacheKey} = this.state;
|
|
246
209
|
if (requestCacheKey) {
|
|
247
210
|
delete requestCache[requestCacheKey];
|
|
248
211
|
// HACK
|
|
249
212
|
delete this.state.requestCacheKey;
|
|
250
213
|
}
|
|
214
|
+
|
|
215
|
+
if (this.props.query && queryFetcher !== prevState.queryFetcher) {
|
|
216
|
+
queryFetcher.setOnDataChange(this._handleDataChange);
|
|
217
|
+
}
|
|
251
218
|
}
|
|
252
219
|
|
|
253
220
|
componentWillUnmount(): void {
|
|
254
221
|
this.state.queryFetcher.dispose();
|
|
222
|
+
this._maybeHiddenOrFastRefresh = true;
|
|
255
223
|
}
|
|
256
224
|
|
|
257
225
|
shouldComponentUpdate(nextProps: Props, nextState: State): boolean {
|
|
@@ -261,6 +229,37 @@ class ReactRelayQueryRenderer extends React.Component<Props, State> {
|
|
|
261
229
|
);
|
|
262
230
|
}
|
|
263
231
|
|
|
232
|
+
_handleDataChange = (params: {
|
|
233
|
+
error?: Error,
|
|
234
|
+
snapshot?: Snapshot,
|
|
235
|
+
...
|
|
236
|
+
}): void => {
|
|
237
|
+
const error = params.error == null ? null : params.error;
|
|
238
|
+
const snapshot = params.snapshot == null ? null : params.snapshot;
|
|
239
|
+
|
|
240
|
+
this.setState(prevState => {
|
|
241
|
+
const {requestCacheKey: prevRequestCacheKey} = prevState;
|
|
242
|
+
if (prevRequestCacheKey) {
|
|
243
|
+
delete requestCache[prevRequestCacheKey];
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Don't update state if nothing has changed.
|
|
247
|
+
if (snapshot === prevState.snapshot && error === prevState.error) {
|
|
248
|
+
return null;
|
|
249
|
+
}
|
|
250
|
+
return {
|
|
251
|
+
renderProps: getRenderProps(
|
|
252
|
+
error,
|
|
253
|
+
snapshot,
|
|
254
|
+
prevState.queryFetcher,
|
|
255
|
+
prevState.retryCallbacks,
|
|
256
|
+
),
|
|
257
|
+
snapshot,
|
|
258
|
+
requestCacheKey: null,
|
|
259
|
+
};
|
|
260
|
+
});
|
|
261
|
+
};
|
|
262
|
+
|
|
264
263
|
render(): React.Element<typeof ReactRelayContext.Provider> {
|
|
265
264
|
const {renderProps, relayContext} = this.state;
|
|
266
265
|
// Note that the root fragment results in `renderProps.props` is already
|
|
@@ -334,6 +333,41 @@ function getRequestCacheKey(
|
|
|
334
333
|
});
|
|
335
334
|
}
|
|
336
335
|
|
|
336
|
+
function resetQueryStateForUpdate(
|
|
337
|
+
props: Props,
|
|
338
|
+
prevState: State,
|
|
339
|
+
): $Shape<State> {
|
|
340
|
+
const {query} = props;
|
|
341
|
+
|
|
342
|
+
const prevSelectionReferences =
|
|
343
|
+
prevState.queryFetcher.getSelectionReferences();
|
|
344
|
+
prevState.queryFetcher.disposeRequest();
|
|
345
|
+
|
|
346
|
+
let queryFetcher;
|
|
347
|
+
if (query) {
|
|
348
|
+
const request = getRequest(query);
|
|
349
|
+
const requestCacheKey = getRequestCacheKey(request.params, props.variables);
|
|
350
|
+
queryFetcher = requestCache[requestCacheKey]
|
|
351
|
+
? requestCache[requestCacheKey].queryFetcher
|
|
352
|
+
: new ReactRelayQueryFetcher(prevSelectionReferences);
|
|
353
|
+
} else {
|
|
354
|
+
queryFetcher = new ReactRelayQueryFetcher(prevSelectionReferences);
|
|
355
|
+
}
|
|
356
|
+
return {
|
|
357
|
+
prevQuery: props.query,
|
|
358
|
+
prevPropsEnvironment: props.environment,
|
|
359
|
+
prevPropsVariables: props.variables,
|
|
360
|
+
queryFetcher: queryFetcher,
|
|
361
|
+
...fetchQueryAndComputeStateFromProps(
|
|
362
|
+
props,
|
|
363
|
+
queryFetcher,
|
|
364
|
+
prevState.retryCallbacks,
|
|
365
|
+
// passing no requestCacheKey will cause it to be recalculated internally
|
|
366
|
+
// and we want the updated requestCacheKey, since variables may have changed
|
|
367
|
+
),
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
|
|
337
371
|
function fetchQueryAndComputeStateFromProps(
|
|
338
372
|
props: Props,
|
|
339
373
|
queryFetcher: ReactRelayQueryFetcher,
|
|
@@ -390,7 +424,7 @@ function fetchQueryAndComputeStateFromProps(
|
|
|
390
424
|
);
|
|
391
425
|
const querySnapshot = queryFetcher.fetch({
|
|
392
426
|
environment: genericEnvironment,
|
|
393
|
-
onDataChange:
|
|
427
|
+
onDataChange: null,
|
|
394
428
|
operation,
|
|
395
429
|
});
|
|
396
430
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright (c)
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
@@ -12,34 +12,12 @@
|
|
|
12
12
|
|
|
13
13
|
'use strict';
|
|
14
14
|
|
|
15
|
-
const React = require('react');
|
|
16
|
-
const ReactRelayContext = require('./ReactRelayContext');
|
|
17
|
-
const ReactRelayQueryFetcher = require('./ReactRelayQueryFetcher');
|
|
18
|
-
|
|
19
|
-
const areEqual = require('areEqual');
|
|
20
|
-
const buildReactRelayContainer = require('./buildReactRelayContainer');
|
|
21
|
-
const getRootVariablesForFragments = require('./getRootVariablesForFragments');
|
|
22
|
-
const warning = require('warning');
|
|
23
|
-
|
|
24
|
-
const {getContainerName} = require('./ReactRelayContainerUtils');
|
|
25
|
-
const {assertRelayContext} = require('./RelayContext');
|
|
26
|
-
const {
|
|
27
|
-
Observable,
|
|
28
|
-
createFragmentSpecResolver,
|
|
29
|
-
createOperationDescriptor,
|
|
30
|
-
getDataIDsFromObject,
|
|
31
|
-
getRequest,
|
|
32
|
-
getSelector,
|
|
33
|
-
getVariablesFromObject,
|
|
34
|
-
isScalarAndEqual,
|
|
35
|
-
} = require('relay-runtime');
|
|
36
|
-
|
|
37
15
|
import type {
|
|
38
|
-
$RelayProps,
|
|
39
|
-
ObserverOrCallback,
|
|
40
16
|
GeneratedNodeMap,
|
|
17
|
+
ObserverOrCallback,
|
|
41
18
|
RefetchOptions,
|
|
42
19
|
RelayRefetchProp,
|
|
20
|
+
$RelayProps,
|
|
43
21
|
} from './ReactRelayTypes';
|
|
44
22
|
import type {
|
|
45
23
|
CacheConfig,
|
|
@@ -52,6 +30,25 @@ import type {
|
|
|
52
30
|
} from 'relay-runtime';
|
|
53
31
|
import type {FragmentSpecResolver} from 'relay-runtime';
|
|
54
32
|
|
|
33
|
+
const buildReactRelayContainer = require('./buildReactRelayContainer');
|
|
34
|
+
const getRootVariablesForFragments = require('./getRootVariablesForFragments');
|
|
35
|
+
const {getContainerName} = require('./ReactRelayContainerUtils');
|
|
36
|
+
const ReactRelayContext = require('./ReactRelayContext');
|
|
37
|
+
const ReactRelayQueryFetcher = require('./ReactRelayQueryFetcher');
|
|
38
|
+
const {assertRelayContext} = require('./RelayContext');
|
|
39
|
+
const areEqual = require('areEqual');
|
|
40
|
+
const React = require('react');
|
|
41
|
+
const {
|
|
42
|
+
Observable,
|
|
43
|
+
createFragmentSpecResolver,
|
|
44
|
+
createOperationDescriptor,
|
|
45
|
+
getDataIDsFromObject,
|
|
46
|
+
getRequest,
|
|
47
|
+
getVariablesFromObject,
|
|
48
|
+
isScalarAndEqual,
|
|
49
|
+
} = require('relay-runtime');
|
|
50
|
+
const warning = require('warning');
|
|
51
|
+
|
|
55
52
|
type ContainerProps = $FlowFixMeProps;
|
|
56
53
|
|
|
57
54
|
type ContainerState = {
|
|
@@ -119,7 +116,7 @@ function createContainerWithFragments<
|
|
|
119
116
|
|
|
120
117
|
componentDidMount() {
|
|
121
118
|
this._isUnmounted = false;
|
|
122
|
-
this.
|
|
119
|
+
this._subscribeToNewResolverAndRerenderIfStoreHasChanged();
|
|
123
120
|
}
|
|
124
121
|
|
|
125
122
|
componentDidUpdate(prevProps: ContainerProps, prevState: ContainerState) {
|
|
@@ -133,7 +130,9 @@ function createContainerWithFragments<
|
|
|
133
130
|
this._queryFetcher && this._queryFetcher.dispose();
|
|
134
131
|
this._refetchSubscription && this._refetchSubscription.unsubscribe();
|
|
135
132
|
|
|
136
|
-
this.
|
|
133
|
+
this._subscribeToNewResolverAndRerenderIfStoreHasChanged();
|
|
134
|
+
} else {
|
|
135
|
+
this._rerenderIfStoreHasChanged();
|
|
137
136
|
}
|
|
138
137
|
}
|
|
139
138
|
|
|
@@ -250,16 +249,26 @@ function createContainerWithFragments<
|
|
|
250
249
|
return false;
|
|
251
250
|
}
|
|
252
251
|
|
|
253
|
-
|
|
252
|
+
_rerenderIfStoreHasChanged() {
|
|
254
253
|
const {data, resolver} = this.state;
|
|
254
|
+
// External values could change between render and commit.
|
|
255
|
+
// Check for this case, even though it requires an extra store read.
|
|
256
|
+
const maybeNewData = resolver.resolve();
|
|
257
|
+
if (data !== maybeNewData) {
|
|
258
|
+
this.setState({data: maybeNewData});
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
_subscribeToNewResolverAndRerenderIfStoreHasChanged() {
|
|
263
|
+
const {data, resolver} = this.state;
|
|
264
|
+
const maybeNewData = resolver.resolve();
|
|
255
265
|
|
|
256
266
|
// Event listeners are only safe to add during the commit phase,
|
|
257
267
|
// So they won't leak if render is interrupted or errors.
|
|
258
|
-
resolver.setCallback(this._handleFragmentDataUpdate);
|
|
268
|
+
resolver.setCallback(this.props, this._handleFragmentDataUpdate);
|
|
259
269
|
|
|
260
270
|
// External values could change between render and commit.
|
|
261
271
|
// Check for this case, even though it requires an extra store read.
|
|
262
|
-
const maybeNewData = resolver.resolve();
|
|
263
272
|
if (data !== maybeNewData) {
|
|
264
273
|
this.setState({data: maybeNewData});
|
|
265
274
|
}
|
|
@@ -321,11 +330,9 @@ function createContainerWithFragments<
|
|
|
321
330
|
typeof refetchVariables === 'function'
|
|
322
331
|
? refetchVariables(this._getFragmentVariables())
|
|
323
332
|
: refetchVariables;
|
|
324
|
-
// $FlowFixMe[cannot-spread-interface]
|
|
325
333
|
fetchVariables = {...rootVariables, ...fetchVariables};
|
|
326
334
|
const fragmentVariables = renderVariables
|
|
327
|
-
?
|
|
328
|
-
{...fetchVariables, ...renderVariables}
|
|
335
|
+
? {...fetchVariables, ...renderVariables}
|
|
329
336
|
: fetchVariables;
|
|
330
337
|
|
|
331
338
|
const cacheConfig: ?CacheConfig = options
|
|
@@ -441,12 +448,8 @@ function createContainerWithFragments<
|
|
|
441
448
|
};
|
|
442
449
|
|
|
443
450
|
render() {
|
|
444
|
-
const {
|
|
445
|
-
|
|
446
|
-
__relayContext,
|
|
447
|
-
__rootIsQueryRenderer,
|
|
448
|
-
...props
|
|
449
|
-
} = this.props;
|
|
451
|
+
const {componentRef, __relayContext, __rootIsQueryRenderer, ...props} =
|
|
452
|
+
this.props;
|
|
450
453
|
const {relayProp, contextForChildren} = this.state;
|
|
451
454
|
return (
|
|
452
455
|
<ReactRelayContext.Provider value={contextForChildren}>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright (c)
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
@@ -12,16 +12,6 @@
|
|
|
12
12
|
|
|
13
13
|
'use strict';
|
|
14
14
|
|
|
15
|
-
const areEqual = require('areEqual');
|
|
16
|
-
const invariant = require('invariant');
|
|
17
|
-
const warning = require('warning');
|
|
18
|
-
|
|
19
|
-
const {
|
|
20
|
-
createOperationDescriptor,
|
|
21
|
-
isRelayModernEnvironment,
|
|
22
|
-
Network,
|
|
23
|
-
} = require('relay-runtime');
|
|
24
|
-
|
|
25
15
|
import type {
|
|
26
16
|
CacheConfig,
|
|
27
17
|
ConcreteRequest,
|
|
@@ -32,6 +22,15 @@ import type {
|
|
|
32
22
|
Variables,
|
|
33
23
|
} from 'relay-runtime';
|
|
34
24
|
|
|
25
|
+
const areEqual = require('areEqual');
|
|
26
|
+
const invariant = require('invariant');
|
|
27
|
+
const {
|
|
28
|
+
Network,
|
|
29
|
+
createOperationDescriptor,
|
|
30
|
+
isRelayModernEnvironment,
|
|
31
|
+
} = require('relay-runtime');
|
|
32
|
+
const warning = require('warning');
|
|
33
|
+
|
|
35
34
|
export type DataWriteConfig = {
|
|
36
35
|
query: ConcreteRequest,
|
|
37
36
|
variables: Variables,
|
|
@@ -66,7 +65,7 @@ let nextId = 0;
|
|
|
66
65
|
|
|
67
66
|
class ReactRelayTestMocker {
|
|
68
67
|
_environment: IEnvironment;
|
|
69
|
-
_defaults: {[string]:
|
|
68
|
+
_defaults: {[string]: NetworkWriteConfig['payload'], ...} = {};
|
|
70
69
|
_pendingFetches: Array<PendingFetch> = [];
|
|
71
70
|
|
|
72
71
|
constructor(env: IEnvironment) {
|
|
@@ -118,7 +117,6 @@ class ReactRelayTestMocker {
|
|
|
118
117
|
* annoying to test (e.g. client_mutation_id, actor_id)
|
|
119
118
|
*/
|
|
120
119
|
static stripUnused(variables: Variables): Variables {
|
|
121
|
-
// $FlowFixMe[prop-missing]
|
|
122
120
|
if (variables.input) {
|
|
123
121
|
const toRemove = [
|
|
124
122
|
'client_mutation_id',
|
|
@@ -126,7 +124,6 @@ class ReactRelayTestMocker {
|
|
|
126
124
|
'clientMutationId',
|
|
127
125
|
'actorId',
|
|
128
126
|
];
|
|
129
|
-
// $FlowFixMe[cannot-spread-interface]
|
|
130
127
|
const strippedVariables = {...variables, input: {...variables.input}};
|
|
131
128
|
toRemove.forEach(item => (strippedVariables.input[item] = undefined));
|
|
132
129
|
return strippedVariables;
|
|
@@ -143,7 +140,11 @@ class ReactRelayTestMocker {
|
|
|
143
140
|
* their components behave under error conditions.
|
|
144
141
|
*/
|
|
145
142
|
_mockNetworkLayer(env: IEnvironment): IEnvironment {
|
|
146
|
-
const fetch = (
|
|
143
|
+
const fetch = (
|
|
144
|
+
request: RequestParameters,
|
|
145
|
+
variables: Variables,
|
|
146
|
+
cacheConfig: CacheConfig,
|
|
147
|
+
) => {
|
|
147
148
|
let resolve;
|
|
148
149
|
let reject;
|
|
149
150
|
const promise = new Promise((res, rej) => {
|
|
@@ -314,6 +315,7 @@ class ReactRelayTestMocker {
|
|
|
314
315
|
);
|
|
315
316
|
|
|
316
317
|
const realPayload =
|
|
318
|
+
// $FlowFixMe[incompatible-call]
|
|
317
319
|
typeof payload === 'function' ? payload(toResolve.variables) : payload;
|
|
318
320
|
|
|
319
321
|
// if there are errors, reject the query
|
package/ReactRelayTypes.js.flow
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright (c)
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
import type {
|
|
16
16
|
Disposable,
|
|
17
|
-
|
|
17
|
+
FragmentType,
|
|
18
18
|
GraphQLTaggedNode,
|
|
19
19
|
IEnvironment,
|
|
20
20
|
Observer,
|
|
@@ -94,7 +94,7 @@ export type RefetchOptions = {|
|
|
|
94
94
|
*
|
|
95
95
|
*/
|
|
96
96
|
export type $FragmentRef<T> = {
|
|
97
|
-
+$
|
|
97
|
+
+$fragmentSpreads: T['$fragmentType'],
|
|
98
98
|
...
|
|
99
99
|
};
|
|
100
100
|
|
|
@@ -105,14 +105,14 @@ export type $FragmentRef<T> = {
|
|
|
105
105
|
// prettier-ignore
|
|
106
106
|
export type $RelayProps<Props, RelayPropT = RelayProp> = $ObjMap<
|
|
107
107
|
$Diff<Props, { relay: RelayPropT | void, ... }>,
|
|
108
|
-
& (<T: { +$
|
|
109
|
-
& (<T: { +$
|
|
110
|
-
& (<
|
|
111
|
-
& (<
|
|
112
|
-
& (<
|
|
113
|
-
& (<
|
|
114
|
-
& (<
|
|
115
|
-
& (<
|
|
108
|
+
& (<T: { +$fragmentType: empty, ... }>( T) => T)
|
|
109
|
+
& (<T: { +$fragmentType: empty, ... }>(?T) => ?T)
|
|
110
|
+
& (<TFragmentType: FragmentType, T: { +$fragmentType: TFragmentType, ... }>( T ) => $FragmentRef<T> )
|
|
111
|
+
& (<TFragmentType: FragmentType, T: { +$fragmentType: TFragmentType, ... }>(? T ) => ? $FragmentRef<T> )
|
|
112
|
+
& (<TFragmentType: FragmentType, T: { +$fragmentType: TFragmentType, ... }>( $ReadOnlyArray< T>) => $ReadOnlyArray< $FragmentRef<T>>)
|
|
113
|
+
& (<TFragmentType: FragmentType, T: { +$fragmentType: TFragmentType, ... }>(?$ReadOnlyArray< T>) => ?$ReadOnlyArray< $FragmentRef<T>>)
|
|
114
|
+
& (<TFragmentType: FragmentType, T: { +$fragmentType: TFragmentType, ... }>( $ReadOnlyArray<?T>) => $ReadOnlyArray<?$FragmentRef<T>>)
|
|
115
|
+
& (<TFragmentType: FragmentType, T: { +$fragmentType: TFragmentType, ... }>(?$ReadOnlyArray<?T>) => ?$ReadOnlyArray<?$FragmentRef<T>>)
|
|
116
116
|
& (<T>(T) => T),
|
|
117
117
|
>;
|
|
118
118
|
|
package/RelayContext.js.flow
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright (c)
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
@@ -12,11 +12,11 @@
|
|
|
12
12
|
|
|
13
13
|
'use strict';
|
|
14
14
|
|
|
15
|
-
const invariant = require('invariant');
|
|
16
|
-
const isRelayEnvironment = require('./isRelayEnvironment');
|
|
17
|
-
|
|
18
15
|
import type {RelayContext} from 'relay-runtime';
|
|
19
16
|
|
|
17
|
+
const isRelayEnvironment = require('./isRelayEnvironment');
|
|
18
|
+
const invariant = require('invariant');
|
|
19
|
+
|
|
20
20
|
/**
|
|
21
21
|
* Asserts that the input is a matches the `RelayContext` type defined in
|
|
22
22
|
* `RelayEnvironmentTypes` and returns it as that type.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright (c)
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
@@ -12,11 +12,10 @@
|
|
|
12
12
|
|
|
13
13
|
'use strict';
|
|
14
14
|
|
|
15
|
-
const React = require('react');
|
|
16
|
-
|
|
17
15
|
const {
|
|
18
16
|
createContainer: createFragmentContainer,
|
|
19
17
|
} = require('../ReactRelayFragmentContainer');
|
|
18
|
+
const React = require('react');
|
|
20
19
|
const {graphql} = require('relay-runtime');
|
|
21
20
|
|
|
22
21
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright (c)
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
@@ -12,11 +12,10 @@
|
|
|
12
12
|
|
|
13
13
|
'use strict';
|
|
14
14
|
|
|
15
|
-
const React = require('react');
|
|
16
|
-
|
|
17
15
|
const {
|
|
18
16
|
createContainer: createPaginationContainer,
|
|
19
17
|
} = require('../ReactRelayPaginationContainer');
|
|
18
|
+
const React = require('react');
|
|
20
19
|
const {graphql} = require('relay-runtime');
|
|
21
20
|
|
|
22
21
|
/**
|
|
@@ -63,10 +62,15 @@ const Foo = createPaginationContainer(
|
|
|
63
62
|
{
|
|
64
63
|
viewer: graphql`
|
|
65
64
|
fragment ReactRelayPaginationContainerFlowtest_viewer on Viewer {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
65
|
+
account_user {
|
|
66
|
+
friends(after: $cursor, first: $count)
|
|
67
|
+
@connection(
|
|
68
|
+
key: "ReactRelayPaginationContainerFlowtest_viewer__friends"
|
|
69
|
+
) {
|
|
70
|
+
edges {
|
|
71
|
+
node {
|
|
72
|
+
__typename
|
|
73
|
+
}
|
|
70
74
|
}
|
|
71
75
|
}
|
|
72
76
|
}
|
|
@@ -75,7 +79,7 @@ const Foo = createPaginationContainer(
|
|
|
75
79
|
},
|
|
76
80
|
{
|
|
77
81
|
direction: 'forward',
|
|
78
|
-
getConnectionFromProps: props => props.viewer.
|
|
82
|
+
getConnectionFromProps: props => props.viewer.account_user.friends,
|
|
79
83
|
// $FlowFixMe[cannot-spread-interface]
|
|
80
84
|
getFragmentVariables: (vars, totalCount) => ({
|
|
81
85
|
...vars,
|