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,592 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: updating-connections
|
|
3
|
+
title: Updating Connections
|
|
4
|
+
slug: /guided-tour/list-data/updating-connections/
|
|
5
|
+
description: Relay guide to updating connections
|
|
6
|
+
keywords:
|
|
7
|
+
- pagination
|
|
8
|
+
- usePaginationFragment
|
|
9
|
+
- updating
|
|
10
|
+
- connection
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
import DocsRating from '@site/src/core/DocsRating';
|
|
14
|
+
import {OssOnly, FbInternalOnly} from 'docusaurus-plugin-internaldocs-fb/internal';
|
|
15
|
+
|
|
16
|
+
Usually when you're rendering a connection, you'll also want to be able to add or remove items to/from the connection in response to user actions.
|
|
17
|
+
|
|
18
|
+
Relay holds a local in-memory store of normalized GraphQL data, where records are stored by their IDs. When creating mutations, subscriptions, or local data updates with Relay, you must provide an [`updater`](../../updating-data/graphql-mutations/#updater-functions) function, inside which you can access and read records, as well as write and make updates to them. When records are updated, any components affected by the updated data will be notified and re-rendered.
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
## Connection Records
|
|
22
|
+
|
|
23
|
+
In Relay, connection fields that are marked with the `@connection` directive are stored as special records in the store, and they hold and accumulate *all* of the items that have been fetched for the connection so far. In order to add or remove items from a connection, we need to access the connection record using the connection `key`, which was provided when declaring a `@connection`; specifically, this allows us to access a connection inside an [`updater`](../../updating-data/graphql-mutations/#updater-functions) function using the `ConnectionHandler` APIs.
|
|
24
|
+
|
|
25
|
+
For example, given the following fragment that declares a `@connection`, we can access the connection record inside an `updater` function in a few different ways:
|
|
26
|
+
|
|
27
|
+
```js
|
|
28
|
+
const {graphql} = require('react-relay');
|
|
29
|
+
|
|
30
|
+
const storyFragment = graphql`
|
|
31
|
+
fragment StoryComponent_story on Story {
|
|
32
|
+
comments @connection(key: "StoryComponent_story_comments_connection") {
|
|
33
|
+
nodes {
|
|
34
|
+
body {
|
|
35
|
+
text
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
`;
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Accessing connections using `__id`
|
|
44
|
+
|
|
45
|
+
We can query for a connection's `__id` field, and then use that `__id` to access the record in the store:
|
|
46
|
+
|
|
47
|
+
```js
|
|
48
|
+
const fragmentData = useFragment(
|
|
49
|
+
graphql`
|
|
50
|
+
fragment StoryComponent_story on Story {
|
|
51
|
+
comments @connection(key: "StoryComponent_story_comments_connection") {
|
|
52
|
+
# Query for the __id field
|
|
53
|
+
__id
|
|
54
|
+
|
|
55
|
+
# ...
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
`,
|
|
59
|
+
props.story,
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
// Get the connection record id
|
|
63
|
+
const connectionID = fragmentData?.comments?.__id;
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Then use it to access the record in the store:
|
|
67
|
+
|
|
68
|
+
```js
|
|
69
|
+
function updater(store: RecordSourceSelectorProxy) {
|
|
70
|
+
// connectionID is passed as input to the mutation/subscription
|
|
71
|
+
const connection = store.get(connectionID);
|
|
72
|
+
|
|
73
|
+
// ...
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
:::note
|
|
78
|
+
The `__id` field is **NOT** something that your GraphQL API needs to expose. Instead, it's an identifier that Relay automatically adds to identify the connection record.
|
|
79
|
+
:::
|
|
80
|
+
|
|
81
|
+
### Accessing connections using `ConnectionHandler.getConnectionID`
|
|
82
|
+
|
|
83
|
+
If we have access to the ID of the parent record that holds the connection, we can access the connection record by using the `ConnectionHandler.getConnectionID` API:
|
|
84
|
+
|
|
85
|
+
```js
|
|
86
|
+
const {ConnectionHandler} = require('relay-runtime');
|
|
87
|
+
|
|
88
|
+
function updater(store: RecordSourceSelectorProxy) {
|
|
89
|
+
// Get the connection ID
|
|
90
|
+
const connectionID = ConnectionHandler.getConnectionID(
|
|
91
|
+
storyID, // passed as input to the mutation/subscription
|
|
92
|
+
'StoryComponent_story_comments_connection',
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
// Get the connection record
|
|
96
|
+
const connectionRecord = store.get(connectionID);
|
|
97
|
+
|
|
98
|
+
// ...
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Accessing connections using `ConnectionHandler.getConnection`
|
|
103
|
+
|
|
104
|
+
If we have access to the parent record that holds the connection, we can access the connection record via the parent, by using the `ConnectionHandler.getConnection` API:
|
|
105
|
+
|
|
106
|
+
```js
|
|
107
|
+
const {ConnectionHandler} = require('relay-runtime');
|
|
108
|
+
|
|
109
|
+
function updater(store: RecordSourceSelectorProxy) {
|
|
110
|
+
// Get parent story record
|
|
111
|
+
// storyID is passed as input to the mutation/subscription
|
|
112
|
+
const storyRecord = store.get(storyID);
|
|
113
|
+
|
|
114
|
+
// Get the connection record from the parent
|
|
115
|
+
const connectionRecord = ConnectionHandler.getConnection(
|
|
116
|
+
storyRecord,
|
|
117
|
+
'StoryComponent_story_comments_connection',
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
// ...
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Adding edges
|
|
125
|
+
|
|
126
|
+
There are a couple of alternatives for adding edges to a connection:
|
|
127
|
+
|
|
128
|
+
### Using declarative directives
|
|
129
|
+
|
|
130
|
+
Usually, mutation or subscription payloads will expose the new edges that were added on the server as a field with a single edge or list of edges. If your mutation or subscription exposes an edge or edges field that you can query for in the response, then you can use the `@appendEdge` and `@prependEdge` declarative mutation directives on that field in order to add the newly created edges to the specified connections (note that these directives also work on queries).
|
|
131
|
+
|
|
132
|
+
Alternatively, mutation or subscription payloads might expose the new nodes that were added on the server as a field with a single node or list of nodes. If your mutation or subscription exposes a node or nodes field that you can query for in the response, then you can use the `@appendNode` and `@prependNode` declarative mutation directives on that field in order to add the newly created nodes, wrapped inside edges, to the specified connections (note that these directives also work on queries).
|
|
133
|
+
|
|
134
|
+
These directives accept a `connections` parameter, which needs to be a GraphQL variable containing an array of connection IDs. Connection IDs can be obtained either by using the [`__id` field on connections](#accessing-connections-using-__id) or using the [`ConnectionHandler.getConnectionID`](#accessing-connections-using-connectionhandlergetconnectionid) API.
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
#### `@appendEdge` / `@prependEdge`
|
|
138
|
+
|
|
139
|
+
These directives work on a field with a single edge or list of edges. `@prependEdge` will add the selected edges to the beginning of each connection defined in the `connections` array, whereas `@appendEdge` will add the selected edges to the end of each connection in the array.
|
|
140
|
+
|
|
141
|
+
**Arguments:**
|
|
142
|
+
- `connections`: An array of connection IDs. Connection IDs can be obtained either by using the [`__id` field on connections](#accessing-connections-using-__id) or using the [`ConnectionHandler.getConnectionID`](#accessing-connections-using-connectionhandlergetconnectionid) API.
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
**Example:**
|
|
146
|
+
|
|
147
|
+
```js
|
|
148
|
+
// Get the connection ID using the `__id` field
|
|
149
|
+
const connectionID = fragmentData?.comments?.__id;
|
|
150
|
+
|
|
151
|
+
// Or get it using `ConnectionHandler.getConnectionID()`
|
|
152
|
+
const connectionID = ConnectionHandler.getConnectionID(
|
|
153
|
+
'<story-id>',
|
|
154
|
+
'StoryComponent_story_comments_connection',
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
// ...
|
|
158
|
+
|
|
159
|
+
// Mutation
|
|
160
|
+
commitMutation<AppendCommentMutation>(environment, {
|
|
161
|
+
mutation: graphql`
|
|
162
|
+
mutation AppendCommentMutation(
|
|
163
|
+
# Define a GraphQL variable for the connections array
|
|
164
|
+
$connections: [ID!]!
|
|
165
|
+
$input: CommentCreateInput
|
|
166
|
+
) {
|
|
167
|
+
commentCreate(input: $input) {
|
|
168
|
+
# Use @appendEdge or @prependEdge on the edge field
|
|
169
|
+
feedbackCommentEdge @appendEdge(connections: $connections) {
|
|
170
|
+
cursor
|
|
171
|
+
node {
|
|
172
|
+
id
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
`,
|
|
178
|
+
variables: {
|
|
179
|
+
input,
|
|
180
|
+
// Pass the `connections` array
|
|
181
|
+
connections: [connectionID],
|
|
182
|
+
},
|
|
183
|
+
});
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
#### `@appendNode` / `@prependNode`
|
|
188
|
+
|
|
189
|
+
These directives work on a field with a single node or list of nodes, and will create edges with the specified `edgeTypeName`. `@prependNode` will add edges containing the selected nodes to the beginning of each connection defined in the `connections` array, whereas `@appendNode` will add edges containing the selected nodes to the end of each connection in the array.
|
|
190
|
+
|
|
191
|
+
**Arguments:**
|
|
192
|
+
- `connections`: An array of connection IDs. Connection IDs can be obtained either by using the [`__id` field on connections](#accessing-connections-using-__id) or using the [`ConnectionHandler.getConnectionID`](#accessing-connections-using-connectionhandlergetconnectionid) API.
|
|
193
|
+
- `edgeTypeName`: The type name of the edge that contains the node, corresponding to the edge type argument in `ConnectionHandler.createEdge`.
|
|
194
|
+
|
|
195
|
+
**Example:**
|
|
196
|
+
```js
|
|
197
|
+
// Get the connection ID using the `__id` field
|
|
198
|
+
const connectionID = fragmentData?.comments?.__id;
|
|
199
|
+
|
|
200
|
+
// Or get it using `ConnectionHandler.getConnectionID()`
|
|
201
|
+
const connectionID = ConnectionHandler.getConnectionID(
|
|
202
|
+
'<story-id>',
|
|
203
|
+
'StoryComponent_story_comments_connection',
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
// ...
|
|
207
|
+
|
|
208
|
+
// Mutation
|
|
209
|
+
commitMutation<AppendCommentMutation>(environment, {
|
|
210
|
+
mutation: graphql`
|
|
211
|
+
mutation AppendCommentMutation(
|
|
212
|
+
# Define a GraphQL variable for the connections array
|
|
213
|
+
$connections: [ID!]!
|
|
214
|
+
$input: CommentCreateInput
|
|
215
|
+
) {
|
|
216
|
+
commentCreate(input: $input) {
|
|
217
|
+
# Use @appendNode or @prependNode on the node field
|
|
218
|
+
feedbackCommentNode @appendNode(connections: $connections, edgeTypeName: "CommentsEdge") {
|
|
219
|
+
id
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
`,
|
|
224
|
+
variables: {
|
|
225
|
+
input,
|
|
226
|
+
// Pass the `connections` array
|
|
227
|
+
connections: [connectionID],
|
|
228
|
+
},
|
|
229
|
+
});
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
#### Order of execution
|
|
234
|
+
|
|
235
|
+
For all of these directives, they will be executed in the following order within the mutation or subscription, as per the [order of execution of updates](../../updating-data/graphql-mutations/#order-of-execution-of-updater-functions):
|
|
236
|
+
|
|
237
|
+
* When the mutation is initiated, after the optimistic response is handled, and after the optimistic updater function is executed, the `@prependEdge`, `@appendEdge`, `@prependNode`, and `@appendNode` directives will be applied to the optimistic response.
|
|
238
|
+
* If the mutation succeeds, after the data from the network response is merged with the existing values in the store, and after the updater function is executed, the `@prependEdge`, `@appendEdge`, `@prependNode`, and `@appendNode` directives will be applied to the data in the network response.
|
|
239
|
+
* If the mutation failed, the updates from processing the `@prependEdge`, `@appendEdge`, `@prependNode`, and `@appendNode` directives will be rolled back.
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
### Manually adding edges
|
|
243
|
+
|
|
244
|
+
The directives described [above](#using-declarative-directives) largely remove the need to manually add and remove items from a connection, however, they do not provide as much control as you can get with manually writing an updater, and may not fulfill every use case.
|
|
245
|
+
|
|
246
|
+
In order to write an updater to modify the connection, we need to make sure we have access to the [connection record](#connection-record). Once we have the connection record, we also need a record for the new edge that we want to add to the connection. Usually, mutation or subscription payloads will contain the new edge that was added; if not, you can also construct a new edge from scratch.
|
|
247
|
+
|
|
248
|
+
For example, in the following mutation we can query for the newly created edge in the mutation response:
|
|
249
|
+
|
|
250
|
+
```js
|
|
251
|
+
const {graphql} = require('react-relay');
|
|
252
|
+
|
|
253
|
+
const createCommentMutation = graphql`
|
|
254
|
+
mutation CreateCommentMutation($input: CommentCreateData!) {
|
|
255
|
+
comment_create(input: $input) {
|
|
256
|
+
comment_edge {
|
|
257
|
+
cursor
|
|
258
|
+
node {
|
|
259
|
+
body {
|
|
260
|
+
text
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
`;
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
* Note that we also query for the `cursor` for the new edge; this isn't strictly necessary, but it is information that will be required if we need to perform pagination based on that `cursor`.
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
Inside an [`updater`](../../updating-data/graphql-mutations/#updater-functions), we can access the edge inside the mutation response using Relay store APIs:
|
|
273
|
+
|
|
274
|
+
```js
|
|
275
|
+
const {ConnectionHandler} = require('relay-runtime');
|
|
276
|
+
|
|
277
|
+
function updater(store: RecordSourceSelectorProxy) {
|
|
278
|
+
const storyRecord = store.get(storyID);
|
|
279
|
+
const connectionRecord = ConnectionHandler.getConnection(
|
|
280
|
+
storyRecord,
|
|
281
|
+
'StoryComponent_story_comments_connection',
|
|
282
|
+
);
|
|
283
|
+
|
|
284
|
+
// Get the payload returned from the server
|
|
285
|
+
const payload = store.getRootField('comment_create');
|
|
286
|
+
|
|
287
|
+
// Get the edge inside the payload
|
|
288
|
+
const serverEdge = payload.getLinkedRecord('comment_edge');
|
|
289
|
+
|
|
290
|
+
// Build edge for adding to the connection
|
|
291
|
+
const newEdge = ConnectionHandler.buildConnectionEdge(
|
|
292
|
+
store,
|
|
293
|
+
connectionRecord,
|
|
294
|
+
serverEdge,
|
|
295
|
+
);
|
|
296
|
+
|
|
297
|
+
// ...
|
|
298
|
+
}
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
* The mutation payload is available as a root field on that store, which can be read using the `store.getRootField` API. In our case, we're reading `comment_create`, which is the root field in the response.
|
|
302
|
+
* Note that we need to construct the new edge from the edge received from the server using `ConnectionHandler.buildConnectionEdge` before we can add it to the connection.
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
If you need to create a new edge from scratch, you can use `ConnectionHandler.createEdge`:
|
|
306
|
+
|
|
307
|
+
```js
|
|
308
|
+
const {ConnectionHandler} = require('relay-runtime');
|
|
309
|
+
|
|
310
|
+
function updater(store: RecordSourceSelectorProxy) {
|
|
311
|
+
const storyRecord = store.get(storyID);
|
|
312
|
+
const connectionRecord = ConnectionHandler.getConnection(
|
|
313
|
+
storyRecord,
|
|
314
|
+
'StoryComponent_story_comments_connection',
|
|
315
|
+
);
|
|
316
|
+
|
|
317
|
+
// Create a new local Comment record
|
|
318
|
+
const id = `client:new_comment:${randomID()}`;
|
|
319
|
+
const newCommentRecord = store.create(id, 'Comment');
|
|
320
|
+
|
|
321
|
+
// Create new edge
|
|
322
|
+
const newEdge = ConnectionHandler.createEdge(
|
|
323
|
+
store,
|
|
324
|
+
connectionRecord,
|
|
325
|
+
newCommentRecord,
|
|
326
|
+
'CommentEdge', /* GraphQl Type for edge */
|
|
327
|
+
);
|
|
328
|
+
|
|
329
|
+
// ...
|
|
330
|
+
}
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
Once we have a new edge record, we can add it to the the connection using `ConnectionHandler.insertEdgeAfter` or `ConnectionHandler.insertEdgeBefore`:
|
|
335
|
+
|
|
336
|
+
```js
|
|
337
|
+
const {ConnectionHandler} = require('relay-runtime');
|
|
338
|
+
|
|
339
|
+
function updater(store: RecordSourceSelectorProxy) {
|
|
340
|
+
const storyRecord = store.get(storyID);
|
|
341
|
+
const connectionRecord = ConnectionHandler.getConnection(
|
|
342
|
+
storyRecord,
|
|
343
|
+
'StoryComponent_story_comments_connection',
|
|
344
|
+
);
|
|
345
|
+
|
|
346
|
+
const newEdge = (...);
|
|
347
|
+
|
|
348
|
+
// Add edge to the end of the connection
|
|
349
|
+
ConnectionHandler.insertEdgeAfter(
|
|
350
|
+
connectionRecord,
|
|
351
|
+
newEdge,
|
|
352
|
+
);
|
|
353
|
+
|
|
354
|
+
// Add edge to the beginning of the connection
|
|
355
|
+
ConnectionHandler.insertEdgeBefore(
|
|
356
|
+
connectionRecord,
|
|
357
|
+
newEdge,
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
* Note that these APIs will *mutate* the connection in place
|
|
363
|
+
|
|
364
|
+
:::note
|
|
365
|
+
Check out our complete [Relay Store APIs](../../../api-reference/store/).
|
|
366
|
+
:::
|
|
367
|
+
|
|
368
|
+
## Removing edges
|
|
369
|
+
|
|
370
|
+
### Using the declarative deletion directive
|
|
371
|
+
|
|
372
|
+
Similarly to the [directives to add edges](#using-declarative-directives), we can use the `@deleteEdge` directive to delete edges from connections. If your mutation or subscription exposes a field with the ID or IDs of the nodes that were deleted that you can query for in the response, then you can use the `@deleteEdge` directive on that field to delete the respective edges from the connection (note that this directive also works on queries).
|
|
373
|
+
|
|
374
|
+
#### `@deleteEdge`
|
|
375
|
+
|
|
376
|
+
Works on GraphQL fields that return an `ID` or `[ID]`. Will delete the edges with nodes that match the `id` from each connection defined in the `connections` array.
|
|
377
|
+
|
|
378
|
+
**Arguments:**
|
|
379
|
+
- `connections`: An array of connection IDs. Connection IDs can be obtained either by using the [`__id` field on connections](#accessing-connections-using-__id) or using the [`ConnectionHandler.getConnectionID`](#accessing-connections-using-connectionhandlergetconnectionid) API.
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
**Example:**
|
|
383
|
+
|
|
384
|
+
```js
|
|
385
|
+
// Get the connection ID using the `__id` field
|
|
386
|
+
const connectionID = fragmentData?.comments?.__id;
|
|
387
|
+
|
|
388
|
+
// Or get it using `ConnectionHandler.getConnectionID()`
|
|
389
|
+
const connectionID = ConnectionHandler.getConnectionID(
|
|
390
|
+
'<story-id>',
|
|
391
|
+
'StoryComponent_story_comments_connection',
|
|
392
|
+
);
|
|
393
|
+
|
|
394
|
+
// ...
|
|
395
|
+
|
|
396
|
+
// Mutation
|
|
397
|
+
commitMutation<DeleteCommentsMutation>(environment, {
|
|
398
|
+
mutation: graphql`
|
|
399
|
+
mutation DeleteCommentsMutation(
|
|
400
|
+
# Define a GraphQL variable for the connections array
|
|
401
|
+
$connections: [ID!]!
|
|
402
|
+
$input: CommentsDeleteInput
|
|
403
|
+
) {
|
|
404
|
+
commentsDelete(input: $input) {
|
|
405
|
+
deletedCommentIds @deleteEdge(connections: $connections)
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
`,
|
|
409
|
+
variables: {
|
|
410
|
+
input,
|
|
411
|
+
// Pass the `connections` array
|
|
412
|
+
connections: [connectionID],
|
|
413
|
+
},
|
|
414
|
+
});
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
### Manually removing edges
|
|
418
|
+
|
|
419
|
+
`ConnectionHandler` provides a similar API to remove an edge from a connection, via `ConnectionHandler.deleteNode`:
|
|
420
|
+
|
|
421
|
+
```js
|
|
422
|
+
const {ConnectionHandler} = require('RelayModern');
|
|
423
|
+
|
|
424
|
+
function updater(store: RecordSourceSelectorProxy) {
|
|
425
|
+
const storyRecord = store.get(storyID);
|
|
426
|
+
const connectionRecord = ConnectionHandler.getConnection(
|
|
427
|
+
storyRecord,
|
|
428
|
+
'StoryComponent_story_comments_connection',
|
|
429
|
+
);
|
|
430
|
+
|
|
431
|
+
// Remove edge from the connection, given the ID of the node
|
|
432
|
+
ConnectionHandler.deleteNode(
|
|
433
|
+
connectionRecord,
|
|
434
|
+
commentIDToDelete,
|
|
435
|
+
);
|
|
436
|
+
}
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
* In this case `ConnectionHandler.deleteNode` will remove an edge given a *`node` ID*. This means it will look up which edge in the connection contains a node with the provided ID, and remove that edge.
|
|
440
|
+
* Note that this API will *mutate* the connection in place.
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
:::note
|
|
444
|
+
Remember: when performing any of the operations described here to mutate a connection, any fragment or query components that are rendering the affected connection will be notified and re-render with the latest version of the connection.
|
|
445
|
+
:::
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
## Connection identity with filters
|
|
449
|
+
|
|
450
|
+
In our previous examples, our connections didn't take any arguments as filters. If you declared a connection that takes arguments as filters, the values used for the filters will be part of the connection identifier. In other words, *each of the values passed in as connection filters will be used to identify the connection in the Relay store.*
|
|
451
|
+
|
|
452
|
+
:::note
|
|
453
|
+
Note that this excludes pagination arguments, i.e. it excludes `first`, `last`, `before`, and `after`.
|
|
454
|
+
:::
|
|
455
|
+
|
|
456
|
+
|
|
457
|
+
For example, let's say the `comments` field took the following arguments, which we pass in as GraphQL [variables](../../rendering/variables/):
|
|
458
|
+
|
|
459
|
+
```js
|
|
460
|
+
const {graphql} = require('RelayModern');
|
|
461
|
+
|
|
462
|
+
const storyFragment = graphql`
|
|
463
|
+
fragment StoryComponent_story on Story {
|
|
464
|
+
comments(
|
|
465
|
+
order_by: $orderBy,
|
|
466
|
+
filter_mode: $filterMode,
|
|
467
|
+
language: $language,
|
|
468
|
+
) @connection(key: "StoryComponent_story_comments_connection") {
|
|
469
|
+
edges {
|
|
470
|
+
nodes {
|
|
471
|
+
body {
|
|
472
|
+
text
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
`;
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
In the example above, this means that whatever values we used for `$orderBy`, `$filterMode` and `$language` when we queried for the `comments` field will be part of the connection identifier, and we'll need to use those values when accessing the connection record from the Relay store.
|
|
482
|
+
|
|
483
|
+
In order to do so, we need to pass a third argument to `ConnectionHandler.getConnection`, with concrete filter values to identify the connection:
|
|
484
|
+
|
|
485
|
+
```js
|
|
486
|
+
const {ConnectionHandler} = require('RelayModern');
|
|
487
|
+
|
|
488
|
+
function updater(store: RecordSourceSelectorProxy) {
|
|
489
|
+
const storyRecord = store.get(storyID);
|
|
490
|
+
|
|
491
|
+
// Get the connection instance for the connection with comments sorted
|
|
492
|
+
// by the date they were added
|
|
493
|
+
const connectionRecordSortedByDate = ConnectionHandler.getConnection(
|
|
494
|
+
storyRecord,
|
|
495
|
+
'StoryComponent_story_comments_connection',
|
|
496
|
+
{order_by: '*DATE_ADDED*', filter_mode: null, language: null}
|
|
497
|
+
);
|
|
498
|
+
|
|
499
|
+
// Get the connection instance for the connection that only contains
|
|
500
|
+
// comments made by friends
|
|
501
|
+
const connectionRecordFriendsOnly = ConnectionHandler.getConnection(
|
|
502
|
+
storyRecord,
|
|
503
|
+
'StoryComponent_story_comments_connection',
|
|
504
|
+
{order_by: null, filter_mode: '*FRIENDS_ONLY*', language: null}
|
|
505
|
+
);
|
|
506
|
+
}
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
This implies that by default, *each combination of values used for filters will produce a different record for the connection.*
|
|
510
|
+
|
|
511
|
+
When making updates to a connection, you will need to make sure to update all of the relevant records affected by a change. For example, if we were to add a new comment to our example connection, we'd need to make sure *not* to add the comment to the `FRIENDS_ONLY` connection, if the new comment wasn't made by a friend of the user:
|
|
512
|
+
|
|
513
|
+
```js
|
|
514
|
+
const {ConnectionHandler} = require('relay-runtime');
|
|
515
|
+
|
|
516
|
+
function updater(store: RecordSourceSelectorProxy) {
|
|
517
|
+
const storyRecord = store.get(storyID);
|
|
518
|
+
|
|
519
|
+
// Get the connection instance for the connection with comments sorted
|
|
520
|
+
// by the date they were added
|
|
521
|
+
const connectionRecordSortedByDate = ConnectionHandler.getConnection(
|
|
522
|
+
storyRecord,
|
|
523
|
+
'StoryComponent_story_comments_connection',
|
|
524
|
+
{order_by: '*DATE_ADDED*', filter_mode: null, language: null}
|
|
525
|
+
);
|
|
526
|
+
|
|
527
|
+
// Get the connection instance for the connection that only contains
|
|
528
|
+
// comments made by friends
|
|
529
|
+
const connectionRecordFriendsOnly = ConnectionHandler.getConnection(
|
|
530
|
+
storyRecord,
|
|
531
|
+
'StoryComponent_story_comments_connection',
|
|
532
|
+
{order_by: null, filter_mode: '*FRIENDS_ONLY*', language: null}
|
|
533
|
+
);
|
|
534
|
+
|
|
535
|
+
const newComment = (...);
|
|
536
|
+
const newEdge = (...);
|
|
537
|
+
|
|
538
|
+
ConnectionHandler.insertEdgeAfter(
|
|
539
|
+
connectionRecordSortedByDate,
|
|
540
|
+
newEdge,
|
|
541
|
+
);
|
|
542
|
+
|
|
543
|
+
if (isMadeByFriend(storyRecord, newComment) {
|
|
544
|
+
// Only add new comment to friends-only connection if the comment
|
|
545
|
+
// was made by a friend
|
|
546
|
+
ConnectionHandler.insertEdgeAfter(
|
|
547
|
+
connectionRecordFriendsOnly,
|
|
548
|
+
newEdge,
|
|
549
|
+
);
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
|
|
555
|
+
|
|
556
|
+
### Managing connections with many filters
|
|
557
|
+
|
|
558
|
+
As you can see, just adding a few filters to a connection can make the complexity and number of connection records that need to be managed explode. In order to more easily manage this, Relay allows you to specify exactly *which* filters should be used as connection identifiers.
|
|
559
|
+
|
|
560
|
+
By default, *all* non-pagination filters will be used as part of the connection identifier. However, when declaring a `@connection`, you can specify the exact set of filters to use for connection identity:
|
|
561
|
+
|
|
562
|
+
```js
|
|
563
|
+
const {graphql} = require('relay-runtime');
|
|
564
|
+
|
|
565
|
+
const storyFragment = graphql`
|
|
566
|
+
fragment StoryComponent_story on Story {
|
|
567
|
+
comments(
|
|
568
|
+
order_by: $orderBy
|
|
569
|
+
filter_mode: $filterMode
|
|
570
|
+
language: $language
|
|
571
|
+
)
|
|
572
|
+
@connection(
|
|
573
|
+
key: "StoryComponent_story_comments_connection"
|
|
574
|
+
filters: ["order_by", "filter_mode"]
|
|
575
|
+
) {
|
|
576
|
+
edges {
|
|
577
|
+
nodes {
|
|
578
|
+
body {
|
|
579
|
+
text
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
`;
|
|
586
|
+
```
|
|
587
|
+
|
|
588
|
+
* By specifying `filters` when declaring the `@connection`, we're indicating to Relay the exact set of filter values that should be used as part of connection identity. In this case, we're excluding `language`, which means that only values for `order_by` and `filter_mode` will affect connection identity and thus produce new connection records.
|
|
589
|
+
* Conceptually, this means that we're specifying which arguments affect the output of the connection from the server, or in other words, which arguments are *actually* *filters*. If one of the connection arguments doesn't actually change the set of items that are returned from the server, or their ordering, then it isn't really a filter on the connection, and we don't need to identify the connection differently when that value changes. In our example, changing the `language` of the comments we request doesn't change the set of comments that are returned by the connection, so it is safe to exclude it from `filters`.
|
|
590
|
+
* This can also be useful if we know that any of the connection arguments will never change in our app, in which case it would also be safe to exclude from `filters`.
|
|
591
|
+
|
|
592
|
+
<DocsRating />
|