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,160 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: alias-directive
|
|
3
|
+
title: "@alias Directive"
|
|
4
|
+
slug: /guides/alias-directive/
|
|
5
|
+
description: Relay guide to @alias
|
|
6
|
+
keywords:
|
|
7
|
+
- alias
|
|
8
|
+
- directive
|
|
9
|
+
- fragment
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
The `@alias` directive allows you to expose a spread fragment — either a named fragment spread or an inline fragment — as a named field within your selection. This allows Relay to provide additional type safety in the case where your fragment’s type may not match the parent selection.
|
|
13
|
+
|
|
14
|
+
:::info
|
|
15
|
+
This document describes why the `@alias` directive was introduced, and how it can be used to improve type safety in your Relay applications. **To learn about its API, see the [API Reference](../api-reference/graphql/graphql-directives.mdx#alias).**
|
|
16
|
+
:::
|
|
17
|
+
|
|
18
|
+
Let's look at an example where `@alias` can be useful:
|
|
19
|
+
|
|
20
|
+
## Abstract Types
|
|
21
|
+
|
|
22
|
+
Imagine you have a component that renders information about a Viewer:
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
function MyViewer({viewerKey}) {
|
|
26
|
+
const {name} = useFragment(graphql`
|
|
27
|
+
fragment MyViewer on Viewer {
|
|
28
|
+
name @required(action: THROW)
|
|
29
|
+
}`, viewerKey);
|
|
30
|
+
|
|
31
|
+
return `My name is ${name}. That's ${name.length} letters long!`;
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
To use that component in a component that has a fragment on Node (which Viewer implements), you could write something like this:
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
function MyNode({nodeKey}) {
|
|
39
|
+
const node = useFragment(graphql`
|
|
40
|
+
fragment MyFragment on Node {
|
|
41
|
+
...MyViewer
|
|
42
|
+
}`, nodeKey);
|
|
43
|
+
|
|
44
|
+
return <MyViewer viewerKey={node} />
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Can you spot the problem? We don’t actually know that the node we are passing to `<MyViewer />` is actually a Viewer `<MyViewer />`. If `<MyNode />` tries to render a Comment — which also implements Node — we will get a runtime error in `<MyViewer />` because the field name is not present on Comment.
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
TypeError: Cannot read properties of undefined (reading 'length')
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Not only do we not get a type letting us know that about this potential issue, but even at runtime, there is no way to check if node implements Viewer because Viewer is an abstract type!
|
|
55
|
+
|
|
56
|
+
## Aliased Fragments
|
|
57
|
+
|
|
58
|
+
Aliased fragments can solve this problem. Here’s what `<MyNode />` would look like using them:
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
function MyNode({nodeKey}) {
|
|
62
|
+
const node = useFragment(graphql`
|
|
63
|
+
fragment MyFragment on Node {
|
|
64
|
+
...MyViewer @alias(as: "my_viewer")
|
|
65
|
+
}`, nodeKey);
|
|
66
|
+
|
|
67
|
+
// Relay returns the fragment key as its own nullable property
|
|
68
|
+
if(node.my_viewer == null) {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Because `my_viewer` is typed as nullable, Flow/TypeScript will
|
|
73
|
+
// show an error if you try to use the `my_viewer` without first
|
|
74
|
+
// performing a null check.
|
|
75
|
+
// VVVVVVVVVVVVVV
|
|
76
|
+
return <MyViewer viewerKey={node.my_viewer} />
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
With this approach, you can see that Relay exposes the fragment key as its own nullable property, which allows us to check that node actually implements Viewer and even allows Flow to enforce that the component handles the possibility!
|
|
81
|
+
|
|
82
|
+
## @skip and @include
|
|
83
|
+
|
|
84
|
+
A similar problem can occur when using `@skip` and `@include` directives on fragments. In order to safely use the spread fragment, you need to check if it was fetched. Historically this has required gaining access to the query variable that was used to determine if the fragment was skipped or included.
|
|
85
|
+
|
|
86
|
+
With `@alias`, you can now check if the fragment was fetched by simply assigning the fragment an alias, and checking if the alias is null:
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
function MyUser({userKey}) {
|
|
90
|
+
const user = useFragment(graphql`
|
|
91
|
+
fragment MyFragment on User {
|
|
92
|
+
...ConditionalData @skip(if: $someVar) @alias
|
|
93
|
+
}`, userKey);
|
|
94
|
+
|
|
95
|
+
if(user.ConditionalData == null) {
|
|
96
|
+
return "No data fetched";
|
|
97
|
+
}
|
|
98
|
+
return <ConditionalData userKey={user.ConditionalData} />
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Enforced Safety
|
|
103
|
+
|
|
104
|
+
We've outlined two different ways that fragments can be unsafe in Relay today without `@alias`. To help prevent runtime issues resulting from these unsafe edge cases, Relay requires that all conditionally fetched fragments are aliased.
|
|
105
|
+
|
|
106
|
+
To disable this validation in your project, you can disable the `enforce_fragment_alias_where_ambiguous` compiler feature flag for your project. If you need to enable incremental adoption of this enforcement, Relay exposes a directive `@dangerously_unaliased_fixme` which will suppress enforcement errors. This will allow you to enable the enforcement for all new spreads without first needing to migrate all existing issues.
|
|
107
|
+
|
|
108
|
+
The [Relay VSCode extension](../editor-support.mdx) offers quick fixes to add either `@alias` or `@dangerously_unaliased_fixme` to unsafe fragments, and the
|
|
109
|
+
[mark-dangerous-conditional-fragment-spreads](../codemods/#mark-dangerous-conditional-fragment-spreads) codemod can be used to apply `@dangerously_unaliased_fixme` across your entire project.
|
|
110
|
+
|
|
111
|
+
## Use with @required
|
|
112
|
+
|
|
113
|
+
`@alias` can be used with [`@required(action: NONE)`](./required-directive.mdx) to group together required fields. In the following example, we group `name` and `email` together as `requiredFields`. If either is null, that null will bubble up to, the `user.requiredFields` field, making it null. This allows us to perform a single check, without impacting the `id` field.
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
function MyUser({userKey}) {
|
|
117
|
+
const user = useFragment(graphql`
|
|
118
|
+
fragment MyFragment on User {
|
|
119
|
+
id
|
|
120
|
+
... @alias(as: "requiredFields") {
|
|
121
|
+
name @required(action: NONE)
|
|
122
|
+
email @required(action: NONE)
|
|
123
|
+
}
|
|
124
|
+
}`, userKey);
|
|
125
|
+
|
|
126
|
+
if(user.requiredFields == null) {
|
|
127
|
+
return `Missing required fields for user ${user.id}`;
|
|
128
|
+
}
|
|
129
|
+
return `Hello ${user.requiredFields.name} (${user.requiredFields.email}).!`;
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
:::note
|
|
134
|
+
Using `@required` on a fragment spread that has an `@alias` is not currently supported, but we may add support in the future.
|
|
135
|
+
:::
|
|
136
|
+
|
|
137
|
+
## Under the Hood
|
|
138
|
+
|
|
139
|
+
For people familiar with Relay, or curious to learn, here is a brief description of how this feature is implemented:
|
|
140
|
+
|
|
141
|
+
Under the hood, `@alias` is implemented entirely within Relay (compiler and runtime). It does not require any server support. The Relay compiler interprets the `@alias` directive, and generates types indicating that the fragment key, or inline fragment data, will be attached to the new field, rather than directly on the parent object. In the Relay runtime artifact, it wraps the fragment node with a new node indicating the name of the alias and additional information about the type of the fragment.
|
|
142
|
+
|
|
143
|
+
The Relay compiler also inserts an additional field into the spread which allows it to determine if the fragment has matched:
|
|
144
|
+
|
|
145
|
+
```graphql
|
|
146
|
+
fragment Foo on Node {
|
|
147
|
+
... on Viewer {
|
|
148
|
+
isViewer: __typename # <-- Relay inserts this
|
|
149
|
+
name
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Relay can now check for the existence of the `isViewer` field in the response to know if the fragment matched.
|
|
155
|
+
|
|
156
|
+
When Relay reads the content of your fragment out of the store using its runtime artifact, it uses this information to attach the fragment key to this new field, rather than attaching it directly to the parent object.
|
|
157
|
+
|
|
158
|
+
### Related
|
|
159
|
+
|
|
160
|
+
While `@alias` is a Relay-specific feature, it draws inspiration from fragment modularity as outlined in the GraphQL [RFC Fragment Modularity](https://github.com/graphql/graphql-wg/blob/main/rfcs/FragmentModularity.mdx).
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: catch-directive
|
|
3
|
+
title: '@catch Directive'
|
|
4
|
+
slug: /guides/catch-directive/
|
|
5
|
+
description: Relay guide to @catch
|
|
6
|
+
keywords:
|
|
7
|
+
- catch
|
|
8
|
+
- directive
|
|
9
|
+
- optional
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
import DocsRating from '@site/src/core/DocsRating';
|
|
13
|
+
|
|
14
|
+
The `@catch` directive can be added to fields, fragment/operation definitions or
|
|
15
|
+
aliased inline fragment spreads declare how exceptions and unexpected values
|
|
16
|
+
should be handled at runtime. Using `@catch` allows Relay to surface these error
|
|
17
|
+
states as part of your fragment/query/mutation data instead of a null value
|
|
18
|
+
(which has been the default behavior), or a runtime exception if
|
|
19
|
+
[`@throwOnFieldError`](./throw-on-field-error-directive.mdx) is being used.
|
|
20
|
+
|
|
21
|
+
:::tip
|
|
22
|
+
Both `@catch` and `@throwOnFieldError` only handle field errors in the
|
|
23
|
+
query/fragment/mutation in which they are used. They **do not** handle errors
|
|
24
|
+
related to fields in any spread fragments.
|
|
25
|
+
:::
|
|
26
|
+
|
|
27
|
+
## `to` Argument
|
|
28
|
+
|
|
29
|
+
The `@catch` directive accepts an optional `to` argument which has two options:
|
|
30
|
+
|
|
31
|
+
- `RESULT` (default): The value is returned as `{ ok: true, value: T } | { ok: false, errors: [error] }`. This allows you implement explicit field-granular error handling in your application.
|
|
32
|
+
- `NULL`: If an error is encountered within the `@catch`, the value will be replaced with `null`.
|
|
33
|
+
|
|
34
|
+
## Examples
|
|
35
|
+
|
|
36
|
+
If a `@catch` error is caught directly on the field that the error originated
|
|
37
|
+
from - the error is provided on that field. Here's an example:
|
|
38
|
+
|
|
39
|
+
```graphql
|
|
40
|
+
query MyQuery {
|
|
41
|
+
viewer {
|
|
42
|
+
name @catch
|
|
43
|
+
age
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
If `name` contains an error - it would be provided in the response data on the
|
|
49
|
+
`name` field - like so:
|
|
50
|
+
|
|
51
|
+
```js
|
|
52
|
+
{
|
|
53
|
+
viewer: {
|
|
54
|
+
name: {
|
|
55
|
+
ok: false,
|
|
56
|
+
errors: [{path: ['viewer', 'name']}]
|
|
57
|
+
}
|
|
58
|
+
age: 39
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
However, if `@catch` exists on one of the ancestors of a field, that error will
|
|
64
|
+
bubble up to there, like so:
|
|
65
|
+
|
|
66
|
+
```graphql
|
|
67
|
+
query MyQuery {
|
|
68
|
+
viewer @catch {
|
|
69
|
+
name
|
|
70
|
+
age
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
```js
|
|
76
|
+
{
|
|
77
|
+
viewer: {
|
|
78
|
+
ok: false,
|
|
79
|
+
errors: [{ path: ['viewer', 'name'] } ]
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Implications for nullability
|
|
85
|
+
|
|
86
|
+
Fields whose errors are explicitly handled by `@catch`, either by being
|
|
87
|
+
annotated with `@catch` or by being nested with a `@catch` ancestor will be
|
|
88
|
+
typed using their [Semantic Nullability](./semantic-nullability.mdx). In other
|
|
89
|
+
words, if a field has been marked as `@semanticNonNull` in the server schema to
|
|
90
|
+
indicate that it will only be null in the case of error, Relay will type that
|
|
91
|
+
field as non-nullable in its generated Flow/TypeScript types.
|
|
92
|
+
|
|
93
|
+
## What can be caught with `@catch`?
|
|
94
|
+
|
|
95
|
+
### Payload Field Errors
|
|
96
|
+
|
|
97
|
+
Payload [field
|
|
98
|
+
errors](https://spec.graphql.org/October2021/#sec-Errors.Field-errors) are
|
|
99
|
+
errors that occur as the result of a server-side exception while executing a
|
|
100
|
+
given field's resolver. In this case, the GraphQL specifies that the server must
|
|
101
|
+
provide a null value where a value should be, and a separate errors object.
|
|
102
|
+
|
|
103
|
+
When you `@catch` on a field, Relay takes those errors and provides them to you
|
|
104
|
+
in-line instead, making them easier to handle, and no longer invisible.
|
|
105
|
+
|
|
106
|
+
### @required(action: THROW) within an @catch
|
|
107
|
+
|
|
108
|
+
If you have an `@required(action: THROW)` with an ancestor that contains a
|
|
109
|
+
`@catch` - instead of throwing an exception, the `@required` error would bubble
|
|
110
|
+
up and be provided in the same way normal errors would. Here's an example:
|
|
111
|
+
|
|
112
|
+
```graphql
|
|
113
|
+
query MyQuery {
|
|
114
|
+
viewer @catch {
|
|
115
|
+
name @required(action: THROW)
|
|
116
|
+
age
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
```js
|
|
122
|
+
{
|
|
123
|
+
viewer: {
|
|
124
|
+
ok: false,
|
|
125
|
+
errors: [{ path: ["viewer", "name"] }]
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Missing Data in response
|
|
131
|
+
|
|
132
|
+
[Here is an example of where missing data may occur in Relay](https://relay.dev/docs/next/debugging/why-null/#graph-relationship-change)
|
|
133
|
+
|
|
134
|
+
If a field is expected to have a value, and that field is undefined - the field
|
|
135
|
+
is considered to be "missing data". This is also an unexpected state - and when
|
|
136
|
+
it happens with an `@catch` as an ancestor, it will also be caught like so:
|
|
137
|
+
|
|
138
|
+
```js
|
|
139
|
+
{
|
|
140
|
+
viewer: {
|
|
141
|
+
ok: false,
|
|
142
|
+
errors: [{ path: ["viewer", "name"] }]
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## How does `@catch` interact with `@throwOnFieldError`?
|
|
148
|
+
|
|
149
|
+
Using `@throwOnFieldError` enables fields to throw a JavaScript exception when a
|
|
150
|
+
field error occurs. By using `@catch` - you tell Relay that you don't want a
|
|
151
|
+
JavaScript exception in this case. Instead, you are requesting that the error be
|
|
152
|
+
provided in the data object, with the same behaviors and rules as are listed
|
|
153
|
+
above (including bubbling to a parent field).
|
|
154
|
+
|
|
155
|
+
It is important to note that you can still use @catch without
|
|
156
|
+
@throwOnFieldError. It will still provide you the error in the data object. But
|
|
157
|
+
other fields that are not under a `@catch` will still not throw - because
|
|
158
|
+
`@throwOnFieldError` would be missing.
|
|
159
|
+
|
|
160
|
+
Read more about `@throwOnFieldError`
|
|
161
|
+
[here](https://relay.dev/docs/next/api-reference/graphql-and-directives/#throwonfielderror-experimental).
|
|
162
|
+
|
|
163
|
+
## GraphQL Conf Talk
|
|
164
|
+
|
|
165
|
+
The Relay team gave a talk at GraphQL Conf 2024 about `@catch` and explicit error handling in Relay. You can watch it here:
|
|
166
|
+
|
|
167
|
+
<iframe src="https://www.youtube-nocookie.com/embed/_TSYKAtaK5A" width={640} height={360} allowFullScreen={true} frameBorder="0" />
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: client-schema-extensions
|
|
3
|
+
title: Client Schema Extensions
|
|
4
|
+
slug: /guides/client-schema-extensions/
|
|
5
|
+
description: Relay guide to client schema extensions
|
|
6
|
+
keywords:
|
|
7
|
+
- client
|
|
8
|
+
- schema
|
|
9
|
+
- extension
|
|
10
|
+
- commitLocalUpdate
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
import DocsRating from '@site/src/core/DocsRating';
|
|
14
|
+
|
|
15
|
+
:::note
|
|
16
|
+
See also [the local data updates](../../guided-tour/updating-data/local-data-updates/) and [client-only data](../../guided-tour/updating-data/client-only-data/) sections of the guided tour.
|
|
17
|
+
:::
|
|
18
|
+
|
|
19
|
+
Relay can be used to read and write local data, and act as a single source of truth for _all_ data in your client application.
|
|
20
|
+
|
|
21
|
+
The Relay Compiler fully supports client-side extensions of the schema, which allows you to define local fields and types.
|
|
22
|
+
|
|
23
|
+
## Table of Contents:
|
|
24
|
+
|
|
25
|
+
- [Extending the server schema](#extending-the-server-schema)
|
|
26
|
+
- [Querying local state](#querying-local-state)
|
|
27
|
+
- [Mutating local state](#mutating-local-state)
|
|
28
|
+
- [Initial local state](#initial-local-state)
|
|
29
|
+
|
|
30
|
+
## Extending the server schema
|
|
31
|
+
|
|
32
|
+
To extend the server schema, create a new `.graphql` file inside your `--src`
|
|
33
|
+
directory. Let's call it `./src/clientSchema.graphql`. This file needs to be
|
|
34
|
+
referenced in the `"schemaExtensions"` of your Relay config, either directly or
|
|
35
|
+
via its folder.
|
|
36
|
+
|
|
37
|
+
This schema describes what local data can be queried on the client.
|
|
38
|
+
It can even be used to extend an existing server schema.
|
|
39
|
+
|
|
40
|
+
For example, we can create a new type called `Note`:
|
|
41
|
+
|
|
42
|
+
```graphql
|
|
43
|
+
type Note {
|
|
44
|
+
id: ID!
|
|
45
|
+
title: String
|
|
46
|
+
body: String
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
And then extend the server schema type `User`, with a list of `Note`, called `notes`.
|
|
51
|
+
|
|
52
|
+
```graphql
|
|
53
|
+
extend type User {
|
|
54
|
+
notes: [Note]
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Querying local state
|
|
59
|
+
|
|
60
|
+
Accessing local data is no different from querying your GraphQL server, although you are required to include at least one server field in the query.
|
|
61
|
+
The field can be from the server schema, or it can be schema agnostic, like an introspection field (e.g. `__typename`).
|
|
62
|
+
|
|
63
|
+
Here, we use [useLazyLoadQuery](../../api-reference/use-lazy-load-query) to get the current `User` via the `viewer` field, along with their id, name and the local list of notes.
|
|
64
|
+
|
|
65
|
+
```javascript
|
|
66
|
+
// Example.js
|
|
67
|
+
import * as React from 'react';
|
|
68
|
+
import { useLazyLoadQuery, graphql } from 'react-relay';
|
|
69
|
+
|
|
70
|
+
const Example = (props) => {
|
|
71
|
+
const data = useLazyLoadQuery(graphql`
|
|
72
|
+
query ExampleQuery {
|
|
73
|
+
viewer {
|
|
74
|
+
id
|
|
75
|
+
name
|
|
76
|
+
notes {
|
|
77
|
+
id
|
|
78
|
+
title
|
|
79
|
+
body
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
`, {});
|
|
84
|
+
// ...
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Mutating local state
|
|
89
|
+
|
|
90
|
+
All local data lives in the [Relay Store](../../api-reference/store/).
|
|
91
|
+
|
|
92
|
+
Updating local state can be done with any `updater` function.
|
|
93
|
+
|
|
94
|
+
The `commitLocalUpdate` function is especially ideal for this, because writes to local state are usually executed outside of a mutation.
|
|
95
|
+
|
|
96
|
+
To build upon the previous example, let's try creating, updating and deleting a `Note` from the list of `notes` on `User`.
|
|
97
|
+
|
|
98
|
+
### Create
|
|
99
|
+
|
|
100
|
+
```javascript
|
|
101
|
+
import {commitLocalUpdate} from 'react-relay';
|
|
102
|
+
|
|
103
|
+
let tempID = 0;
|
|
104
|
+
|
|
105
|
+
function createUserNote(environment) {
|
|
106
|
+
commitLocalUpdate(environment, store => {
|
|
107
|
+
const user = store.getRoot().getLinkedRecord('viewer');
|
|
108
|
+
const userNoteRecords = user.getLinkedRecords('notes') || [];
|
|
109
|
+
|
|
110
|
+
// Create a unique ID.
|
|
111
|
+
const dataID = `client:Note:${tempID++}`;
|
|
112
|
+
|
|
113
|
+
//Create a new note record.
|
|
114
|
+
const newNoteRecord = store.create(dataID, 'Note');
|
|
115
|
+
|
|
116
|
+
// Add the record to the user's list of notes.
|
|
117
|
+
user.setLinkedRecords([...userNoteRecords, newNoteRecord], 'notes');
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Note that since this record will be rendered by the `ExampleQuery` via `useLazyLoadQuery`, the query data will automatically be retained and won't be garbage collected.
|
|
123
|
+
|
|
124
|
+
If no component is rendering the local data and you want to manually retain it, you can do so by calling `environment.retain()`:
|
|
125
|
+
|
|
126
|
+
```javascript
|
|
127
|
+
import {createOperationDescriptor, getRequest} from 'relay-runtime';
|
|
128
|
+
|
|
129
|
+
// Create a query that references that record
|
|
130
|
+
const localDataQuery = graphql`
|
|
131
|
+
query LocalDataQuery {
|
|
132
|
+
viewer {
|
|
133
|
+
notes {
|
|
134
|
+
__typename
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
`;
|
|
139
|
+
|
|
140
|
+
// Create an operation descriptor for the query
|
|
141
|
+
const request = getRequest(localDataQuery);
|
|
142
|
+
const operation = createOperationDescriptor(request, {} /* variables */);
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
// Tell Relay to retain this operation so any data referenced by it isn't garbage collected
|
|
146
|
+
// In this case, all the notes linked to the `viewer` will be retained
|
|
147
|
+
const disposable = environment.retain(operation);
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
// Whenever you don't need that data anymore and it's okay for Relay to garbage collect it,
|
|
151
|
+
// you can dispose of the retain
|
|
152
|
+
disposable.dispose();
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Update
|
|
156
|
+
|
|
157
|
+
```javascript
|
|
158
|
+
import {commitLocalUpdate} from 'react-relay';
|
|
159
|
+
|
|
160
|
+
function updateUserNote(environment, dataID, body, title) {
|
|
161
|
+
commitLocalUpdate(environment, store => {
|
|
162
|
+
const note = store.get(dataID);
|
|
163
|
+
|
|
164
|
+
note.setValue(body, 'body');
|
|
165
|
+
note.setValue(title, 'title')
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Delete
|
|
171
|
+
|
|
172
|
+
```javascript
|
|
173
|
+
import {commitLocalUpdate} from 'react-relay';
|
|
174
|
+
|
|
175
|
+
function deleteUserNote(environment, dataID) {
|
|
176
|
+
commitLocalUpdate(environment, store => {
|
|
177
|
+
const user = store.getRoot().getLinkedRecord('viewer');
|
|
178
|
+
const userNoteRecords = user.getLinkedRecords('notes');
|
|
179
|
+
|
|
180
|
+
// Remove the note from the list of user notes.
|
|
181
|
+
const newUserNoteRecords = userNoteRecords.filter(x => x.getDataID() !== dataID);
|
|
182
|
+
|
|
183
|
+
// Delete the note from the store.
|
|
184
|
+
store.delete(dataID);
|
|
185
|
+
|
|
186
|
+
// Set the new list of notes.
|
|
187
|
+
user.setLinkedRecords(newUserNoteRecords, 'notes');
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## Initial local state
|
|
193
|
+
|
|
194
|
+
All new client-side schema fields default to `undefined` value. Often however, you will want to set the initial state before querying local data.
|
|
195
|
+
You can use an updater function via `commitLocalUpdate` to prime local state.
|
|
196
|
+
|
|
197
|
+
```javascript
|
|
198
|
+
import {commitLocalUpdate} from 'react-relay';
|
|
199
|
+
|
|
200
|
+
commitLocalUpdate(environment, store => {
|
|
201
|
+
const user = store.getRoot().getLinkedRecord('viewer');
|
|
202
|
+
|
|
203
|
+
// initialize user notes to an empty array.
|
|
204
|
+
user.setLinkedRecords([], 'notes');
|
|
205
|
+
});
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
<DocsRating />
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: codemods
|
|
3
|
+
title: Codemods
|
|
4
|
+
slug: /guides/codemods/
|
|
5
|
+
description: Relay guide to codemods
|
|
6
|
+
keywords:
|
|
7
|
+
- codemod
|
|
8
|
+
- codemods
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
import DocsRating from '@site/src/core/DocsRating'; import {FbInternalOnly,
|
|
12
|
+
OssOnly, fbContent} from 'docusaurus-plugin-internaldocs-fb/internal'; import
|
|
13
|
+
Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem';
|
|
14
|
+
|
|
15
|
+
The Relay compiler has the ability to make changes across the source files of
|
|
16
|
+
your projects with the use of codemods. You can see the list of codemods
|
|
17
|
+
available by running the Relay compiler's `codemod` command:
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
> relay codemod --help
|
|
21
|
+
Apply codemod (verification with auto-applied fixes)
|
|
22
|
+
|
|
23
|
+
Usage: relay codemod [OPTIONS] [CONFIG] <COMMAND>
|
|
24
|
+
|
|
25
|
+
Commands:
|
|
26
|
+
mark-dangerous-conditional-fragment-spreads Marks unaliased conditional fragment spreads as @dangerously_unaliased_fixme
|
|
27
|
+
remove-unnecessary-required-directives Removes @required directives from non-null fields within @throwOnFieldError fragments and operations.
|
|
28
|
+
fix-all Runs all Relay compiler transforms and fixes all fixable diagnostics
|
|
29
|
+
help Print this message or the help of the given subcommand(s)
|
|
30
|
+
|
|
31
|
+
Arguments:
|
|
32
|
+
[CONFIG] Compile using this config file. If not provided, searches for a config in package.json under the `relay` key or `relay.config.json` files among other up from the current working directory
|
|
33
|
+
|
|
34
|
+
Options:
|
|
35
|
+
-p, --project <project> Compile only this project. You can pass this argument multiple times. to compile multiple projects. If excluded, all projects will be compiled
|
|
36
|
+
-h, --help Print help
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Available codemods
|
|
40
|
+
|
|
41
|
+
The compiler currently has these available codemods:
|
|
42
|
+
|
|
43
|
+
### mark-dangerous-conditional-fragment-spreads
|
|
44
|
+
|
|
45
|
+
This codemod finds fragment spreads that are _dangerously unaliased_; that is,
|
|
46
|
+
the fragment might not be fetched due to a directive such as `@skip` or its
|
|
47
|
+
inclusion on a mismatched type within a union. If such a conditional fragment is
|
|
48
|
+
not aliased with [`@alias`](../alias-directive/), there is no way for the
|
|
49
|
+
resulting generated Flow or TypeScript types to reflect its nullability. This
|
|
50
|
+
codemod will add the `@dangerously_unaliased_fixme` directive to such fragment
|
|
51
|
+
spreads, indicating to developers that there is a problem to be fixed. After
|
|
52
|
+
applying this codemod, the `enforce_fragment_alias_where_ambiguous` feature flag
|
|
53
|
+
can be enabled, which will ensure any future ambiguous fragment spreads must be
|
|
54
|
+
aliased.
|
|
55
|
+
|
|
56
|
+
Since this codemod can potentially modify many files, there is an optional
|
|
57
|
+
`--rollout-percentage` parameter (shorthand: `-r`) which, if used alongside the
|
|
58
|
+
`enforce_fragment_alias_where_ambiguous` feature flag in rollout mode, allows
|
|
59
|
+
progressive codemod and enforcement of this validation.
|
|
60
|
+
|
|
61
|
+
### remove-unnecessary-required-directives
|
|
62
|
+
|
|
63
|
+
Removes [@required](../api-reference/graphql/graphql-directives.mdx#required)
|
|
64
|
+
directives from non-null fields within
|
|
65
|
+
[@throwOnFieldError](../api-reference/graphql/graphql-directives.mdx#throwonfielderror)
|
|
66
|
+
fragments and operations, or linked fields with
|
|
67
|
+
[`@catch`](../guides/catch-directive.mdx), where the compiler is certain that the
|
|
68
|
+
directive does not change the generated types for the data being fetched.
|
|
69
|
+
|
|
70
|
+
### fix-all
|
|
71
|
+
|
|
72
|
+
Runs all Relay compiler transforms and automatically applies fixes for every
|
|
73
|
+
fixable diagnostic. This is a convenient catch-all codemod to apply when
|
|
74
|
+
upgrading Relay versions — run it after updating the package to repair any
|
|
75
|
+
issues the compiler now flags:
|
|
76
|
+
|
|
77
|
+
```sh
|
|
78
|
+
relay codemod fix-all
|
|
79
|
+
```
|