relay-runtime 20.1.1 → 21.0.1
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/experimental.d.ts +34 -0
- package/experimental.js +1 -1
- package/experimental.js.flow +11 -11
- package/handlers/RelayDefaultHandlerProvider.d.ts +12 -0
- package/handlers/connection/ConnectionHandler.d.ts +51 -0
- package/handlers/connection/ConnectionHandler.js.flow +5 -5
- package/handlers/connection/ConnectionInterface.d.ts +40 -0
- package/handlers/connection/ConnectionInterface.js.flow +1 -1
- package/handlers/connection/MutationHandlers.d.ts +17 -0
- package/index.d.ts +274 -0
- package/index.js +1 -1
- package/index.js.flow +125 -62
- package/lib/experimental.js +3 -3
- package/lib/index.js +105 -57
- package/lib/multi-actor-environment/ActorIdentifier.js +2 -2
- package/lib/multi-actor-environment/MultiActorEnvironment.js +3 -1
- package/lib/mutations/commitMutation.js +8 -8
- package/lib/mutations/validateMutation.js +4 -4
- package/lib/query/GraphQLTag.js +3 -3
- package/lib/query/fetchQuery.js +15 -3
- package/lib/store/DataChecker.js +38 -4
- package/lib/store/NormalizationEngine.js +373 -0
- package/lib/store/OperationExecutor.js +172 -113
- package/lib/store/RelayConcreteVariables.js +1 -1
- package/lib/store/RelayErrorTrie.js +2 -2
- package/lib/store/RelayExperimentalGraphResponseTransform.js +8 -8
- package/lib/store/RelayModernEnvironment.js +26 -19
- package/lib/store/RelayModernRecord.js +18 -8
- package/lib/store/RelayModernSelector.js +9 -9
- package/lib/store/RelayModernStore.js +152 -43
- package/lib/store/RelayPublishQueue.js +1 -1
- package/lib/store/RelayReader.js +76 -38
- package/lib/store/RelayRecordSource.js +6 -0
- package/lib/store/RelayReferenceMarker.js +2 -1
- package/lib/store/RelayResponseNormalizer.js +88 -55
- package/lib/store/RelayStoreSubscriptions.js +34 -10
- package/lib/store/RelayStoreUtils.js +8 -1
- package/lib/store/ResolverFragments.js +2 -2
- package/lib/store/live-resolvers/LiveResolverCache.js +25 -9
- package/lib/store/observeFragmentExperimental.js +17 -1
- package/lib/store/observeQueryExperimental.js +2 -2
- package/lib/subscription/requestSubscription.js +3 -3
- package/lib/util/RelayError.js +3 -0
- package/lib/util/RelayFeatureFlags.js +6 -2
- package/lib/util/RelayReplaySubject.js +4 -4
- package/lib/util/handlePotentialSnapshotErrors.js +2 -2
- package/lib/util/stableCopy.js +2 -2
- package/llm-docs/api-reference/entrypoint-apis/entrypoint-container.mdx +38 -0
- package/llm-docs/api-reference/entrypoint-apis/load-entrypoint.mdx +77 -0
- package/llm-docs/api-reference/entrypoint-apis/use-entrypoint-loader.mdx +99 -0
- package/llm-docs/api-reference/graphql/graphql-directives.mdx +378 -0
- package/llm-docs/api-reference/hooks/_use-lazy-load-query-extra.mdx +16 -0
- package/llm-docs/api-reference/hooks/load-query.mdx +84 -0
- package/llm-docs/api-reference/hooks/relay-environment-provider.mdx +78 -0
- package/llm-docs/api-reference/hooks/use-client-query.mdx +65 -0
- package/llm-docs/api-reference/hooks/use-fragment.mdx +69 -0
- package/llm-docs/api-reference/hooks/use-lazy-load-query.mdx +62 -0
- package/llm-docs/api-reference/hooks/use-mutation.mdx +94 -0
- package/llm-docs/api-reference/hooks/use-pagination-fragment.mdx +166 -0
- package/llm-docs/api-reference/hooks/use-prefetchable-forward-pagination-fragment.mdx +134 -0
- package/llm-docs/api-reference/hooks/use-preloaded-query.mdx +84 -0
- package/llm-docs/api-reference/hooks/use-query-loader.mdx +95 -0
- package/llm-docs/api-reference/hooks/use-refetchable-fragment.mdx +122 -0
- package/llm-docs/api-reference/hooks/use-relay-environment.mdx +37 -0
- package/llm-docs/api-reference/hooks/use-subscription.mdx +66 -0
- package/llm-docs/api-reference/relay-resolvers/docblock-format.mdx +321 -0
- package/llm-docs/api-reference/relay-resolvers/runtime-functions.mdx +94 -0
- package/llm-docs/api-reference/relay-runtime/commit-mutation.mdx +65 -0
- package/llm-docs/api-reference/relay-runtime/fetch-query.mdx +118 -0
- package/llm-docs/api-reference/relay-runtime/field-logger.mdx +170 -0
- package/llm-docs/api-reference/relay-runtime/observe-fragment.mdx +92 -0
- package/llm-docs/api-reference/relay-runtime/relay-environment.mdx +53 -0
- package/llm-docs/api-reference/relay-runtime/request-subscription.mdx +54 -0
- package/llm-docs/api-reference/relay-runtime/runtime-configuration.mdx +52 -0
- package/llm-docs/api-reference/relay-runtime/store.mdx +734 -0
- package/llm-docs/api-reference/relay-runtime/wait-for-fragment-data.mdx +89 -0
- package/llm-docs/api-reference/types/CacheConfig.mdx +8 -0
- package/llm-docs/api-reference/types/Disposable.mdx +4 -0
- package/llm-docs/api-reference/types/GraphQLSubscriptionConfig.mdx +17 -0
- package/llm-docs/api-reference/types/MutationConfig.mdx +31 -0
- package/llm-docs/api-reference/types/SelectorStoreUpdater.mdx +6 -0
- package/llm-docs/api-reference/types/UploadableMap.mdx +3 -0
- package/llm-docs/community/learning-resources.mdx +64 -0
- package/llm-docs/debugging/declarative-mutation-directives.mdx +34 -0
- package/llm-docs/debugging/disallowed-id-types-error.mdx +43 -0
- package/llm-docs/debugging/inconsistent-typename-error.mdx +47 -0
- package/llm-docs/debugging/relay-devtools.mdx +73 -0
- package/llm-docs/debugging/why-null.mdx +116 -0
- package/llm-docs/editor-support.mdx +55 -0
- package/llm-docs/error-reference/unknown-field.mdx +36 -0
- package/llm-docs/getting-started/babel-plugin.mdx +31 -0
- package/llm-docs/getting-started/compiler-config.mdx +25 -0
- package/llm-docs/getting-started/compiler.mdx +98 -0
- package/llm-docs/getting-started/lint-rules.mdx +87 -0
- package/llm-docs/getting-started/production.mdx +30 -0
- package/llm-docs/getting-started/quick-start.mdx +216 -0
- package/llm-docs/glossary/glossary.mdx +1040 -0
- package/llm-docs/guided-tour/list-data/advanced-pagination.mdx +157 -0
- package/llm-docs/guided-tour/list-data/connections.mdx +81 -0
- package/llm-docs/guided-tour/list-data/pagination.mdx +193 -0
- package/llm-docs/guided-tour/list-data/rendering-connections.mdx +112 -0
- package/llm-docs/guided-tour/list-data/streaming-pagination.mdx +87 -0
- package/llm-docs/guided-tour/managing-data-outside-react/retaining-queries.mdx +51 -0
- package/llm-docs/guided-tour/refetching/refetching-queries-with-different-data.mdx +337 -0
- package/llm-docs/guided-tour/refetching/refreshing-queries.mdx +350 -0
- package/llm-docs/guided-tour/rendering/environment.mdx +59 -0
- package/llm-docs/guided-tour/rendering/error-states.mdx +295 -0
- package/llm-docs/guided-tour/rendering/fragments.mdx +354 -0
- package/llm-docs/guided-tour/rendering/loading-states.mdx +245 -0
- package/llm-docs/guided-tour/rendering/queries.mdx +261 -0
- package/llm-docs/guided-tour/rendering/variables.mdx +233 -0
- package/llm-docs/guided-tour/reusing-cached-data/fetch-policies.mdx +56 -0
- package/llm-docs/guided-tour/reusing-cached-data/filling-in-missing-data.mdx +102 -0
- package/llm-docs/guided-tour/reusing-cached-data/introduction.mdx +22 -0
- package/llm-docs/guided-tour/reusing-cached-data/presence-of-data.mdx +93 -0
- package/llm-docs/guided-tour/reusing-cached-data/rendering-partially-cached-data.mdx +175 -0
- package/llm-docs/guided-tour/reusing-cached-data/staleness-of-data.mdx +116 -0
- package/llm-docs/guided-tour/updating-data/client-only-data.mdx +115 -0
- package/llm-docs/guided-tour/updating-data/graphql-mutations.mdx +334 -0
- package/llm-docs/guided-tour/updating-data/graphql-subscriptions.mdx +279 -0
- package/llm-docs/guided-tour/updating-data/imperatively-modifying-linked-fields.mdx +511 -0
- package/llm-docs/guided-tour/updating-data/imperatively-modifying-store-data-legacy.mdx +142 -0
- package/llm-docs/guided-tour/updating-data/imperatively-modifying-store-data.mdx +275 -0
- package/llm-docs/guided-tour/updating-data/introduction.mdx +25 -0
- package/llm-docs/guided-tour/updating-data/local-data-updates.mdx +71 -0
- package/llm-docs/guided-tour/updating-data/typesafe-updaters-faq.mdx +83 -0
- package/llm-docs/guided-tour/updating-data/updating-connections.mdx +592 -0
- package/llm-docs/guides/alias-directive.mdx +160 -0
- package/llm-docs/guides/catch-directive.mdx +167 -0
- package/llm-docs/guides/client-schema-extensions.mdx +208 -0
- package/llm-docs/guides/codemods.mdx +79 -0
- package/llm-docs/guides/data-driven-dependencies/client-3d.mdx +255 -0
- package/llm-docs/guides/data-driven-dependencies/configuration.mdx +127 -0
- package/llm-docs/guides/data-driven-dependencies/introduction.mdx +39 -0
- package/llm-docs/guides/data-driven-dependencies/server-3d.mdx +664 -0
- package/llm-docs/guides/document-comparison.mdx +106 -0
- package/llm-docs/guides/graphql-server-specification.mdx +453 -0
- package/llm-docs/guides/network-layer.mdx +69 -0
- package/llm-docs/guides/persisted-queries.mdx +328 -0
- package/llm-docs/guides/relay-resolvers/context.mdx +99 -0
- package/llm-docs/guides/relay-resolvers/defining-fields.mdx +151 -0
- package/llm-docs/guides/relay-resolvers/defining-types.mdx +164 -0
- package/llm-docs/guides/relay-resolvers/deprecated.mdx +27 -0
- package/llm-docs/guides/relay-resolvers/derived-fields.mdx +127 -0
- package/llm-docs/guides/relay-resolvers/descriptions.mdx +44 -0
- package/llm-docs/guides/relay-resolvers/enabling.mdx +41 -0
- package/llm-docs/guides/relay-resolvers/errors.mdx +64 -0
- package/llm-docs/guides/relay-resolvers/field-arguments.mdx +63 -0
- package/llm-docs/guides/relay-resolvers/introduction.mdx +62 -0
- package/llm-docs/guides/relay-resolvers/limitations.mdx +30 -0
- package/llm-docs/guides/relay-resolvers/live-fields.mdx +164 -0
- package/llm-docs/guides/relay-resolvers/return-types.mdx +161 -0
- package/llm-docs/guides/relay-resolvers/suspense.mdx +41 -0
- package/llm-docs/guides/required-directive.mdx +240 -0
- package/llm-docs/guides/semantic-nullability.mdx +93 -0
- package/llm-docs/guides/testing-relay-components.mdx +642 -0
- package/llm-docs/guides/testing-relay-with-preloaded-queries.mdx +160 -0
- package/llm-docs/guides/throw-on-field-error-directive.mdx +58 -0
- package/llm-docs/guides/type-emission.mdx +414 -0
- package/llm-docs/home.mdx +32 -0
- package/llm-docs/principles-and-architecture/architecture-overview.mdx +24 -0
- package/llm-docs/principles-and-architecture/compiler-architecture.mdx +106 -0
- package/llm-docs/principles-and-architecture/runtime-architecture.mdx +249 -0
- package/llm-docs/principles-and-architecture/thinking-in-graphql.mdx +309 -0
- package/llm-docs/principles-and-architecture/thinking-in-relay.mdx +104 -0
- package/llm-docs/principles-and-architecture/videos.mdx +50 -0
- package/llm-docs/tutorial/arrays-lists.mdx +126 -0
- package/llm-docs/tutorial/fragments-1.mdx +487 -0
- package/llm-docs/tutorial/graphql.mdx +172 -0
- package/llm-docs/tutorial/interfaces-polymorphism.mdx +161 -0
- package/llm-docs/tutorial/intro.mdx +58 -0
- package/llm-docs/tutorial/mutations-updates.mdx +624 -0
- package/llm-docs/tutorial/organizing-mutations-queries-and-subscriptions.mdx +13 -0
- package/llm-docs/tutorial/queries-1.mdx +267 -0
- package/llm-docs/tutorial/queries-2.mdx +389 -0
- package/llm-docs/tutorial/refetchable-fragments.mdx +352 -0
- package/multi-actor-environment/ActorIdentifier.d.ts +17 -0
- package/multi-actor-environment/ActorIdentifier.js.flow +2 -2
- package/multi-actor-environment/ActorSpecificEnvironment.js.flow +15 -15
- package/multi-actor-environment/ActorUtils.js.flow +1 -1
- package/multi-actor-environment/MultiActorEnvironment.d.ts +123 -0
- package/multi-actor-environment/MultiActorEnvironment.js.flow +32 -24
- package/multi-actor-environment/MultiActorEnvironmentTypes.d.ts +225 -0
- package/multi-actor-environment/MultiActorEnvironmentTypes.js.flow +6 -6
- package/multi-actor-environment/index.d.ts +14 -0
- package/multi-actor-environment.d.ts +8 -0
- package/mutations/RelayDeclarativeMutationConfig.d.ts +70 -0
- package/mutations/RelayDeclarativeMutationConfig.js.flow +9 -9
- package/mutations/RelayRecordProxy.js.flow +8 -11
- package/mutations/RelayRecordSourceMutator.js.flow +4 -4
- package/mutations/RelayRecordSourceProxy.js.flow +4 -4
- package/mutations/RelayRecordSourceSelectorProxy.js.flow +6 -6
- package/mutations/applyOptimisticMutation.d.ts +25 -0
- package/mutations/applyOptimisticMutation.js.flow +2 -2
- package/mutations/commitLocalUpdate.d.ts +10 -0
- package/mutations/commitMutation.d.ts +48 -0
- package/mutations/commitMutation.js.flow +21 -17
- package/mutations/createUpdatableProxy.js.flow +19 -19
- package/mutations/readUpdatableFragment.js.flow +3 -3
- package/mutations/readUpdatableQuery.js.flow +3 -3
- package/mutations/validateMutation.js.flow +7 -7
- package/network/RelayNetwork.d.ts +12 -0
- package/network/RelayNetworkTypes.d.ts +145 -0
- package/network/RelayNetworkTypes.js.flow +18 -18
- package/network/RelayObservable.d.ts +197 -0
- package/network/RelayObservable.js.flow +32 -30
- package/network/RelayQueryResponseCache.d.ts +16 -0
- package/network/RelayQueryResponseCache.js.flow +3 -3
- package/network/wrapNetworkWithLogObserver.js.flow +1 -1
- package/package.json +2 -1
- package/query/GraphQLTag.d.ts +45 -0
- package/query/GraphQLTag.js.flow +22 -10
- package/query/fetchQuery.d.ts +21 -0
- package/query/fetchQuery.js.flow +23 -10
- package/query/fetchQueryInternal.d.ts +26 -0
- package/query/fetchQueryInternal.js.flow +4 -4
- package/query/fetchQuery_DEPRECATED.d.ts +17 -0
- package/query/fetchQuery_DEPRECATED.js.flow +1 -1
- package/store/ClientID.d.ts +14 -0
- package/store/DataChecker.js.flow +51 -15
- package/store/NormalizationEngine.js.flow +782 -0
- package/store/OperationExecutor.d.ts +51 -0
- package/store/OperationExecutor.js.flow +204 -98
- package/store/RelayConcreteVariables.js.flow +5 -5
- package/store/RelayErrorTrie.js.flow +12 -12
- package/store/RelayExperimentalGraphResponseHandler.js.flow +3 -3
- package/store/RelayExperimentalGraphResponseTransform.js.flow +10 -10
- package/store/RelayModernEnvironment.d.ts +97 -0
- package/store/RelayModernEnvironment.js.flow +58 -43
- package/store/RelayModernFragmentSpecResolver.js.flow +1 -1
- package/store/RelayModernOperationDescriptor.d.ts +28 -0
- package/store/RelayModernOperationDescriptor.js.flow +1 -1
- package/store/RelayModernRecord.d.ts +92 -0
- package/store/RelayModernRecord.js.flow +44 -20
- package/store/RelayModernSelector.d.ts +123 -0
- package/store/RelayModernSelector.js.flow +21 -21
- package/store/RelayModernStore.d.ts +57 -0
- package/store/RelayModernStore.js.flow +219 -58
- package/store/RelayOperationTracker.d.ts +29 -0
- package/store/RelayOperationTracker.js.flow +2 -2
- package/store/RelayOptimisticRecordSource.js.flow +2 -2
- package/store/RelayPublishQueue.js.flow +29 -20
- package/store/RelayReader.js.flow +129 -57
- package/store/RelayRecordSource.d.ts +26 -0
- package/store/RelayRecordSource.js.flow +10 -0
- package/store/RelayRecordState.d.ts +28 -0
- package/store/RelayRecordState.js.flow +1 -1
- package/store/RelayReferenceMarker.js.flow +5 -4
- package/store/RelayResponseNormalizer.d.ts +28 -0
- package/store/RelayResponseNormalizer.js.flow +130 -62
- package/store/RelayStoreSubscriptions.js.flow +52 -8
- package/store/RelayStoreTypes.d.ts +1327 -0
- package/store/RelayStoreTypes.js.flow +371 -278
- package/store/RelayStoreUtils.d.ts +86 -0
- package/store/RelayStoreUtils.js.flow +16 -8
- package/store/ResolverCache.js.flow +2 -2
- package/store/ResolverFragments.d.ts +43 -0
- package/store/ResolverFragments.js.flow +22 -14
- package/store/StoreInspector.js.flow +7 -8
- package/store/ViewerPattern.d.ts +11 -0
- package/store/cloneRelayHandleSourceField.js.flow +1 -1
- package/store/cloneRelayScalarHandleSourceField.js.flow +1 -1
- package/store/createFragmentSpecResolver.d.ts +16 -0
- package/store/createRelayContext.js.flow +1 -1
- package/store/createRelayLoggingContext.js.flow +4 -4
- package/store/defaultGetDataID.js.flow +2 -2
- package/store/isRelayModernEnvironment.d.ts +8 -0
- package/store/isRelayModernEnvironment.js.flow +4 -2
- package/store/live-resolvers/LiveResolverCache.js.flow +55 -20
- package/store/live-resolvers/LiveResolverSuspenseSentinel.js.flow +3 -3
- package/store/live-resolvers/getOutputTypeRecordIDs.js.flow +1 -1
- package/store/live-resolvers/isLiveStateValue.js.flow +2 -2
- package/store/live-resolvers/resolverDataInjector.d.ts +27 -0
- package/store/live-resolvers/resolverDataInjector.js.flow +8 -5
- package/store/observeFragmentExperimental.d.ts +46 -0
- package/store/observeFragmentExperimental.js.flow +50 -21
- package/store/observeQueryExperimental.d.ts +30 -0
- package/store/observeQueryExperimental.js.flow +5 -5
- package/store/readInlineData.d.ts +19 -0
- package/store/readInlineData.js.flow +5 -5
- package/store/waitForFragmentExperimental.d.ts +49 -0
- package/store/waitForFragmentExperimental.js.flow +3 -3
- package/subscription/requestSubscription.d.ts +27 -0
- package/subscription/requestSubscription.js.flow +10 -10
- package/util/JSResourceTypes.flow.js.flow +4 -4
- package/util/NormalizationNode.d.ts +235 -0
- package/util/NormalizationNode.js.flow +127 -123
- package/util/ReaderNode.d.ts +264 -0
- package/util/ReaderNode.js.flow +156 -151
- package/util/RelayConcreteNode.d.ts +120 -0
- package/util/RelayConcreteNode.js.flow +32 -32
- package/util/RelayError.d.ts +13 -0
- package/util/RelayError.js.flow +4 -1
- package/util/RelayFeatureFlags.d.ts +40 -0
- package/util/RelayFeatureFlags.js.flow +21 -1
- package/util/RelayProfiler.d.ts +121 -0
- package/util/RelayProfiler.js.flow +1 -1
- package/util/RelayReplaySubject.d.ts +25 -0
- package/util/RelayReplaySubject.js.flow +3 -3
- package/util/RelayRuntimeTypes.d.ts +59 -0
- package/util/RelayRuntimeTypes.js.flow +36 -33
- package/util/createPayloadFor3DField.d.ts +17 -0
- package/util/createPayloadFor3DField.js.flow +9 -5
- package/util/deepFreeze.d.ts +8 -0
- package/util/deepFreeze.js.flow +2 -2
- package/util/getFragmentIdentifier.d.ts +10 -0
- package/util/getFragmentIdentifier.js.flow +1 -1
- package/util/getPaginationMetadata.d.ts +20 -0
- package/util/getPaginationMetadata.js.flow +1 -1
- package/util/getPaginationVariables.d.ts +20 -0
- package/util/getPaginationVariables.js.flow +1 -1
- package/util/getPendingOperationsForFragment.d.ts +18 -0
- package/util/getPendingOperationsForFragment.js.flow +2 -2
- package/util/getRefetchMetadata.d.ts +19 -0
- package/util/getRefetchMetadata.js.flow +6 -5
- package/util/getRelayHandleKey.d.ts +8 -0
- package/util/getRequestIdentifier.d.ts +17 -0
- package/util/getValueAtPath.d.ts +8 -0
- package/util/getValueAtPath.js.flow +3 -3
- package/util/handlePotentialSnapshotErrors.d.ts +14 -0
- package/util/handlePotentialSnapshotErrors.js.flow +5 -5
- package/util/isEmptyObject.js.flow +1 -1
- package/util/isPromise.d.ts +8 -0
- package/util/isPromise.js.flow +2 -2
- package/util/isScalarAndEqual.d.ts +8 -0
- package/util/isScalarAndEqual.js.flow +1 -1
- package/util/recycleNodesInto.d.ts +8 -0
- package/util/recycleNodesInto.js.flow +2 -2
- package/util/registerEnvironmentWithDevTools.js.flow +1 -1
- package/util/shallowFreeze.js.flow +1 -1
- package/util/stableCopy.d.ts +8 -0
- package/util/stableCopy.js.flow +5 -5
- package/util/withProvidedVariables.d.ts +19 -0
- package/util/withProvidedVariables.js.flow +14 -10
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: refetching-queries-with-different-data
|
|
3
|
+
title: Refetching Queries with Different Data
|
|
4
|
+
slug: /guided-tour/refetching/refetching-queries-with-different-data/
|
|
5
|
+
description: Relay guide to refetching queries with different data
|
|
6
|
+
keywords:
|
|
7
|
+
- refetching
|
|
8
|
+
- query
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
import DocsRating from '@site/src/core/DocsRating';
|
|
12
|
+
import {OssOnly, FbInternalOnly} from 'docusaurus-plugin-internaldocs-fb/internal';
|
|
13
|
+
// @fb-only
|
|
14
|
+
// @fb-only
|
|
15
|
+
// @fb-only
|
|
16
|
+
|
|
17
|
+
When referring to **"refetching a query"**, we mean fetching the query again for *different* data than was originally rendered by the query. For example, this might be to change a currently selected item, to render a different list of items than the one being shown, or more generally to transition the currently rendered content to show new or different content.
|
|
18
|
+
|
|
19
|
+
## When using `useQueryLoader` / `loadQuery`
|
|
20
|
+
|
|
21
|
+
Similarly to [Refreshing Queries with `useQueryLoader`](../refreshing-queries/#when-using-usequeryloader--loadquery), we can also use the `useQueryLoader` Hook described in our [Fetching Queries for Render](../../rendering/queries/#fetching-queries-for-render) section, but this time passing *different query variables*:
|
|
22
|
+
|
|
23
|
+
<FbInternalOnly>
|
|
24
|
+
// @fb-only
|
|
25
|
+
</FbInternalOnly>
|
|
26
|
+
|
|
27
|
+
<OssOnly>
|
|
28
|
+
|
|
29
|
+
```js
|
|
30
|
+
/**
|
|
31
|
+
* App.react.js
|
|
32
|
+
*/
|
|
33
|
+
const AppQuery = require('__generated__/AppQuery.graphql');
|
|
34
|
+
|
|
35
|
+
function App(props: Props) {
|
|
36
|
+
const variables = {id: '4'};
|
|
37
|
+
const [queryRef, loadQuery] = useQueryLoader(
|
|
38
|
+
AppQuery,
|
|
39
|
+
props.appQueryRef /* initial query ref */
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
const refetch = useCallback(() => {
|
|
43
|
+
// Load the query again using the same original variables.
|
|
44
|
+
// Calling loadQuery will update the value of queryRef.
|
|
45
|
+
loadQuery({id: 'different-id'});
|
|
46
|
+
}, [/* ... */]);
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<React.Suspense fallback="Loading query...">
|
|
50
|
+
<MainContent
|
|
51
|
+
refetch={refetch}
|
|
52
|
+
queryRef={queryRef}
|
|
53
|
+
/>
|
|
54
|
+
</React.Suspense>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
```js
|
|
60
|
+
/**
|
|
61
|
+
* MainContent.react.js
|
|
62
|
+
*/
|
|
63
|
+
|
|
64
|
+
// Renders the preloaded query, given the query reference
|
|
65
|
+
function MainContent(props) {
|
|
66
|
+
const {refetch, queryRef} = props;
|
|
67
|
+
const data = usePreloadedQuery(
|
|
68
|
+
graphql`
|
|
69
|
+
query AppQuery($id: ID!) {
|
|
70
|
+
user(id: $id) {
|
|
71
|
+
name
|
|
72
|
+
friends {
|
|
73
|
+
count
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
`,
|
|
78
|
+
queryRef,
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
return (
|
|
82
|
+
<>
|
|
83
|
+
<h1>{data.user?.name}</h1>
|
|
84
|
+
<div>Friends count: {data.user?.friends?.count}</div>
|
|
85
|
+
<Button
|
|
86
|
+
onClick={() => refetch()}>
|
|
87
|
+
Fetch latest count
|
|
88
|
+
</Button>
|
|
89
|
+
</>
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Let's distill what's going on here:
|
|
95
|
+
|
|
96
|
+
* We call `loadQuery` in the event handler for refetching, so the network request starts immediately, and then pass the `queryRef` to `usePreloadedQuery`, so it renders the updated data.
|
|
97
|
+
* We are not passing a `fetchPolicy` to `loadQuery`, meaning that it will use the default value of `'store-or-network'`. We could provide a different policy in order to specify whether to use locally cached data (as we covered in [Reusing Cached Data For Render](../../reusing-cached-data/)).
|
|
98
|
+
* Calling `loadQuery` will re-render the component and may cause `usePreloadedQuery` to suspend (as explained in [Loading States with Suspense](../../rendering/loading-states/)). This means that we'll need to make sure that there's a `Suspense` boundary wrapping the `MainContent` component, in order to show a fallback loading state.
|
|
99
|
+
|
|
100
|
+
</OssOnly>
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
### If you need to avoid Suspense
|
|
104
|
+
|
|
105
|
+
In some cases, you might want to avoid showing a Suspense fallback, which would hide the already rendered content. For these cases, you can use [`fetchQuery`](../../../api-reference/fetch-query/) instead, and manually keep track of a loading state:
|
|
106
|
+
|
|
107
|
+
<FbInternalOnly>
|
|
108
|
+
// @fb-only
|
|
109
|
+
</FbInternalOnly>
|
|
110
|
+
|
|
111
|
+
```js
|
|
112
|
+
/**
|
|
113
|
+
* App.react.js
|
|
114
|
+
*/
|
|
115
|
+
const AppQuery = require('__generated__/AppQuery.graphql');
|
|
116
|
+
|
|
117
|
+
function App(props: Props) {
|
|
118
|
+
const environment = useRelayEnvironment();
|
|
119
|
+
const [queryRef, loadQuery] = useQueryLoader(
|
|
120
|
+
AppQuery,
|
|
121
|
+
props.appQueryRef /* initial query ref */
|
|
122
|
+
);
|
|
123
|
+
const [isRefetching, setIsRefetching] = useState(false)
|
|
124
|
+
|
|
125
|
+
const refetch = useCallback(() => {
|
|
126
|
+
if (isRefetching) { return; }
|
|
127
|
+
setIsRefetching(true);
|
|
128
|
+
const variables = { id: 'different-id' };
|
|
129
|
+
|
|
130
|
+
// fetchQuery will fetch the query and write
|
|
131
|
+
// the data to the Relay store. This will ensure
|
|
132
|
+
// that when we re-render, the data is already
|
|
133
|
+
// cached and we don't suspend
|
|
134
|
+
fetchQuery(environment, AppQuery, variables)
|
|
135
|
+
.subscribe({
|
|
136
|
+
complete: () => {
|
|
137
|
+
setIsRefetching(false);
|
|
138
|
+
|
|
139
|
+
// *After* the query has been fetched, we call
|
|
140
|
+
// loadQuery again to re-render with a new
|
|
141
|
+
// queryRef.
|
|
142
|
+
// At this point the data for the query should
|
|
143
|
+
// be cached, so we use the 'store-only'
|
|
144
|
+
// fetchPolicy to avoid suspending.
|
|
145
|
+
loadQuery(variables, {fetchPolicy: 'store-only'});
|
|
146
|
+
},
|
|
147
|
+
error: () => {
|
|
148
|
+
setIsRefetching(false);
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
}, [/* ... */]);
|
|
152
|
+
|
|
153
|
+
return (
|
|
154
|
+
<React.Suspense fallback="Loading query...">
|
|
155
|
+
<MainContent
|
|
156
|
+
isRefetching={isRefetching}
|
|
157
|
+
refetch={refetch}
|
|
158
|
+
queryRef={queryRef}
|
|
159
|
+
/>
|
|
160
|
+
</React.Suspense>
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Let's distill what's going on here:
|
|
166
|
+
|
|
167
|
+
* When refetching, we now keep track of our own `isRefetching` loading state, since we are avoiding suspending. We can use this state to render a busy spinner or similar loading UI inside the `MainContent` component, *without* hiding the `MainContent`.
|
|
168
|
+
* In the event handler, we first call `fetchQuery`, which will fetch the query and write the data to the local Relay store. When the `fetchQuery` network request completes, we call `loadQuery` so that we obtain an updated `queryRef` that we then pass to `usePreloadedQuery` in order render the updated data, similar to the previous example.
|
|
169
|
+
* At this point, when `loadQuery` is called, the data for the query should already be cached in the local Relay store, so we use `fetchPolicy` of `'store-only'` to avoid suspending and only read the already cached data.
|
|
170
|
+
|
|
171
|
+
## When using `useLazyLoadQuery`
|
|
172
|
+
|
|
173
|
+
Similarly to [Refreshing Queries with `useLazyLoadQuery`](../refreshing-queries/#when-using-uselazyloadquery), we can also use the [`useLazyLoadQuery`](../../../api-reference/use-lazy-load-query/) Hook described in our [Lazily Fetching Queries during Render](../../rendering/queries/#lazily-fetching-queries-during-render) section, but this time passing *different query variables*:
|
|
174
|
+
|
|
175
|
+
<FbInternalOnly>
|
|
176
|
+
// @fb-only
|
|
177
|
+
</FbInternalOnly>
|
|
178
|
+
|
|
179
|
+
<OssOnly>
|
|
180
|
+
|
|
181
|
+
```js
|
|
182
|
+
/**
|
|
183
|
+
* App.react.js
|
|
184
|
+
*/
|
|
185
|
+
const AppQuery = require('__generated__/AppQuery.graphql');
|
|
186
|
+
|
|
187
|
+
function App(props: Props) {
|
|
188
|
+
const [queryArgs, setQueryArgs] = useState({
|
|
189
|
+
options: {fetchKey: 0},
|
|
190
|
+
variables: {id: '4'},
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
const refetch = useCallback(() => {
|
|
194
|
+
// Trigger a re-render of useLazyLoadQuery with new variables,
|
|
195
|
+
// *and* an updated fetchKey.
|
|
196
|
+
// The new fetchKey will ensure that the query is fully
|
|
197
|
+
// re-evaluated and refetched.
|
|
198
|
+
setQueryArgs(prev => ({
|
|
199
|
+
options: {
|
|
200
|
+
fetchKey: (prev?.options.fetchKey ?? 0) + 1,
|
|
201
|
+
},
|
|
202
|
+
variables: {id: 'different-id'}
|
|
203
|
+
}));
|
|
204
|
+
}, [/* ... */]);
|
|
205
|
+
|
|
206
|
+
return (
|
|
207
|
+
<React.Suspense fallback="Loading query...">
|
|
208
|
+
<MainContent
|
|
209
|
+
refetch={refetch}
|
|
210
|
+
queryArgs={queryArgs}
|
|
211
|
+
/>
|
|
212
|
+
</React.Suspense>
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
```js
|
|
218
|
+
/**
|
|
219
|
+
* MainContent.react.js
|
|
220
|
+
*/
|
|
221
|
+
// Fetches and renders the query, given the fetch options
|
|
222
|
+
function MainContent(props) {
|
|
223
|
+
const {refetch, queryArgs} = props;
|
|
224
|
+
const data = useLazyLoadQuery(
|
|
225
|
+
graphql`
|
|
226
|
+
query AppQuery($id: ID!) {
|
|
227
|
+
user(id: $id) {
|
|
228
|
+
name
|
|
229
|
+
friends {
|
|
230
|
+
count
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
`,
|
|
235
|
+
queryArgs.variables,
|
|
236
|
+
queryArgs.options,
|
|
237
|
+
);
|
|
238
|
+
|
|
239
|
+
return (
|
|
240
|
+
<>
|
|
241
|
+
<h1>{data.user?.name}</h1>
|
|
242
|
+
<div>Friends count: {data.user.friends?.count}</div>
|
|
243
|
+
<Button
|
|
244
|
+
onClick={() => refetch()}>
|
|
245
|
+
Fetch latest count
|
|
246
|
+
</Button>
|
|
247
|
+
</>
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Let's distill what's going on here:
|
|
253
|
+
|
|
254
|
+
* We update the component in the event handler for refreshing by setting new query args in state. This will cause the `MainContent` component that uses `useLazyLoadQuery` to re-render with the new `variables` and `fetchKey`, and refetch the query upon rendering.
|
|
255
|
+
* We are passing a new value of `fetchKey` which we increment on every update. Passing a new `fetchKey` to `useLazyLoadQuery` on every update will ensure that the query is fully re-evaluated and refetched.
|
|
256
|
+
* We are not passing a new `fetchPolicy` to `useLazyLoadQuery`, meaning that it will use the default value of `'store-or-network'`. We could provide a different policy in order to specify whether to use locally cached data (as we covered in [Reusing Cached Data For Render](../../reusing-cached-data/)).
|
|
257
|
+
* The state update in `refetch` will re-render the component and may cause the component to suspend (as explained in [Loading States with Suspense](../../rendering/loading-states/)). This means that we'll need to make sure that there's a `Suspense` boundary wrapping the `MainContent` component, in order to show a fallback loading state.
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
</OssOnly>
|
|
261
|
+
|
|
262
|
+
### If you need to avoid Suspense
|
|
263
|
+
|
|
264
|
+
In some cases, you might want to avoid showing a Suspense fallback, which would hide the already rendered content. For these cases, you can use [`fetchQuery`](../../../api-reference/fetch-query/) instead, and manually keep track of a loading state:
|
|
265
|
+
|
|
266
|
+
<FbInternalOnly>
|
|
267
|
+
// @fb-only
|
|
268
|
+
</FbInternalOnly>
|
|
269
|
+
|
|
270
|
+
```js
|
|
271
|
+
/**
|
|
272
|
+
* App.react.js
|
|
273
|
+
*/
|
|
274
|
+
const AppQuery = require('__generated__/AppQuery.graphql');
|
|
275
|
+
|
|
276
|
+
function App(props: Props) {
|
|
277
|
+
const environment = useRelayEnvironment();
|
|
278
|
+
const [isRefreshing, setIsRefreshing] = useState(false)
|
|
279
|
+
const [queryArgs, setQueryArgs] = useState({
|
|
280
|
+
options: {fetchKey: 0, fetchPolicy: 'store-or-network'},
|
|
281
|
+
variables: {id: '4'},
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
const refetch = useCallback(() => {
|
|
285
|
+
if (isRefreshing) { return; }
|
|
286
|
+
setIsRefreshing(true);
|
|
287
|
+
const variables = { id: 'different-id' };
|
|
288
|
+
|
|
289
|
+
// fetchQuery will fetch the query and write
|
|
290
|
+
// the data to the Relay store. This will ensure
|
|
291
|
+
// that when we re-render, the data is already
|
|
292
|
+
// cached and we don't suspend
|
|
293
|
+
fetchQuery(environment, AppQuery, variables)
|
|
294
|
+
.subscribe({
|
|
295
|
+
complete: () => {
|
|
296
|
+
setIsRefreshing(false);
|
|
297
|
+
|
|
298
|
+
// *After* the query has been fetched, we update
|
|
299
|
+
// our state to re-render with the new fetchKey
|
|
300
|
+
// and fetchPolicy.
|
|
301
|
+
// At this point the data for the query should
|
|
302
|
+
// be cached, so we use the 'store-only'
|
|
303
|
+
// fetchPolicy to avoid suspending.
|
|
304
|
+
setQueryArgs(prev => ({
|
|
305
|
+
options: {
|
|
306
|
+
fetchKey: (prev?.options.fetchKey ?? 0) + 1,
|
|
307
|
+
fetchPolicy: 'store-only',
|
|
308
|
+
},
|
|
309
|
+
variables,
|
|
310
|
+
}));
|
|
311
|
+
},
|
|
312
|
+
error: () => {
|
|
313
|
+
setIsRefreshing(false);
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
}, [/* ... */]);
|
|
317
|
+
|
|
318
|
+
return (
|
|
319
|
+
<React.Suspense fallback="Loading query...">
|
|
320
|
+
<MainContent
|
|
321
|
+
isRefetching={isRefetching}
|
|
322
|
+
refetch={refetch}
|
|
323
|
+
queryArgs={queryArgs}
|
|
324
|
+
/>
|
|
325
|
+
</React.Suspense>
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
Let's distill what's going on here:
|
|
331
|
+
|
|
332
|
+
* When refetching, we now keep track of our own `isRefetching` loading state, since we are avoiding suspending. We can use this state to render a busy spinner or similar loading UI inside the `MainContent` component, *without* hiding the `MainContent`.
|
|
333
|
+
* In the event handler, we first call `fetchQuery`, which will fetch the query and write the data to the local Relay store. When the `fetchQuery` network request completes, we update our state so that we re-render an updated `fetchKey` and `fetchPolicy` that we then pass to `useLazyLoadQuery` in order render the updated data, similar to the previous example.
|
|
334
|
+
* At this point, when we update the state, the data for the query should already be cached in the local Relay store, so we use `fetchPolicy` of `'store-only'` to avoid suspending and only read the already cached data.
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
<DocsRating />
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: refreshing-queries
|
|
3
|
+
title: Refreshing Queries
|
|
4
|
+
slug: /guided-tour/refetching/refreshing-queries/
|
|
5
|
+
description: Relay guide to refreshing queries
|
|
6
|
+
keywords:
|
|
7
|
+
- refreshing
|
|
8
|
+
- queries
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
import DocsRating from '@site/src/core/DocsRating';
|
|
12
|
+
import {OssOnly, FbInternalOnly} from 'docusaurus-plugin-internaldocs-fb/internal';
|
|
13
|
+
// @fb-only
|
|
14
|
+
// @fb-only
|
|
15
|
+
// @fb-only
|
|
16
|
+
// @fb-only
|
|
17
|
+
|
|
18
|
+
When referring to **"refreshing a query"**, we mean fetching the *exact* same data that was originally rendered by the query, in order to get the most up-to-date version of that data from the server.
|
|
19
|
+
|
|
20
|
+
## Using real-time features
|
|
21
|
+
|
|
22
|
+
<FbInternalOnly>
|
|
23
|
+
// @fb-only
|
|
24
|
+
</FbInternalOnly>
|
|
25
|
+
|
|
26
|
+
<OssOnly>
|
|
27
|
+
|
|
28
|
+
If we want to keep our data up to date with the latest version from the server, the first thing to consider is if it appropriate to use any real-time features, which can make it easier to automatically keep the data up to date without manually refreshing the data periodically.
|
|
29
|
+
|
|
30
|
+
One example of this is using [GraphQL Subscriptions](https://relay.dev/docs/guided-tour/updating-data/graphql-subscriptions), which will require additional configuration on your server and [network layer](https://relay.dev/docs/guided-tour/updating-data/graphql-subscriptions/#configuring-the-network-layer).
|
|
31
|
+
|
|
32
|
+
</OssOnly>
|
|
33
|
+
|
|
34
|
+
## When using `useQueryLoader` / `loadQuery`
|
|
35
|
+
|
|
36
|
+
To refresh a query using the [`useQueryLoader`](../../../api-reference/use-query-loader/) Hook described in our [Fetching Queries for Render](../../rendering/queries/#fetching-queries-for-render) section, we only need to call `loadQuery` again:
|
|
37
|
+
|
|
38
|
+
<FbInternalOnly>
|
|
39
|
+
// @fb-only
|
|
40
|
+
</FbInternalOnly>
|
|
41
|
+
|
|
42
|
+
<OssOnly>
|
|
43
|
+
|
|
44
|
+
```js
|
|
45
|
+
/**
|
|
46
|
+
* App.react.js
|
|
47
|
+
*/
|
|
48
|
+
|
|
49
|
+
const AppQuery = require('__generated__/AppQuery.graphql');
|
|
50
|
+
|
|
51
|
+
function App(props: Props) {
|
|
52
|
+
const [queryRef, loadQuery] = useQueryLoader(
|
|
53
|
+
AppQuery,
|
|
54
|
+
props.appQueryRef /* initial query ref */
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const refresh = useCallback(() => {
|
|
58
|
+
// Load the query again using the same original variables.
|
|
59
|
+
// Calling loadQuery will update the value of queryRef.
|
|
60
|
+
// The fetchPolicy ensures we always fetch from the server and skip
|
|
61
|
+
// the local data cache.
|
|
62
|
+
const {variables} = props.appQueryRef;
|
|
63
|
+
loadQuery(variables, {fetchPolicy: 'network-only'});
|
|
64
|
+
}, [/* ... */]);
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<React.Suspense fallback="Loading query...">
|
|
68
|
+
<MainContent
|
|
69
|
+
refresh={refresh}
|
|
70
|
+
queryRef={queryRef}
|
|
71
|
+
/>
|
|
72
|
+
</React.Suspense>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
```js
|
|
78
|
+
/**
|
|
79
|
+
* MainContent.react.js
|
|
80
|
+
*/
|
|
81
|
+
|
|
82
|
+
// Renders the preloaded query, given the query reference
|
|
83
|
+
function MainContent(props) {
|
|
84
|
+
const {refresh, queryRef} = props;
|
|
85
|
+
const data = usePreloadedQuery(
|
|
86
|
+
graphql`
|
|
87
|
+
query AppQuery($id: ID!) {
|
|
88
|
+
user(id: $id) {
|
|
89
|
+
name
|
|
90
|
+
friends {
|
|
91
|
+
count
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
`,
|
|
96
|
+
queryRef,
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<>
|
|
101
|
+
<h1>{data.user?.name}</h1>
|
|
102
|
+
<div>Friends count: {data.user.friends?.count}</div>
|
|
103
|
+
<Button
|
|
104
|
+
onClick={() => refresh()}>
|
|
105
|
+
Fetch latest count
|
|
106
|
+
</Button>
|
|
107
|
+
</>
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Let's distill what's going on here:
|
|
113
|
+
|
|
114
|
+
* We call `loadQuery` in the event handler for refreshing, so the network request starts immediately, and then pass the updated `queryRef` to the `MainContent` component that uses `usePreloadedQuery`, so it renders the updated data.
|
|
115
|
+
* We are passing a `fetchPolicy` of `'network-only'` to ensure that we always fetch from the network and skip the local data cache.
|
|
116
|
+
* Calling `loadQuery` will re-render the component and cause `usePreloadedQuery` to suspend (as explained in [Loading States with Suspense](../../rendering/loading-states/)), since a network request will always be made due to the `fetchPolicy` we are using. This means that we'll need to make sure that there's a `Suspense` boundary wrapping the `MainContent` component in order to show a fallback loading state.
|
|
117
|
+
|
|
118
|
+
</OssOnly>
|
|
119
|
+
|
|
120
|
+
### If you need to avoid Suspense
|
|
121
|
+
|
|
122
|
+
In some cases, you might want to avoid showing a Suspense fallback, which would hide the already rendered content. For these cases, you can use [`fetchQuery`](../../../api-reference/fetch-query/) instead, and manually keep track of a loading state:
|
|
123
|
+
|
|
124
|
+
<FbInternalOnly>
|
|
125
|
+
// @fb-only
|
|
126
|
+
</FbInternalOnly>
|
|
127
|
+
|
|
128
|
+
```js
|
|
129
|
+
/**
|
|
130
|
+
* App.react.js
|
|
131
|
+
*/
|
|
132
|
+
|
|
133
|
+
const AppQuery = require('__generated__/AppQuery.graphql');
|
|
134
|
+
|
|
135
|
+
function App(props: Props) {
|
|
136
|
+
const environment = useRelayEnvironment();
|
|
137
|
+
const [queryRef, loadQuery] = useQueryLoader(
|
|
138
|
+
AppQuery,
|
|
139
|
+
props.appQueryRef /* initial query ref */
|
|
140
|
+
);
|
|
141
|
+
const [isRefreshing, setIsRefreshing] = useState(false)
|
|
142
|
+
|
|
143
|
+
const refresh = useCallback(() => {
|
|
144
|
+
if (isRefreshing) { return; }
|
|
145
|
+
const {variables} = props.appQueryRef;
|
|
146
|
+
setIsRefreshing(true);
|
|
147
|
+
|
|
148
|
+
// fetchQuery will fetch the query and write
|
|
149
|
+
// the data to the Relay store. This will ensure
|
|
150
|
+
// that when we re-render, the data is already
|
|
151
|
+
// cached and we don't suspend
|
|
152
|
+
fetchQuery(environment, AppQuery, variables)
|
|
153
|
+
.subscribe({
|
|
154
|
+
complete: () => {
|
|
155
|
+
setIsRefreshing(false);
|
|
156
|
+
|
|
157
|
+
// *After* the query has been fetched, we call
|
|
158
|
+
// loadQuery again to re-render with a new
|
|
159
|
+
// queryRef.
|
|
160
|
+
// At this point the data for the query should
|
|
161
|
+
// be cached, so we use the 'store-only'
|
|
162
|
+
// fetchPolicy to avoid suspending.
|
|
163
|
+
loadQuery(variables, {fetchPolicy: 'store-only'});
|
|
164
|
+
}
|
|
165
|
+
error: () => {
|
|
166
|
+
setIsRefreshing(false);
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
}, [/* ... */]);
|
|
170
|
+
|
|
171
|
+
return (
|
|
172
|
+
<React.Suspense fallback="Loading query...">
|
|
173
|
+
<MainContent
|
|
174
|
+
isRefreshing={isRefreshing}
|
|
175
|
+
refresh={refresh}
|
|
176
|
+
queryRef={queryRef}
|
|
177
|
+
/>
|
|
178
|
+
</React.Suspense>
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Let's distill what's going on here:
|
|
184
|
+
|
|
185
|
+
* When refreshing, we now keep track of our own `isRefreshing` loading state, since we are avoiding suspending. We can use this state to render a busy spinner or similar loading UI inside the `MainContent` component, *without* hiding the `MainContent`.
|
|
186
|
+
* In the event handler, we first call `fetchQuery`, which will fetch the query and write the data to the local Relay store. When the `fetchQuery` network request completes, we call `loadQuery` so that we obtain an updated `queryRef` that we then pass to `usePreloadedQuery` in order render the updated data, similar to the previous example.
|
|
187
|
+
* At this point, when `loadQuery` is called, the data for the query should already be cached in the local Relay store, so we use `fetchPolicy` of `'store-only'` to avoid suspending and only read the already cached data.
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
## When using `useLazyLoadQuery`
|
|
191
|
+
|
|
192
|
+
To refresh a query using the [`useLazyLoadQuery`](../../../api-reference/use-lazy-load-query/) Hook described in our [Lazily Fetching Queries during Render](../../rendering/queries/#lazily-fetching-queries-during-render) section, we can do the following:
|
|
193
|
+
|
|
194
|
+
<FbInternalOnly>
|
|
195
|
+
// @fb-only
|
|
196
|
+
</FbInternalOnly>
|
|
197
|
+
|
|
198
|
+
<OssOnly>
|
|
199
|
+
|
|
200
|
+
```js
|
|
201
|
+
/**
|
|
202
|
+
* App.react.js
|
|
203
|
+
*/
|
|
204
|
+
const AppQuery = require('__generated__/AppQuery.graphql');
|
|
205
|
+
|
|
206
|
+
function App(props: Props) {
|
|
207
|
+
const variables = {id: '4'};
|
|
208
|
+
const [refreshedQueryOptions, setRefreshedQueryOptions] = useState(null);
|
|
209
|
+
|
|
210
|
+
const refresh = useCallback(() => {
|
|
211
|
+
// Trigger a re-render of useLazyLoadQuery with the same variables,
|
|
212
|
+
// but an updated fetchKey and fetchPolicy.
|
|
213
|
+
// The new fetchKey will ensure that the query is fully
|
|
214
|
+
// re-evaluated and refetched.
|
|
215
|
+
// The fetchPolicy ensures that we always fetch from the network
|
|
216
|
+
// and skip the local data cache.
|
|
217
|
+
setRefreshedQueryOptions(prev => ({
|
|
218
|
+
fetchKey: (prev?.fetchKey ?? 0) + 1,
|
|
219
|
+
fetchPolicy: 'network-only',
|
|
220
|
+
}));
|
|
221
|
+
}, [/* ... */]);
|
|
222
|
+
|
|
223
|
+
return (
|
|
224
|
+
<React.Suspense fallback="Loading query...">
|
|
225
|
+
<MainContent
|
|
226
|
+
refresh={refresh}
|
|
227
|
+
queryOptions={refreshedQueryOptions ?? {}}
|
|
228
|
+
variables={variables}
|
|
229
|
+
/>
|
|
230
|
+
</React.Suspense>
|
|
231
|
+
);
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
```js
|
|
235
|
+
/**
|
|
236
|
+
* MainContent.react.js
|
|
237
|
+
*/
|
|
238
|
+
|
|
239
|
+
// Fetches and renders the query, given the fetch options
|
|
240
|
+
function MainContent(props) {
|
|
241
|
+
const {refresh, queryOptions, variables} = props;
|
|
242
|
+
const data = useLazyLoadQuery(
|
|
243
|
+
graphql`
|
|
244
|
+
query AppQuery($id: ID!) {
|
|
245
|
+
user(id: $id) {
|
|
246
|
+
name
|
|
247
|
+
friends {
|
|
248
|
+
count
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
`,
|
|
253
|
+
variables,
|
|
254
|
+
queryOptions,
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
return (
|
|
258
|
+
<>
|
|
259
|
+
<h1>{data.user?.name}</h1>
|
|
260
|
+
<div>Friends count: {data.user.friends?.count}</div>
|
|
261
|
+
<Button
|
|
262
|
+
onClick={() => refresh()}>
|
|
263
|
+
Fetch latest count
|
|
264
|
+
</Button>
|
|
265
|
+
</>
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
Let's distill what's going on here:
|
|
271
|
+
|
|
272
|
+
* We update the component in the event handler for refreshing by setting new options in state. This will cause the `MainContent` component that uses `useLazyLoadQuery` to re-render with the new `fetchKey` and `fetchPolicy`, and refetch the query upon rendering.
|
|
273
|
+
* We are passing a new value of `fetchKey` which we increment on every update. Passing a new `fetchKey` to `useLazyLoadQuery` on every update will ensure that the query is fully re-evaluated and refetched.
|
|
274
|
+
* We are passing a `fetchPolicy` of `'network-only'` to ensure that we always fetch from the network and skip the local data cache.
|
|
275
|
+
* The state update in `refresh` will cause the component to suspend (as explained in [Loading States with Suspense](../../rendering/loading-states/)), since a network request will always be made due to the `fetchPolicy` we are using. This means that we'll need to make sure that there's a `Suspense` boundary wrapping the `MainContent` component in order to show a fallback loading state.
|
|
276
|
+
|
|
277
|
+
</OssOnly>
|
|
278
|
+
|
|
279
|
+
### If you need to avoid Suspense
|
|
280
|
+
|
|
281
|
+
In some cases, you might want to avoid showing a Suspense fallback, which would hide the already rendered content. For these cases, you can use [`fetchQuery`](../../../api-reference/fetch-query/) instead, and manually keep track of a loading state:
|
|
282
|
+
|
|
283
|
+
<FbInternalOnly>
|
|
284
|
+
// @fb-only
|
|
285
|
+
</FbInternalOnly>
|
|
286
|
+
|
|
287
|
+
```js
|
|
288
|
+
/**
|
|
289
|
+
* App.react.js
|
|
290
|
+
*/
|
|
291
|
+
import type {AppQuery as AppQueryType} from 'AppQuery.graphql';
|
|
292
|
+
|
|
293
|
+
const AppQuery = require('__generated__/AppQuery.graphql');
|
|
294
|
+
|
|
295
|
+
function App(props: Props) {
|
|
296
|
+
const variables = {id: '4'}
|
|
297
|
+
const environment = useRelayEnvironment();
|
|
298
|
+
const [refreshedQueryOptions, setRefreshedQueryOptions] = useState(null);
|
|
299
|
+
const [isRefreshing, setIsRefreshing] = useState(false)
|
|
300
|
+
|
|
301
|
+
const refresh = useCallback(() => {
|
|
302
|
+
if (isRefreshing) { return; }
|
|
303
|
+
setIsRefreshing(true);
|
|
304
|
+
|
|
305
|
+
// fetchQuery will fetch the query and write
|
|
306
|
+
// the data to the Relay store. This will ensure
|
|
307
|
+
// that when we re-render, the data is already
|
|
308
|
+
// cached and we don't suspend
|
|
309
|
+
fetchQuery(environment, AppQuery, variables)
|
|
310
|
+
.subscribe({
|
|
311
|
+
complete: () => {
|
|
312
|
+
setIsRefreshing(false);
|
|
313
|
+
|
|
314
|
+
// *After* the query has been fetched, we update
|
|
315
|
+
// our state to re-render with the new fetchKey
|
|
316
|
+
// and fetchPolicy.
|
|
317
|
+
// At this point the data for the query should
|
|
318
|
+
// be cached, so we use the 'store-only'
|
|
319
|
+
// fetchPolicy to avoid suspending.
|
|
320
|
+
setRefreshedQueryOptions(prev => ({
|
|
321
|
+
fetchKey: (prev?.fetchKey ?? 0) + 1,
|
|
322
|
+
fetchPolicy: 'store-only',
|
|
323
|
+
}));
|
|
324
|
+
}
|
|
325
|
+
error: () => {
|
|
326
|
+
setIsRefreshing(false);
|
|
327
|
+
}
|
|
328
|
+
});
|
|
329
|
+
}, [/* ... */]);
|
|
330
|
+
|
|
331
|
+
return (
|
|
332
|
+
<React.Suspense fallback="Loading query...">
|
|
333
|
+
<MainContent
|
|
334
|
+
isRefreshing={isRefreshing}
|
|
335
|
+
refresh={refresh}
|
|
336
|
+
queryOptions={refreshedQueryOptions ?? {}}
|
|
337
|
+
variables={variables}
|
|
338
|
+
/>
|
|
339
|
+
</React.Suspense>
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
Let's distill what's going on here:
|
|
345
|
+
|
|
346
|
+
* When refreshing, we now keep track of our own `isRefreshing` loading state, since we are avoiding suspending. We can use this state to render a busy spinner or similar loading UI inside the `MainContent` component, *without* hiding the `MainContent`.
|
|
347
|
+
* In the event handler, we first call `fetchQuery`, which will fetch the query and write the data to the local Relay store. When the `fetchQuery` network request completes, we update our state so that we re-render an updated `fetchKey` and `fetchPolicy` that we then pass to `useLazyLoadQuery` in order render the updated data, similar to the previous example.
|
|
348
|
+
* At this point, when we update the state, the data for the query should already be cached in the local Relay store, so we use `fetchPolicy` of `'store-only'` to avoid suspending and only read the already cached data.
|
|
349
|
+
|
|
350
|
+
<DocsRating />
|