From cacce8c5aadd6718cb7953235581a7e045392ce2 Mon Sep 17 00:00:00 2001 From: Jan Kassens Date: Wed, 14 Apr 2021 08:42:36 -0700 Subject: [PATCH] remove space form code sample blocks Reviewed By: alunyov Differential Revision: D27765591 fbshipit-source-id: 66a2f4922e6d01e1cae7fad7cd78f164fa629654 --- .../graphql/graphql-directives.md | 12 -- .../docs/api-reference/relay-runtime/store.md | 92 --------- .../getting-started/installation-and-setup.md | 4 +- website/docs/glossary/glossary.md | 20 +- .../list-data/advanced-pagination.md | 1 - .../docs/guided-tour/rendering/fragments.md | 1 - .../docs/guided-tour/rendering/variables.md | 2 +- .../rendering-partially-cached-data.md | 4 +- .../updating-data/client-only-data.md | 3 - .../docs/guides/client-schema-extensions.md | 16 -- website/docs/guides/compiler.md | 12 -- .../guides/graphql-server-specification.md | 50 +---- website/docs/guides/network-layer.md | 2 - website/docs/guides/persisted-queries.md | 26 +-- .../docs/guides/testing-relay-components.md | 13 +- .../testing-relay-with-preloaded-queries.md | 8 +- website/docs/guides/type-emission.md | 28 +-- .../compiler-architecture.md | 5 - .../runtime-architecture.md | 1 - .../thinking-in-graphql.md | 62 ++---- .../thinking-in-relay.md | 16 +- .../Classic-APIReference-Container.md | 17 -- .../Classic-APIReference-GraphQLMutation.md | 11 - .../Classic-APIReference-Mutation.md | 20 -- .../Classic-APIReference-PropTypes.md | 1 - .../Classic-APIReference-QL.md | 5 - .../Classic-APIReference-Relay.md | 8 - .../Classic-APIReference-Route.md | 7 - .../Classic-APIReference-Store.md | 3 - .../Classic-Guides-Containers.md | 5 - .../Classic-Guides-Mutations.md | 13 -- .../Classic-Guides-NetworkLayer.md | 5 - .../Classic-Guides-RootContainer.md | 1 - .../version-classic/Classic-Guides-Routes.md | 8 - .../Classic-Interfaces-MutationRequest.md | 2 - .../Classic-Interfaces-NetworkLayer.md | 3 - .../Classic-Interfaces-QueryRequest.md | 1 - ...inciplesAndArchitecture-ThinkingInRelay.md | 3 - .../GraphQL-ServerSpecification.md | 23 --- .../Introduction-InstallationAndSetup.md | 10 +- .../Modern-GraphQLInRelay.md | 31 +-- ...ciplesAndArchitecture-ThinkingInGraphQL.md | 21 -- ...inciplesAndArchitecture-ThinkingInRelay.md | 3 - .../RelayHooks-AGuidedTourOfRelay.md | 192 +----------------- .../RelayHooks-ApiReference.md | 25 --- .../RelayHooks-StepByStep.md | 9 - .../GraphQL-ServerSpecification.md | 23 --- .../Introduction-InstallationAndSetup.md | 10 +- .../Introduction-QuickStartGuide.md | 28 --- .../Modern-ConvertingMutations.md | 12 -- .../Modern-FragmentContainer.md | 24 --- .../version-v1.4.1/Modern-GraphQLInRelay.md | 17 -- .../Modern-LocalStateManagement.md | 16 -- .../version-v1.4.1/Modern-MigrationSetup.md | 6 - .../version-v1.4.1/Modern-Mutations.md | 14 -- .../version-v1.4.1/Modern-NetworkLayer.md | 2 - .../Modern-PaginationContainer.md | 15 -- .../version-v1.4.1/Modern-PersistedQueries.md | 26 +-- .../version-v1.4.1/Modern-QueryRenderer.md | 2 - .../version-v1.4.1/Modern-RefetchContainer.md | 9 - .../version-v1.4.1/Modern-RelayCompat.md | 2 - .../version-v1.4.1/Modern-RelayEnvironment.md | 4 - .../version-v1.4.1/Modern-RelayStore.md | 76 ------- .../version-v1.4.1/Modern-Subscriptions.md | 6 - .../Modern-TestingRelayComponents.md | 22 -- .../version-v1.4.1/Modern-TypeEmission.md | 9 - .../Modern-UpgradingSetVariables.md | 3 - .../version-v1.4.1/Modern-fetchQuery.md | 2 - .../PrinciplesAndArchitecture-Compiler.md | 2 - .../PrinciplesAndArchitecture-Runtime.md | 1 - ...ciplesAndArchitecture-ThinkingInGraphQL.md | 21 -- ...inciplesAndArchitecture-ThinkingInRelay.md | 3 - .../GraphQL-ServerSpecification.md | 23 --- .../Introduction-InstallationAndSetup.md | 10 +- .../Introduction-QuickStartGuide.md | 28 --- .../Modern-ConvertingMutations.md | 12 -- .../Modern-FragmentContainer.md | 24 --- .../version-v1.5.0/Modern-GraphQLInRelay.md | 17 -- .../Modern-LocalStateManagement.md | 16 -- .../version-v1.5.0/Modern-MigrationSetup.md | 6 - .../version-v1.5.0/Modern-Mutations.md | 14 -- .../version-v1.5.0/Modern-NetworkLayer.md | 2 - .../Modern-PaginationContainer.md | 15 -- .../version-v1.5.0/Modern-PersistedQueries.md | 26 +-- .../version-v1.5.0/Modern-QueryRenderer.md | 2 - .../version-v1.5.0/Modern-RefetchContainer.md | 9 - .../version-v1.5.0/Modern-RelayCompat.md | 2 - .../version-v1.5.0/Modern-RelayEnvironment.md | 4 - .../version-v1.5.0/Modern-RelayStore.md | 76 ------- .../version-v1.5.0/Modern-Subscriptions.md | 6 - .../Modern-TestingRelayComponents.md | 22 -- .../version-v1.5.0/Modern-TypeEmission.md | 9 - .../Modern-UpgradingSetVariables.md | 3 - .../version-v1.5.0/Modern-fetchQuery.md | 2 - .../PrinciplesAndArchitecture-Compiler.md | 2 - .../PrinciplesAndArchitecture-Runtime.md | 1 - ...ciplesAndArchitecture-ThinkingInGraphQL.md | 21 -- ...inciplesAndArchitecture-ThinkingInRelay.md | 3 - .../GraphQL-ServerSpecification.md | 23 --- .../Introduction-InstallationAndSetup.md | 10 +- .../Introduction-QuickStartGuide.md | 28 --- .../Modern-ConvertingMutations.md | 12 -- .../Modern-FragmentContainer.md | 24 --- .../version-v1.6.0/Modern-GraphQLInRelay.md | 17 -- .../Modern-LocalStateManagement.md | 16 -- .../version-v1.6.0/Modern-MigrationSetup.md | 6 - .../version-v1.6.0/Modern-Mutations.md | 14 -- .../version-v1.6.0/Modern-NetworkLayer.md | 2 - .../Modern-PaginationContainer.md | 15 -- .../version-v1.6.0/Modern-PersistedQueries.md | 26 +-- .../version-v1.6.0/Modern-QueryRenderer.md | 2 - .../version-v1.6.0/Modern-RefetchContainer.md | 9 - .../version-v1.6.0/Modern-RelayCompat.md | 2 - .../version-v1.6.0/Modern-RelayEnvironment.md | 4 - .../version-v1.6.0/Modern-RelayStore.md | 76 ------- .../version-v1.6.0/Modern-Subscriptions.md | 6 - .../Modern-TestingRelayComponents.md | 22 -- .../version-v1.6.0/Modern-TypeEmission.md | 9 - .../Modern-UpgradingSetVariables.md | 3 - .../version-v1.6.0/Modern-fetchQuery.md | 2 - .../PrinciplesAndArchitecture-Compiler.md | 2 - .../PrinciplesAndArchitecture-Runtime.md | 1 - ...ciplesAndArchitecture-ThinkingInGraphQL.md | 21 -- ...inciplesAndArchitecture-ThinkingInRelay.md | 3 - .../GraphQL-ServerSpecification.md | 23 --- .../Introduction-InstallationAndSetup.md | 10 +- .../Introduction-QuickStartGuide.md | 28 --- .../Modern-ConvertingMutations.md | 12 -- .../Modern-FragmentContainer.md | 24 --- .../version-v1.6.1/Modern-GraphQLInRelay.md | 17 -- .../Modern-LocalStateManagement.md | 16 -- .../version-v1.6.1/Modern-MigrationSetup.md | 6 - .../version-v1.6.1/Modern-Mutations.md | 14 -- .../version-v1.6.1/Modern-NetworkLayer.md | 2 - .../Modern-PaginationContainer.md | 15 -- .../version-v1.6.1/Modern-PersistedQueries.md | 26 +-- .../version-v1.6.1/Modern-QueryRenderer.md | 2 - .../version-v1.6.1/Modern-RefetchContainer.md | 9 - .../version-v1.6.1/Modern-RelayCompat.md | 2 - .../version-v1.6.1/Modern-RelayEnvironment.md | 4 - .../version-v1.6.1/Modern-RelayStore.md | 76 ------- .../version-v1.6.1/Modern-Subscriptions.md | 6 - .../Modern-TestingRelayComponents.md | 22 -- .../version-v1.6.1/Modern-TypeEmission.md | 9 - .../Modern-UpgradingSetVariables.md | 3 - .../version-v1.6.1/Modern-fetchQuery.md | 2 - .../PrinciplesAndArchitecture-Compiler.md | 2 - .../PrinciplesAndArchitecture-Runtime.md | 1 - ...ciplesAndArchitecture-ThinkingInGraphQL.md | 21 -- ...inciplesAndArchitecture-ThinkingInRelay.md | 3 - .../GraphQL-ServerSpecification.md | 23 --- .../Introduction-InstallationAndSetup.md | 10 +- .../Introduction-QuickStartGuide.md | 28 --- .../Modern-ConvertingMutations.md | 12 -- .../Modern-FragmentContainer.md | 24 --- .../version-v1.6.2/Modern-GraphQLInRelay.md | 17 -- .../Modern-LocalStateManagement.md | 16 -- .../version-v1.6.2/Modern-MigrationSetup.md | 6 - .../version-v1.6.2/Modern-Mutations.md | 14 -- .../version-v1.6.2/Modern-NetworkLayer.md | 2 - .../Modern-PaginationContainer.md | 15 -- .../version-v1.6.2/Modern-PersistedQueries.md | 26 +-- .../version-v1.6.2/Modern-QueryRenderer.md | 2 - .../version-v1.6.2/Modern-RefetchContainer.md | 9 - .../version-v1.6.2/Modern-RelayCompat.md | 2 - .../version-v1.6.2/Modern-RelayEnvironment.md | 4 - .../version-v1.6.2/Modern-RelayStore.md | 76 ------- .../version-v1.6.2/Modern-Subscriptions.md | 6 - .../Modern-TestingRelayComponents.md | 22 -- .../version-v1.6.2/Modern-TypeEmission.md | 9 - .../Modern-UpgradingSetVariables.md | 3 - .../version-v1.6.2/Modern-fetchQuery.md | 2 - .../PrinciplesAndArchitecture-Compiler.md | 2 - .../PrinciplesAndArchitecture-Runtime.md | 1 - ...ciplesAndArchitecture-ThinkingInGraphQL.md | 21 -- ...inciplesAndArchitecture-ThinkingInRelay.md | 3 - .../GraphQL-ServerSpecification.md | 23 --- .../Introduction-InstallationAndSetup.md | 16 +- .../Introduction-QuickStartGuide.md | 28 --- .../Modern-ConvertingMutations.md | 12 -- .../Modern-FragmentContainer.md | 24 --- .../version-v1.7.0/Modern-GraphQLInRelay.md | 17 -- .../Modern-LocalStateManagement.md | 16 -- .../version-v1.7.0/Modern-MigrationSetup.md | 6 - .../version-v1.7.0/Modern-Mutations.md | 14 -- .../version-v1.7.0/Modern-NetworkLayer.md | 4 - .../Modern-PaginationContainer.md | 15 -- .../version-v1.7.0/Modern-PersistedQueries.md | 26 +-- .../version-v1.7.0/Modern-QueryRenderer.md | 2 - .../version-v1.7.0/Modern-RefetchContainer.md | 9 - .../version-v1.7.0/Modern-RelayCompat.md | 2 - .../version-v1.7.0/Modern-RelayEnvironment.md | 4 - .../version-v1.7.0/Modern-RelayStore.md | 76 ------- .../version-v1.7.0/Modern-Subscriptions.md | 6 - .../Modern-TestingRelayComponents.md | 22 -- .../version-v1.7.0/Modern-TypeEmission.md | 9 - .../Modern-UpgradingSetVariables.md | 3 - .../version-v1.7.0/Modern-fetchQuery.md | 2 - .../PrinciplesAndArchitecture-Compiler.md | 2 - .../PrinciplesAndArchitecture-Runtime.md | 1 - ...ciplesAndArchitecture-ThinkingInGraphQL.md | 21 -- ...inciplesAndArchitecture-ThinkingInRelay.md | 3 - .../GraphQL-ServerSpecification.md | 23 --- .../Introduction-InstallationAndSetup.md | 20 +- .../Introduction-QuickStartGuide.md | 28 --- .../Modern-ConvertingMutations.md | 12 -- .../Modern-FragmentContainer.md | 16 -- .../version-v10.0.0/Modern-GraphQLInRelay.md | 31 +-- .../Modern-LocalStateManagement.md | 16 -- .../version-v10.0.0/Modern-MigrationSetup.md | 6 - .../version-v10.0.0/Modern-Mutations.md | 14 -- .../version-v10.0.0/Modern-NetworkLayer.md | 4 - .../Modern-PaginationContainer.md | 15 -- .../Modern-PersistedQueries.md | 26 +-- .../version-v10.0.0/Modern-QueryRenderer.md | 2 - .../Modern-RefetchContainer.md | 9 - .../version-v10.0.0/Modern-RelayCompat.md | 2 - .../Modern-RelayEnvironment.md | 4 - .../version-v10.0.0/Modern-RelayStore.md | 82 -------- .../version-v10.0.0/Modern-Subscriptions.md | 6 - .../Modern-TestingRelayComponents.md | 22 -- .../version-v10.0.0/Modern-TypeEmission.md | 9 - .../Modern-UpgradingSetVariables.md | 3 - .../version-v10.0.0/Modern-fetchQuery.md | 2 - .../PrinciplesAndArchitecture-Compiler.md | 2 - .../PrinciplesAndArchitecture-Runtime.md | 1 - ...ciplesAndArchitecture-ThinkingInGraphQL.md | 21 -- ...inciplesAndArchitecture-ThinkingInRelay.md | 3 - .../GraphQL-ServerSpecification.md | 23 --- .../Introduction-InstallationAndSetup.md | 20 +- .../Introduction-QuickStartGuide.md | 28 --- .../Modern-ConvertingMutations.md | 12 -- .../Modern-FragmentContainer.md | 16 -- .../version-v10.0.1/Modern-GraphQLInRelay.md | 31 +-- .../Modern-LocalStateManagement.md | 16 -- .../version-v10.0.1/Modern-MigrationSetup.md | 6 - .../version-v10.0.1/Modern-Mutations.md | 14 -- .../version-v10.0.1/Modern-NetworkLayer.md | 4 - .../Modern-PaginationContainer.md | 15 -- .../Modern-PersistedQueries.md | 26 +-- .../version-v10.0.1/Modern-QueryRenderer.md | 2 - .../Modern-RefetchContainer.md | 9 - .../version-v10.0.1/Modern-RelayCompat.md | 2 - .../Modern-RelayEnvironment.md | 4 - .../version-v10.0.1/Modern-RelayStore.md | 82 -------- .../version-v10.0.1/Modern-Subscriptions.md | 7 - .../Modern-TestingRelayComponents.md | 22 -- .../version-v10.0.1/Modern-TypeEmission.md | 9 - .../Modern-UpgradingSetVariables.md | 3 - .../version-v10.0.1/Modern-fetchQuery.md | 2 - .../PrinciplesAndArchitecture-Compiler.md | 2 - .../PrinciplesAndArchitecture-Runtime.md | 1 - ...ciplesAndArchitecture-ThinkingInGraphQL.md | 21 -- ...inciplesAndArchitecture-ThinkingInRelay.md | 3 - .../GraphQL-ServerSpecification.md | 23 --- .../Introduction-InstallationAndSetup.md | 20 +- .../Introduction-QuickStartGuide.md | 28 --- .../Modern-ConvertingMutations.md | 12 -- .../Modern-FragmentContainer.md | 16 -- .../version-v10.1.0/Modern-GraphQLInRelay.md | 31 +-- .../Modern-LocalStateManagement.md | 16 -- .../version-v10.1.0/Modern-MigrationSetup.md | 6 - .../version-v10.1.0/Modern-Mutations.md | 14 -- .../version-v10.1.0/Modern-NetworkLayer.md | 4 - .../Modern-PaginationContainer.md | 15 -- .../Modern-PersistedQueries.md | 26 +-- .../version-v10.1.0/Modern-QueryRenderer.md | 2 - .../Modern-RefetchContainer.md | 9 - .../version-v10.1.0/Modern-RelayCompat.md | 2 - .../Modern-RelayEnvironment.md | 4 - .../version-v10.1.0/Modern-RelayStore.md | 82 -------- .../version-v10.1.0/Modern-Subscriptions.md | 7 - .../Modern-TestingRelayComponents.md | 22 -- .../version-v10.1.0/Modern-TypeEmission.md | 9 - .../Modern-UpgradingSetVariables.md | 3 - .../version-v10.1.0/Modern-fetchQuery.md | 2 - .../PrinciplesAndArchitecture-Compiler.md | 2 - .../PrinciplesAndArchitecture-Runtime.md | 1 - ...ciplesAndArchitecture-ThinkingInGraphQL.md | 21 -- ...inciplesAndArchitecture-ThinkingInRelay.md | 3 - .../GraphQL-ServerSpecification.md | 23 --- .../Introduction-InstallationAndSetup.md | 20 +- .../Introduction-QuickStartGuide.md | 28 --- .../Modern-ConvertingMutations.md | 12 -- .../Modern-FragmentContainer.md | 16 -- .../version-v10.1.1/Modern-GraphQLInRelay.md | 31 +-- .../Modern-LocalStateManagement.md | 16 -- .../version-v10.1.1/Modern-MigrationSetup.md | 6 - .../version-v10.1.1/Modern-Mutations.md | 14 -- .../version-v10.1.1/Modern-NetworkLayer.md | 4 - .../Modern-PaginationContainer.md | 15 -- .../Modern-PersistedQueries.md | 26 +-- .../version-v10.1.1/Modern-QueryRenderer.md | 2 - .../Modern-RefetchContainer.md | 9 - .../version-v10.1.1/Modern-RelayCompat.md | 2 - .../Modern-RelayEnvironment.md | 4 - .../version-v10.1.1/Modern-RelayStore.md | 82 -------- .../version-v10.1.1/Modern-Subscriptions.md | 7 - .../Modern-TestingRelayComponents.md | 22 -- .../version-v10.1.1/Modern-TypeEmission.md | 9 - .../Modern-UpgradingSetVariables.md | 3 - .../version-v10.1.1/Modern-fetchQuery.md | 2 - .../PrinciplesAndArchitecture-Compiler.md | 2 - .../PrinciplesAndArchitecture-Runtime.md | 1 - ...ciplesAndArchitecture-ThinkingInGraphQL.md | 21 -- ...inciplesAndArchitecture-ThinkingInRelay.md | 3 - .../GraphQL-ServerSpecification.md | 23 --- .../Introduction-InstallationAndSetup.md | 20 +- .../Introduction-QuickStartGuide.md | 28 --- .../Modern-ConvertingMutations.md | 12 -- .../Modern-FragmentContainer.md | 16 -- .../version-v10.1.2/Modern-GraphQLInRelay.md | 31 +-- .../Modern-LocalStateManagement.md | 16 -- .../version-v10.1.2/Modern-MigrationSetup.md | 6 - .../version-v10.1.2/Modern-Mutations.md | 14 -- .../version-v10.1.2/Modern-NetworkLayer.md | 4 - .../Modern-PaginationContainer.md | 15 -- .../Modern-PersistedQueries.md | 26 +-- .../version-v10.1.2/Modern-QueryRenderer.md | 2 - .../Modern-RefetchContainer.md | 9 - .../version-v10.1.2/Modern-RelayCompat.md | 2 - .../Modern-RelayEnvironment.md | 4 - .../version-v10.1.2/Modern-RelayStore.md | 82 -------- .../version-v10.1.2/Modern-Subscriptions.md | 7 - .../Modern-TestingRelayComponents.md | 22 -- .../version-v10.1.2/Modern-TypeEmission.md | 9 - .../Modern-UpgradingSetVariables.md | 3 - .../version-v10.1.2/Modern-fetchQuery.md | 2 - .../PrinciplesAndArchitecture-Compiler.md | 2 - .../PrinciplesAndArchitecture-Runtime.md | 1 - ...ciplesAndArchitecture-ThinkingInGraphQL.md | 21 -- ...inciplesAndArchitecture-ThinkingInRelay.md | 3 - .../GraphQL-ServerSpecification.md | 23 --- .../Introduction-InstallationAndSetup.md | 20 +- .../Introduction-QuickStartGuide.md | 28 --- .../Modern-ConvertingMutations.md | 12 -- .../Modern-FragmentContainer.md | 16 -- .../version-v10.1.3/Modern-GraphQLInRelay.md | 31 +-- .../Modern-LocalStateManagement.md | 16 -- .../version-v10.1.3/Modern-MigrationSetup.md | 6 - .../version-v10.1.3/Modern-Mutations.md | 14 -- .../version-v10.1.3/Modern-NetworkLayer.md | 4 - .../Modern-PaginationContainer.md | 15 -- .../Modern-PersistedQueries.md | 26 +-- .../version-v10.1.3/Modern-QueryRenderer.md | 2 - .../Modern-RefetchContainer.md | 9 - .../version-v10.1.3/Modern-RelayCompat.md | 2 - .../Modern-RelayEnvironment.md | 4 - .../version-v10.1.3/Modern-RelayStore.md | 87 -------- .../version-v10.1.3/Modern-Subscriptions.md | 7 - .../Modern-TestingRelayComponents.md | 22 -- .../version-v10.1.3/Modern-TypeEmission.md | 9 - .../Modern-UpgradingSetVariables.md | 3 - .../version-v10.1.3/Modern-fetchQuery.md | 2 - .../PrinciplesAndArchitecture-Compiler.md | 2 - .../PrinciplesAndArchitecture-Runtime.md | 1 - ...ciplesAndArchitecture-ThinkingInGraphQL.md | 21 -- ...inciplesAndArchitecture-ThinkingInRelay.md | 3 - .../graphql/graphql-directives.md | 12 -- .../api-reference/relay-runtime/store.md | 87 -------- .../getting-started/installation-and-setup.md | 4 +- .../version-v11.0.0/glossary/glossary.md | 6 +- .../list-data/advanced-pagination.md | 1 - .../guided-tour/rendering/fragments.md | 1 - .../rendering-partially-cached-data.md | 4 +- .../updating-data/client-only-data.md | 3 - .../guides/client-schema-extensions.md | 16 -- .../version-v11.0.0/guides/compiler.md | 9 - .../guides/graphql-server-specification.md | 18 -- .../version-v11.0.0/guides/network-layer.md | 2 - .../guides/persisted-queries.md | 26 +-- .../guides/testing-relay-components.md | 13 +- .../testing-relay-with-preloaded-queries.md | 8 +- .../version-v11.0.0/guides/type-emission.md | 1 - .../compiler-architecture.md | 2 - .../runtime-architecture.md | 1 - .../thinking-in-graphql.md | 21 -- .../thinking-in-relay.md | 16 +- .../GraphQL-ServerSpecification.md | 23 --- .../Introduction-InstallationAndSetup.md | 16 +- .../Introduction-QuickStartGuide.md | 28 --- .../Modern-ConvertingMutations.md | 12 -- .../Modern-FragmentContainer.md | 24 --- .../version-v2.0.0/Modern-GraphQLInRelay.md | 21 +- .../Modern-LocalStateManagement.md | 16 -- .../version-v2.0.0/Modern-MigrationSetup.md | 6 - .../version-v2.0.0/Modern-Mutations.md | 14 -- .../version-v2.0.0/Modern-NetworkLayer.md | 4 - .../Modern-PaginationContainer.md | 15 -- .../version-v2.0.0/Modern-PersistedQueries.md | 26 +-- .../version-v2.0.0/Modern-QueryRenderer.md | 2 - .../version-v2.0.0/Modern-RefetchContainer.md | 9 - .../version-v2.0.0/Modern-RelayCompat.md | 2 - .../version-v2.0.0/Modern-RelayEnvironment.md | 4 - .../version-v2.0.0/Modern-RelayStore.md | 76 ------- .../version-v2.0.0/Modern-Subscriptions.md | 6 - .../Modern-TestingRelayComponents.md | 22 -- .../version-v2.0.0/Modern-TypeEmission.md | 9 - .../Modern-UpgradingSetVariables.md | 3 - .../version-v2.0.0/Modern-fetchQuery.md | 2 - .../PrinciplesAndArchitecture-Compiler.md | 2 - .../PrinciplesAndArchitecture-Runtime.md | 1 - ...ciplesAndArchitecture-ThinkingInGraphQL.md | 21 -- ...inciplesAndArchitecture-ThinkingInRelay.md | 3 - .../GraphQL-ServerSpecification.md | 23 --- .../Introduction-InstallationAndSetup.md | 16 +- .../Introduction-QuickStartGuide.md | 28 --- .../Modern-ConvertingMutations.md | 12 -- .../Modern-FragmentContainer.md | 24 --- .../version-v3.0.0/Modern-GraphQLInRelay.md | 21 +- .../Modern-LocalStateManagement.md | 16 -- .../version-v3.0.0/Modern-MigrationSetup.md | 6 - .../version-v3.0.0/Modern-Mutations.md | 14 -- .../version-v3.0.0/Modern-NetworkLayer.md | 4 - .../Modern-PaginationContainer.md | 15 -- .../version-v3.0.0/Modern-PersistedQueries.md | 26 +-- .../version-v3.0.0/Modern-QueryRenderer.md | 2 - .../version-v3.0.0/Modern-RefetchContainer.md | 9 - .../version-v3.0.0/Modern-RelayCompat.md | 2 - .../version-v3.0.0/Modern-RelayEnvironment.md | 4 - .../version-v3.0.0/Modern-RelayStore.md | 76 ------- .../version-v3.0.0/Modern-Subscriptions.md | 6 - .../Modern-TestingRelayComponents.md | 22 -- .../version-v3.0.0/Modern-TypeEmission.md | 9 - .../Modern-UpgradingSetVariables.md | 3 - .../version-v3.0.0/Modern-fetchQuery.md | 2 - .../PrinciplesAndArchitecture-Compiler.md | 2 - .../PrinciplesAndArchitecture-Runtime.md | 1 - ...ciplesAndArchitecture-ThinkingInGraphQL.md | 21 -- ...inciplesAndArchitecture-ThinkingInRelay.md | 3 - .../GraphQL-ServerSpecification.md | 23 --- .../Introduction-InstallationAndSetup.md | 17 +- .../Introduction-QuickStartGuide.md | 28 --- .../Modern-ConvertingMutations.md | 12 -- .../Modern-FragmentContainer.md | 16 -- .../version-v4.0.0/Modern-GraphQLInRelay.md | 27 +-- .../Modern-LocalStateManagement.md | 14 -- .../version-v4.0.0/Modern-MigrationSetup.md | 6 - .../version-v4.0.0/Modern-Mutations.md | 14 -- .../version-v4.0.0/Modern-NetworkLayer.md | 4 - .../Modern-PaginationContainer.md | 15 -- .../version-v4.0.0/Modern-PersistedQueries.md | 26 +-- .../version-v4.0.0/Modern-QueryRenderer.md | 2 - .../version-v4.0.0/Modern-RefetchContainer.md | 9 - .../version-v4.0.0/Modern-RelayCompat.md | 2 - .../version-v4.0.0/Modern-RelayEnvironment.md | 4 - .../version-v4.0.0/Modern-RelayStore.md | 76 ------- .../version-v4.0.0/Modern-Subscriptions.md | 6 - .../Modern-TestingRelayComponents.md | 22 -- .../version-v4.0.0/Modern-TypeEmission.md | 9 - .../Modern-UpgradingSetVariables.md | 3 - .../version-v4.0.0/Modern-fetchQuery.md | 2 - .../PrinciplesAndArchitecture-Compiler.md | 2 - .../PrinciplesAndArchitecture-Runtime.md | 1 - ...ciplesAndArchitecture-ThinkingInGraphQL.md | 21 -- ...inciplesAndArchitecture-ThinkingInRelay.md | 3 - .../GraphQL-ServerSpecification.md | 23 --- .../Introduction-InstallationAndSetup.md | 20 +- .../Introduction-QuickStartGuide.md | 28 --- .../Modern-ConvertingMutations.md | 12 -- .../Modern-FragmentContainer.md | 16 -- .../version-v5.0.0/Modern-GraphQLInRelay.md | 27 +-- .../Modern-LocalStateManagement.md | 14 -- .../version-v5.0.0/Modern-MigrationSetup.md | 6 - .../version-v5.0.0/Modern-Mutations.md | 14 -- .../version-v5.0.0/Modern-NetworkLayer.md | 4 - .../Modern-PaginationContainer.md | 15 -- .../version-v5.0.0/Modern-PersistedQueries.md | 26 +-- .../version-v5.0.0/Modern-QueryRenderer.md | 2 - .../version-v5.0.0/Modern-RefetchContainer.md | 9 - .../version-v5.0.0/Modern-RelayCompat.md | 2 - .../version-v5.0.0/Modern-RelayEnvironment.md | 4 - .../version-v5.0.0/Modern-RelayStore.md | 76 ------- .../version-v5.0.0/Modern-Subscriptions.md | 6 - .../Modern-TestingRelayComponents.md | 22 -- .../version-v5.0.0/Modern-TypeEmission.md | 9 - .../Modern-UpgradingSetVariables.md | 3 - .../version-v5.0.0/Modern-fetchQuery.md | 2 - .../PrinciplesAndArchitecture-Compiler.md | 2 - .../PrinciplesAndArchitecture-Runtime.md | 1 - ...ciplesAndArchitecture-ThinkingInGraphQL.md | 21 -- ...inciplesAndArchitecture-ThinkingInRelay.md | 3 - .../GraphQL-ServerSpecification.md | 23 --- .../Introduction-InstallationAndSetup.md | 20 +- .../Introduction-QuickStartGuide.md | 28 --- .../Modern-ConvertingMutations.md | 12 -- .../Modern-FragmentContainer.md | 16 -- .../version-v6.0.0/Modern-GraphQLInRelay.md | 31 +-- .../Modern-LocalStateManagement.md | 16 -- .../version-v6.0.0/Modern-MigrationSetup.md | 6 - .../version-v6.0.0/Modern-Mutations.md | 14 -- .../version-v6.0.0/Modern-NetworkLayer.md | 4 - .../Modern-PaginationContainer.md | 15 -- .../version-v6.0.0/Modern-PersistedQueries.md | 26 +-- .../version-v6.0.0/Modern-QueryRenderer.md | 2 - .../version-v6.0.0/Modern-RefetchContainer.md | 9 - .../version-v6.0.0/Modern-RelayCompat.md | 2 - .../version-v6.0.0/Modern-RelayEnvironment.md | 4 - .../version-v6.0.0/Modern-RelayStore.md | 76 ------- .../version-v6.0.0/Modern-Subscriptions.md | 6 - .../Modern-TestingRelayComponents.md | 22 -- .../version-v6.0.0/Modern-TypeEmission.md | 9 - .../Modern-UpgradingSetVariables.md | 3 - .../version-v6.0.0/Modern-fetchQuery.md | 2 - .../PrinciplesAndArchitecture-Compiler.md | 2 - .../PrinciplesAndArchitecture-Runtime.md | 1 - ...ciplesAndArchitecture-ThinkingInGraphQL.md | 21 -- ...inciplesAndArchitecture-ThinkingInRelay.md | 3 - .../GraphQL-ServerSpecification.md | 23 --- .../Introduction-InstallationAndSetup.md | 20 +- .../Introduction-QuickStartGuide.md | 28 --- .../Modern-ConvertingMutations.md | 12 -- .../Modern-FragmentContainer.md | 16 -- .../version-v7.0.0/Modern-GraphQLInRelay.md | 31 +-- .../Modern-LocalStateManagement.md | 16 -- .../version-v7.0.0/Modern-MigrationSetup.md | 6 - .../version-v7.0.0/Modern-Mutations.md | 14 -- .../version-v7.0.0/Modern-NetworkLayer.md | 4 - .../Modern-PaginationContainer.md | 15 -- .../version-v7.0.0/Modern-PersistedQueries.md | 26 +-- .../version-v7.0.0/Modern-QueryRenderer.md | 2 - .../version-v7.0.0/Modern-RefetchContainer.md | 9 - .../version-v7.0.0/Modern-RelayCompat.md | 2 - .../version-v7.0.0/Modern-RelayEnvironment.md | 4 - .../version-v7.0.0/Modern-RelayStore.md | 76 ------- .../version-v7.0.0/Modern-Subscriptions.md | 6 - .../Modern-TestingRelayComponents.md | 22 -- .../version-v7.0.0/Modern-TypeEmission.md | 9 - .../Modern-UpgradingSetVariables.md | 3 - .../version-v7.0.0/Modern-fetchQuery.md | 2 - .../PrinciplesAndArchitecture-Compiler.md | 2 - .../PrinciplesAndArchitecture-Runtime.md | 1 - ...ciplesAndArchitecture-ThinkingInGraphQL.md | 21 -- ...inciplesAndArchitecture-ThinkingInRelay.md | 3 - .../GraphQL-ServerSpecification.md | 23 --- .../Introduction-InstallationAndSetup.md | 20 +- .../Introduction-QuickStartGuide.md | 28 --- .../Modern-ConvertingMutations.md | 12 -- .../Modern-FragmentContainer.md | 16 -- .../version-v7.1.0/Modern-GraphQLInRelay.md | 31 +-- .../Modern-LocalStateManagement.md | 16 -- .../version-v7.1.0/Modern-MigrationSetup.md | 6 - .../version-v7.1.0/Modern-Mutations.md | 14 -- .../version-v7.1.0/Modern-NetworkLayer.md | 4 - .../Modern-PaginationContainer.md | 15 -- .../version-v7.1.0/Modern-PersistedQueries.md | 26 +-- .../version-v7.1.0/Modern-QueryRenderer.md | 2 - .../version-v7.1.0/Modern-RefetchContainer.md | 9 - .../version-v7.1.0/Modern-RelayCompat.md | 2 - .../version-v7.1.0/Modern-RelayEnvironment.md | 4 - .../version-v7.1.0/Modern-RelayStore.md | 76 ------- .../version-v7.1.0/Modern-Subscriptions.md | 6 - .../Modern-TestingRelayComponents.md | 22 -- .../version-v7.1.0/Modern-TypeEmission.md | 9 - .../Modern-UpgradingSetVariables.md | 3 - .../version-v7.1.0/Modern-fetchQuery.md | 2 - .../PrinciplesAndArchitecture-Compiler.md | 2 - .../PrinciplesAndArchitecture-Runtime.md | 1 - ...ciplesAndArchitecture-ThinkingInGraphQL.md | 21 -- ...inciplesAndArchitecture-ThinkingInRelay.md | 3 - .../GraphQL-ServerSpecification.md | 23 --- .../Introduction-InstallationAndSetup.md | 20 +- .../Introduction-QuickStartGuide.md | 28 --- .../Modern-ConvertingMutations.md | 12 -- .../Modern-FragmentContainer.md | 16 -- .../version-v8.0.0/Modern-GraphQLInRelay.md | 31 +-- .../Modern-LocalStateManagement.md | 16 -- .../version-v8.0.0/Modern-MigrationSetup.md | 6 - .../version-v8.0.0/Modern-Mutations.md | 14 -- .../version-v8.0.0/Modern-NetworkLayer.md | 4 - .../Modern-PaginationContainer.md | 15 -- .../version-v8.0.0/Modern-PersistedQueries.md | 26 +-- .../version-v8.0.0/Modern-QueryRenderer.md | 2 - .../version-v8.0.0/Modern-RefetchContainer.md | 9 - .../version-v8.0.0/Modern-RelayCompat.md | 2 - .../version-v8.0.0/Modern-RelayEnvironment.md | 4 - .../version-v8.0.0/Modern-RelayStore.md | 82 -------- .../version-v8.0.0/Modern-Subscriptions.md | 6 - .../Modern-TestingRelayComponents.md | 22 -- .../version-v8.0.0/Modern-TypeEmission.md | 9 - .../Modern-UpgradingSetVariables.md | 3 - .../version-v8.0.0/Modern-fetchQuery.md | 2 - .../PrinciplesAndArchitecture-Compiler.md | 2 - .../PrinciplesAndArchitecture-Runtime.md | 1 - ...ciplesAndArchitecture-ThinkingInGraphQL.md | 21 -- ...inciplesAndArchitecture-ThinkingInRelay.md | 3 - .../GraphQL-ServerSpecification.md | 23 --- .../Introduction-InstallationAndSetup.md | 20 +- .../Introduction-QuickStartGuide.md | 28 --- .../Modern-ConvertingMutations.md | 12 -- .../Modern-FragmentContainer.md | 16 -- .../version-v9.0.0/Modern-GraphQLInRelay.md | 31 +-- .../Modern-LocalStateManagement.md | 16 -- .../version-v9.0.0/Modern-MigrationSetup.md | 6 - .../version-v9.0.0/Modern-Mutations.md | 14 -- .../version-v9.0.0/Modern-NetworkLayer.md | 4 - .../Modern-PaginationContainer.md | 15 -- .../version-v9.0.0/Modern-PersistedQueries.md | 26 +-- .../version-v9.0.0/Modern-QueryRenderer.md | 2 - .../version-v9.0.0/Modern-RefetchContainer.md | 9 - .../version-v9.0.0/Modern-RelayCompat.md | 2 - .../version-v9.0.0/Modern-RelayEnvironment.md | 4 - .../version-v9.0.0/Modern-RelayStore.md | 82 -------- .../version-v9.0.0/Modern-Subscriptions.md | 6 - .../Modern-TestingRelayComponents.md | 22 -- .../version-v9.0.0/Modern-TypeEmission.md | 9 - .../Modern-UpgradingSetVariables.md | 3 - .../version-v9.0.0/Modern-fetchQuery.md | 2 - .../PrinciplesAndArchitecture-Compiler.md | 2 - .../PrinciplesAndArchitecture-Runtime.md | 1 - ...ciplesAndArchitecture-ThinkingInGraphQL.md | 21 -- ...inciplesAndArchitecture-ThinkingInRelay.md | 3 - .../GraphQL-ServerSpecification.md | 23 --- .../Introduction-InstallationAndSetup.md | 20 +- .../Introduction-QuickStartGuide.md | 28 --- .../Modern-ConvertingMutations.md | 12 -- .../Modern-FragmentContainer.md | 16 -- .../version-v9.1.0/Modern-GraphQLInRelay.md | 31 +-- .../Modern-LocalStateManagement.md | 16 -- .../version-v9.1.0/Modern-MigrationSetup.md | 6 - .../version-v9.1.0/Modern-Mutations.md | 14 -- .../version-v9.1.0/Modern-NetworkLayer.md | 4 - .../Modern-PaginationContainer.md | 15 -- .../version-v9.1.0/Modern-PersistedQueries.md | 26 +-- .../version-v9.1.0/Modern-QueryRenderer.md | 2 - .../version-v9.1.0/Modern-RefetchContainer.md | 9 - .../version-v9.1.0/Modern-RelayCompat.md | 2 - .../version-v9.1.0/Modern-RelayEnvironment.md | 4 - .../version-v9.1.0/Modern-RelayStore.md | 82 -------- .../version-v9.1.0/Modern-Subscriptions.md | 6 - .../Modern-TestingRelayComponents.md | 22 -- .../version-v9.1.0/Modern-TypeEmission.md | 9 - .../Modern-UpgradingSetVariables.md | 3 - .../version-v9.1.0/Modern-fetchQuery.md | 2 - .../PrinciplesAndArchitecture-Compiler.md | 2 - .../PrinciplesAndArchitecture-Runtime.md | 1 - ...ciplesAndArchitecture-ThinkingInGraphQL.md | 21 -- ...inciplesAndArchitecture-ThinkingInRelay.md | 3 - 638 files changed, 318 insertions(+), 8881 deletions(-) diff --git a/website/docs/api-reference/graphql/graphql-directives.md b/website/docs/api-reference/graphql/graphql-directives.md index 78509a7c0bdfc..330ffa9cd0422 100644 --- a/website/docs/api-reference/graphql/graphql-directives.md +++ b/website/docs/api-reference/graphql/graphql-directives.md @@ -25,11 +25,9 @@ Relay uses directives to add additional information to GraphQL documents, which `@arguments` is a directive used to pass arguments to a fragment that was defined using [`@argumentDefinitions`](#argumentdefinitions). For example: ```graphql - query TodoListQuery($userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` ## `@argumentDefinitions` @@ -37,7 +35,6 @@ query TodoListQuery($userID: ID) { `@argumentDefinitions` is a directive used to specify arguments taken by a fragment. For example: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -47,7 +44,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` ## `@connection(key: String!, filters: [String])` @@ -59,7 +55,6 @@ With `usePaginationFragment`, Relay expects connection fields to be annotated wi When defining a fragment for use with a Fragment container, you can use the `@relay(plural: true)` directive to indicate that container expects the prop for that fragment to be a list of items instead of a single item. A query or parent that spreads a `@relay(plural: true)` fragment should do so within a plural field (ie a field backed by a [GraphQL list](http://graphql.org/learn/schema/#lists-and-non-null). For example: ```javascript - // Plural fragment definition graphql` fragment TodoItems_items on TodoItem @relay(plural: true) { @@ -75,7 +70,6 @@ fragment TodoApp_app on App { ...TodoItem_items } } - ``` ## `@inline` @@ -85,7 +79,6 @@ The hooks APIs that Relay exposes allow you to read data from the store only dur In the example below, the function `processItemData` is called from a React component. It requires an item object with a specific set of fields. All React components that use this function should spread the `processItemData_item` fragment to ensure all of the correct item data is loaded for this function. ```javascript - import {graphql, readInlineData} from 'react-relay'; // non-React function called from React @@ -105,11 +98,9 @@ function processItemData(itemRef) { creatorName: item.creator.name }); } - ``` ```javascript - export default function MyComponent({item}) { function handleClick() { processItemData(item); @@ -129,7 +120,6 @@ export default function MyComponent({item}) { ); } - ``` ## `@relay(mask: Boolean)` @@ -147,14 +137,12 @@ Keep in mind that it is typically considered an **anti-pattern** to create a sin In the example below, the `user` prop will include the data for `id` and `name` fields wherever `...Component_internUser` is included, instead of Relay's normal behavior to mask those fields: ```javascript - graphql` fragment Component_internUser on InternUser @relay(mask: false) { id name } `; - ``` diff --git a/website/docs/api-reference/relay-runtime/store.md b/website/docs/api-reference/relay-runtime/store.md index 40c75cfb8cd6f..0ff473aa767ab 100644 --- a/website/docs/api-reference/relay-runtime/store.md +++ b/website/docs/api-reference/relay-runtime/store.md @@ -23,7 +23,6 @@ Table of Contents: The `RecordSourceSelectorProxy` is the type of the `store` that [`updater` functions](../../guided-tour/updating-data/graphql-mutations/) receive as an argument. The following is the `RecordSourceSelectorProxy` interface: ```javascript - interface RecordSourceSelectorProxy { create(dataID: string, typeName: string): RecordProxy; delete(dataID: string): void; @@ -33,7 +32,6 @@ interface RecordSourceSelectorProxy { getPluralRootField(fieldName: string): ?Array; invalidateStore(): void; } - ``` ### `create(dataID: string, typeName: string): RecordProxy` @@ -43,9 +41,7 @@ Creates a new record in the store given a `dataID` and the `typeName` as defined #### Example ```javascript - const record = store.create(dataID, 'Todo'); - ``` ### `delete(dataID: string): void` @@ -55,9 +51,7 @@ Deletes a record from the store given its `dataID`. #### Example ```javascript - store.delete(dataID); - ``` ### `get(dataID: string): ?RecordProxy` @@ -67,9 +61,7 @@ Retrieves a record from the store given its `dataID`. Returns a [`RecordProxy`]( #### Example ```javascript - const record = store.get(dataID); - ``` ### `getRoot(): RecordProxy` @@ -81,20 +73,16 @@ Returns the [`RecordProxy`](#recordproxy) representing the root of the GraphQL d Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - // Represents root query const root = store.getRoot(); - ``` ### `getRootField(fieldName: string): ?RecordProxy` @@ -106,19 +94,15 @@ Retrieves a root field from the store given the `fieldName`, as defined by the G Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - const viewer = store.getRootField('viewer'); - ``` ### `getPluralRootField(fieldName: string): ?Array` @@ -130,19 +114,15 @@ Retrieves a root field that represents a collection from the store given the `fi Given the GraphQL document: ```graphql - nodes(first: 10) { # ... } - ``` Usage: ```javascript - const nodes = store.getPluralRootField('nodes'); - ``` ### `invalidateStore(): void` @@ -152,17 +132,13 @@ Globally invalidates the Relay store. This will cause any data that was written #### Example ```javascript - store.invalidateStore(); - ``` After global invalidation, any query that is checked before refetching it will be considered stale: ```javascript - environment.check(query) === 'stale' - ``` ## RecordProxy @@ -170,7 +146,6 @@ environment.check(query) === 'stale' The `RecordProxy` serves as an interface to mutate records: ```javascript - interface RecordProxy { copyFieldsFrom(sourceRecord: RecordProxy): void; getDataID(): string; @@ -196,7 +171,6 @@ interface RecordProxy { setValue(value: mixed, name: string, arguments?: ?Object): RecordProxy; invalidateRecord(): void; } - ``` ### `getDataID(): string` @@ -206,9 +180,7 @@ Returns the `dataID` of the current record. #### Example ```javascript - const id = record.getDataID(); - ``` ### `getType(): string` @@ -218,9 +190,7 @@ Gets the type of the current record, as defined by the GraphQL schema. #### Example ```javascript - const type = user.getType(); // User - ``` ### `getValue(name: string, arguments?: ?Object): mixed` @@ -232,20 +202,16 @@ Gets the value of a field in the current record given the field name. Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - const name = viewer.getValue('name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. @@ -255,20 +221,16 @@ Optionally, if the field takes arguments, you can pass a bag of `variables`. Given the GraphQL document: ```graphql - viewer { id name(arg: $arg) } - ``` Usage: ```javascript - const name = viewer.getValue('name', {arg: 'value'}); - ``` ### `getLinkedRecord(name: string, arguments?: ?Object): ?RecordProxy` @@ -280,23 +242,19 @@ Retrieves a record associated with the current record given the field name, as d Given the GraphQL document: ```graphql - rootField { viewer { id name } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -306,22 +264,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { viewer(arg: $arg) { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {arg: 'value'}); - ``` ### `getLinkedRecords(name: string, arguments?: ?Object): ?Array` @@ -333,22 +287,18 @@ Retrieves the set of records associated with the current record given the field Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const nodes = rootField.getLinkedRecords('nodes'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -358,22 +308,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { nodes(first: $count) { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const nodes = rootField.getLinkedRecords('nodes', {count: 10}); - ``` ### `getOrCreateLinkedRecord(name: string, typeName: string, arguments?: ?Object)` @@ -385,22 +331,18 @@ Retrieves a record associated with the current record given the field name, as d Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = rootField.getOrCreateLinkedRecord('viewer', 'User'); // Will create if it doesn't exist - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -412,28 +354,22 @@ Mutates the current record by setting a new value on the specified field. Return Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - viewer.setValue('New Name', 'name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. ```javascript - viewer.setValue('New Name', 'name', {arg: 'value'}); - ``` ### `copyFieldsFrom(sourceRecord: RecordProxy): void` @@ -443,11 +379,9 @@ Mutates the current record by copying the fields over from the passed in record #### Example ```javascript - const record = store.get(id1); const otherRecord = store.get(id2); record.copyFieldsFrom(otherRecord); // Mutates `record` - ``` ### `setLinkedRecord(record: RecordProxy, name: string, arguments?: ?Object)` @@ -459,23 +393,19 @@ Mutates the current record by setting a new linked record on the given field nam Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = store.create(/* ... */); rootField.setLinkedRecord(newViewer, 'viewer'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -489,24 +419,20 @@ Mutates the current record by setting a new set of linked records on the given f Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newNode = store.create(/* ... */); const newNodes = [...rootField.getLinkedRecords('nodes'), newNode]; rootField.setLinkedRecords(newNodes, 'nodes'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -518,18 +444,14 @@ Invalidates the record. This will cause any query that references this record to #### Example ```javascript - const record = store.get('4'); record.invalidateRecord(); - ``` After invalidating a record, any query that references the invalidated record and that is checked before refetching it will be considered stale: ```javascript - environment.check(query) === 'stale' - ``` ## ConnectionHandler @@ -537,7 +459,6 @@ environment.check(query) === 'stale' `ConnectionHandler` is a utility module exposed by `relay-runtime` that aids in the manipulation of connections. `ConnectionHandler` exposes the following interface: ```javascript - interface ConnectionHandler { getConnection( record: RecordProxy, @@ -562,7 +483,6 @@ interface ConnectionHandler { ): void, deleteNode(connection: RecordProxy, nodeID: string): void } - ``` ### `getConnection(record: RecordProxy, key: string, filters?: ?Object)` @@ -572,7 +492,6 @@ Given a record and a connection key, and optionally a set of filters, `getConnec First, let's take a look at a plain connection: ```graphql - fragment FriendsFragment on User { friends(first: 10) { edges { @@ -582,26 +501,22 @@ fragment FriendsFragment on User { } } } - ``` Accessing a plain connection field like this is the same as other regular fields: ```javascript - // The `friends` connection record can be accessed with: const user = store.get(userID); const friends = user && user.getLinkedRecord('friends'); // Access fields on the connection: const edges = friends && friends.getLinkedRecords('edges'); - ``` When using [usePaginationFragment](../use-pagination-fragment/), we usually annotate the actual connection field with `@connection` to tell Relay which part needs to be paginated: ```graphql - fragment FriendsFragment on User { friends(first: 10, orderby: "firstname") @connection( key: "FriendsFragment_friends", @@ -613,13 +528,11 @@ fragment FriendsFragment on User { } } } - ``` For connections like the above, `ConnectionHandler` helps us find the record: ```javascript - import {ConnectionHandler} from 'relay-runtime'; // The `friends` connection record can be accessed with: @@ -631,7 +544,6 @@ const friends = ConnectionHandler.getConnection( ); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` ### Edge creation and insertion @@ -651,7 +563,6 @@ Given a connection, inserts the edge at the end of the connection, or after the #### Example ```javascript - const user = store.get(userID); const friends = ConnectionHandler.getConnection(user, 'FriendsFragment_friends'); const newFriend = store.get(newFriendId); @@ -662,7 +573,6 @@ ConnectionHandler.insertEdgeAfter(friends, edge); // No cursor provided, insert the edge at the front: ConnectionHandler.insertEdgeBefore(friends, edge); - ``` ### `deleteNode(connection: RecordProxy, nodeID: string): void` @@ -672,11 +582,9 @@ Given a connection, deletes any edges whose node id matches the given id. #### Example ```javascript - const user = store.get(userID); const friends = ConnectionHandler.getConnection(user, 'FriendsFragment_friends'); ConnectionHandler.deleteNode(friends, idToDelete); - ``` diff --git a/website/docs/getting-started/installation-and-setup.md b/website/docs/getting-started/installation-and-setup.md index b4d87ab4a8d05..ccd17b01e59ab 100644 --- a/website/docs/getting-started/installation-and-setup.md +++ b/website/docs/getting-started/installation-and-setup.md @@ -142,15 +142,13 @@ polyfill in your bundled application, such as [core-js][] or A polyfilled environment for Relay using [core-js][] to support older browsers might look like: -```js - +```javascript require('core-js/es6/map'); require('core-js/es6/set'); require('core-js/es6/promise'); require('core-js/es6/object'); require('./myRelayApplication'); - ``` [core-js]: https://github.com/zloirock/core-js diff --git a/website/docs/glossary/glossary.md b/website/docs/glossary/glossary.md index d4ab3d4a66afe..5a7e24be7dc2b 100644 --- a/website/docs/glossary/glossary.md +++ b/website/docs/glossary/glossary.md @@ -42,7 +42,7 @@ See [type refinement](#type-refinement). If type refinement is a way of conditio A [directive](#directive) that modifies a [fragment spread](#fragment-spread) and is used to pass arguments (defined with [`@argumentDefinitions`](#argumentdefinitions)) to that fragment. -``` +```graphql ...Story_story @arguments(storyId: "1234") ``` @@ -50,7 +50,7 @@ A [directive](#directive) that modifies a [fragment spread](#fragment-spread) an A directive that modifies a fragment definition and defines the names of the local arguments that the fragment can take, as well as their type. -``` +```graphql fragment Store_story on Story @argumentDefinitions(storyId: {type: "ID!"}) { # etc @@ -78,10 +78,8 @@ The concept of availability refers to whether there is enough non-stale, non-inv A build-time transformation of the Javascript codebase, which turns calls to -```js - +```javascript graphql`...` - ``` into query ASTs (concrete requests.) @@ -256,7 +254,7 @@ This identifies by its persist ID (`1234`), followed by the variables it accepts A parameter passed to `useFragment`. Obtained by accessing the value onto which a fragment was spread in another [query](#query), fragment, subscription or mutation. For example, -``` +```javascript const queryData = usePreloadedQuery( graphql`query ComponentQuery { viewer { account_user { ...Component_name } } }`, {}, @@ -292,7 +290,7 @@ TODO A fragment spread is how one fragment is contained in a query, subscription, mutation or other fragment. In the following example, `...Component_name` is a fragment spread: -``` +```graphql query ComponentQuery { viewer { account_user { @@ -380,10 +378,8 @@ Compare to [value](#value). A GraphQL literal is a call to -```js - +```javascript graphql`...` - ``` in your code. These are pre-processed, and replaced at build time with a [GraphlQLTaggedNode](#graphqltaggednode) containing an [AST](#ast) representation of the contents of the literal. @@ -466,7 +462,7 @@ The fundamental abstraction in Relay for representing data that may currently be Observables differ from promises in that if the data in an observable has already been loaded, you can access it synchronously as follows: -``` +```javascript const completedObservable = Observable.from("Relay is awesome!"); let valueFromObservable; observable.subscribe({ @@ -798,7 +794,7 @@ A method exposed by the Relay store. Accepts a callback and a snapshot (see [loo A GraphQL Subscription looks very similar to a query, with the exception that it uses the subscription keyword: -``` +```graphql subscription FeedbackLikeSubscription($input: FeedbackLikeSubscribeData!) { feedback_like_subscribe(data: $input) { feedback { diff --git a/website/docs/guided-tour/list-data/advanced-pagination.md b/website/docs/guided-tour/list-data/advanced-pagination.md index b99b47b67e3eb..5c0df04c0160f 100644 --- a/website/docs/guided-tour/list-data/advanced-pagination.md +++ b/website/docs/guided-tour/list-data/advanced-pagination.md @@ -151,7 +151,6 @@ function FriendsListComponent(props: Props) { ); } - ``` * The APIs for both *"forward"* and *"backward"* are exactly the same, they're only named differently. When paginating forward, then the `after` and `first` connection arguments will be used, when paginating backward, the `before` and `last` connection arguments will be used. diff --git a/website/docs/guided-tour/rendering/fragments.md b/website/docs/guided-tour/rendering/fragments.md index 0739f194b7d92..499f582df5188 100644 --- a/website/docs/guided-tour/rendering/fragments.md +++ b/website/docs/guided-tour/rendering/fragments.md @@ -339,7 +339,6 @@ function App({appQueryRef}) { ); } - ``` Note that: diff --git a/website/docs/guided-tour/rendering/variables.md b/website/docs/guided-tour/rendering/variables.md index 851442c1156f1..546eed9da7886 100644 --- a/website/docs/guided-tour/rendering/variables.md +++ b/website/docs/guided-tour/rendering/variables.md @@ -31,7 +31,7 @@ In the above, `ID!` is the type of the `$id` variable. That is, it is a required When sending a network request to fetch the query above, we need to provide both the query, and the variables to be used for this particular execution of the query. For example: -``` +```graphql # Query: query UserQuery($id: ID!) { # ... diff --git a/website/docs/guided-tour/reusing-cached-data/rendering-partially-cached-data.md b/website/docs/guided-tour/reusing-cached-data/rendering-partially-cached-data.md index ecb7f76cb4b93..10515ed15a24c 100644 --- a/website/docs/guided-tour/reusing-cached-data/rendering-partially-cached-data.md +++ b/website/docs/guided-tour/reusing-cached-data/rendering-partially-cached-data.md @@ -58,8 +58,7 @@ module.exports = UsernameComponent; And we have the following query component, which queries for some data, and also includes the fragment above: -```js - +```javascript /** * AppTabs.react.js * @@ -162,7 +161,6 @@ function HomeTab() { ); } - ``` diff --git a/website/docs/guided-tour/updating-data/client-only-data.md b/website/docs/guided-tour/updating-data/client-only-data.md index 2357feea0df63..757ed5c81ef50 100644 --- a/website/docs/guided-tour/updating-data/client-only-data.md +++ b/website/docs/guided-tour/updating-data/client-only-data.md @@ -34,7 +34,6 @@ In order to extend an existing type, add a `.graphql` file to your appropriate s ```graphql - extend type Comment { is_new_comment: Boolean } @@ -58,7 +57,6 @@ You can define types using the same regular GraphQL syntax, by defining it insid ```graphql - # You can define more than one type in a single file enum FetchStatus { FETCHED @@ -79,7 +77,6 @@ extend type Item { # You can extend server types with client-only types fetch_state: FetchState } - ``` * In this contrived example, we're defining 2 new client-only types, and `enum` and a regular `type`. Note that they can reference themselves as normal, and reference regular server defined types. Also note that we can extend server types and add fields that are of our client-only types. diff --git a/website/docs/guides/client-schema-extensions.md b/website/docs/guides/client-schema-extensions.md index 41458675bc52e..32ca5f7cb4666 100644 --- a/website/docs/guides/client-schema-extensions.md +++ b/website/docs/guides/client-schema-extensions.md @@ -38,23 +38,19 @@ It can even be used to extend an existing server schema. For example, we can create a new type called `Note`: ```graphql - type Note { id: ID! title: String body: String } - ``` And then extend the server schema type `User`, with a list of `Note`, called `notes`. ```graphql - extend type User { notes: [Note] } - ``` ## Querying local state @@ -65,7 +61,6 @@ The field can be from the server schema, or it can be schema agnostic, like an i 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. ```javascript - // Example.js import * as React from 'react'; import { useLazyLoadQuery, graphql } from 'react-relay'; @@ -86,7 +81,6 @@ const Example = (props) => { `, {}); // ... } - ``` ## Mutating local state @@ -102,7 +96,6 @@ To build upon the previous example, let's try creating, updating and deleting a ### Create ```javascript - import {commitLocalUpdate} from 'react-relay'; let tempID = 0; @@ -122,7 +115,6 @@ function createUserNote(environment) { user.setLinkedRecords([...userNoteRecords, newNoteRecord], 'notes'); }); } - ``` 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. @@ -130,7 +122,6 @@ Note that since this record will be rendered by the `ExampleQuery` via `useLazyL If no component is rendering the local data and you want to manually retain it, you can do so by calling `environment.retain()`: ```javascript - import {createOperationDescriptor, getRequest} from 'relay-runtime'; // Create a query that references that record @@ -157,13 +148,11 @@ const disposable = environment.retain(operation); // Whenever you don't need that data anymore and it's okay for Relay to garbage collect it, // you can dispose of the retain disposable.dispose(); - ``` ### Update ```javascript - import {commitLocalUpdate} from 'react-relay'; function updateUserNote(environment, dataID, body, title) { @@ -174,13 +163,11 @@ function updateUserNote(environment, dataID, body, title) { note.setValue(title, 'title') }); } - ``` ### Delete ```javascript - import {commitLocalUpdate} from 'react-relay'; function deleteUserNote(environment, dataID) { @@ -198,7 +185,6 @@ function deleteUserNote(environment, dataID) { user.setLinkedRecords(newUserNoteRecords, 'notes'); }); } - ``` ## Initial local state @@ -207,7 +193,6 @@ All new client-side schema fields default to `undefined` value. Often however, y You can use an updater function via `commitLocalUpdate` to prime local state. ```javascript - import {commitLocalUpdate} from 'react-relay'; commitLocalUpdate(environment, store => { @@ -216,7 +201,6 @@ commitLocalUpdate(environment, store => { // initialize user notes to an empty array. user.setLinkedRecords([], 'notes'); }); - ``` diff --git a/website/docs/guides/compiler.md b/website/docs/guides/compiler.md index 583a332624db9..df48e1fb12a98 100644 --- a/website/docs/guides/compiler.md +++ b/website/docs/guides/compiler.md @@ -18,7 +18,6 @@ import FbImportingGeneratedDefinitions from './fb/FbImportingGeneratedDefinition The `graphql` template tag provided by Relay serves as the mechanism to write queries, fragments, mutations and subscriptions in the [GraphQL](http://graphql.org/learn/) language. For example: ```javascript - import {graphql} from 'react-relay'; graphql` @@ -28,7 +27,6 @@ graphql` } } `; - ``` The result of using the `graphql` template tag is a `GraphQLTaggedNode`; a runtime representation of the GraphQL document. @@ -43,13 +41,11 @@ Relay uses the Relay Compiler to convert [`graphql`](#graphql) literals into gen A fragment like the following: ```javascript - graphql` fragment MyComponent on Type { field } ` - ``` Will cause a generated file to appear in `./__generated__/MyComponent.graphql.js`, @@ -69,7 +65,6 @@ The Relay Compiler is responsible for generating code as part of a build step wh To use the Relay Compiler, you need either a `.graphql` or `.json` [GraphQL Schema](https://graphql.org/learn/schema/) file, describing your GraphQL server's API. Typically these files are local representations of a server source of truth and are not edited directly. For example, we might have a `schema.graphql` like: ```graphql - schema { query: Root } @@ -87,7 +82,6 @@ type WordDefinition { text: String image: String } - ``` @@ -111,7 +105,6 @@ For example, given the two files: - `src/Components/DictionaryComponent.js` ```javascript - const DictionaryWordFragment = graphql` fragment DictionaryComponent_word on Word { id @@ -127,13 +120,11 @@ const DictionaryDefinitionFragment = graphql` image } ` - ``` - `src/Queries/DictionaryQuery.js` ```javascript - const DictionaryQuery = graphql` query DictionaryQuery { dictionary { @@ -141,7 +132,6 @@ const DictionaryQuery = graphql` } } ` - ``` This would produce three generated files, and two `__generated__` directories: @@ -167,9 +157,7 @@ Typically you will not need to import your generated definitions. The [Relay Bab However the Relay Compiler also automatically generates [Flow](https://flow.org) types as [type comments](https://flow.org/en/docs/types/comments/). For example, you can import the generated Flow types like so: ```javascript - import type {DictionaryComponent_word} from './__generated__/DictionaryComponent_word.graphql'; - ``` More rarely, you may need to access a query, mutation, fragment or subscription from multiple files. In these cases, you can also import it directly: diff --git a/website/docs/guides/graphql-server-specification.md b/website/docs/guides/graphql-server-specification.md index 2fb0b461f6568..5b8faba74159c 100644 --- a/website/docs/guides/graphql-server-specification.md +++ b/website/docs/guides/graphql-server-specification.md @@ -40,8 +40,7 @@ It is also assumed that the reader is already familiar with [Star Wars](https:// The schema described below will be used to demonstrate the functionality that a GraphQL server used by Relay should implement. The two core types are a faction and a ship in the Star Wars universe, where a faction has many ships associated with it. -``` - +```graphql interface Node { id: ID! } @@ -89,34 +88,29 @@ The `Node` interface contains a single field, `id`, which is an `ID!`. The `node Let's see this in action, and query for the ID of the rebels: -``` - +```graphql query RebelsQuery { rebels { id name } } - ``` returns ```json - { "rebels": { "id": "RmFjdGlvbjox", "name": "Alliance to Restore the Republic" } } - ``` So now we know the ID of the Rebels in our system. We can now refetch them: -``` - +```graphql query RebelsRefetchQuery { node(id: "RmFjdGlvbjox") { id @@ -125,52 +119,44 @@ query RebelsRefetchQuery { } } } - ``` returns ```json - { "node": { "id": "RmFjdGlvbjox", "name": "Alliance to Restore the Republic" } } - ``` If we do the same thing with the Empire, we'll find that it returns a different ID, and we can refetch it as well: -``` - +```graphql query EmpireQuery { empire { id name } } - ``` yields ```json - { "empire": { "id": "RmFjdGlvbjoy", "name": "Galactic Empire" } } - ``` and -``` - +```graphql query EmpireRefetchQuery { node(id: "RmFjdGlvbjoy") { id @@ -179,20 +165,17 @@ query EmpireRefetchQuery { } } } - ``` yields ```json - { "node": { "id": "RmFjdGlvbjoy", "name": "Galactic Empire" } } - ``` The `Node` interface and `node` field assume globally unique IDs for this refetching. A system without globally unique IDs can usually synthesize them by combining the type with the type-specific ID, which is what was done in this example. @@ -207,8 +190,7 @@ A faction has many ships in the Star Wars universe. Relay contains functionality Let's take the rebels, and ask for their first ship: -``` - +```graphql query RebelsShipsQuery { rebels { name, @@ -221,13 +203,11 @@ query RebelsShipsQuery { } } } - ``` yields ```json - { "rebels": { "name": "Alliance to Restore the Republic", @@ -242,13 +222,11 @@ yields } } } - ``` That used the `first` argument to `ships` to slice the result set down to the first one. But what if we wanted to paginate through it? On each edge, a cursor will be exposed that we can use to paginate. Let's ask for the first two this time, and get the cursor as well: ``` - query MoreRebelShipsQuery { rebels { name, @@ -262,7 +240,6 @@ query MoreRebelShipsQuery { } } } - ``` and we get back @@ -290,7 +267,6 @@ and we get back } } } - ``` Notice that the cursor is a base64 string. That's the pattern from earlier: the server is reminding us that this is an opaque string. We can pass this string back to the server as the `after` argument to the `ships` field, which will let us ask for the next three ships after the last one in the previous result: @@ -310,7 +286,6 @@ query EndOfRebelShipsQuery { } } } - ``` gives us @@ -345,13 +320,11 @@ gives us } } } - ``` Sweet! Let's keep going and get the next four! -``` - +```graphql query RebelsQuery { rebels { name, @@ -365,13 +338,11 @@ query RebelsQuery { } } } - ``` yields ```json - { "rebels": { "name": "Alliance to Restore the Republic", @@ -380,13 +351,11 @@ yields } } } - ``` Hm. There were no more ships; guess there were only five in the system for the rebels. It would have been nice to know that we'd reached the end of the connection, without having to do another round trip in order to verify that. The connection model exposes this capability with a type called `PageInfo`. So let's issue the two queries that got us ships again, but this time ask for `hasNextPage`: -``` - +```graphql query EndOfRebelShipsQuery { rebels { name, @@ -412,13 +381,11 @@ query EndOfRebelShipsQuery { } } } - ``` and we get back ```json - { "rebels": { "name": "Alliance to Restore the Republic", @@ -463,7 +430,6 @@ and we get back } } } - ``` So on the first query for ships, GraphQL told us there was a next page, but on the next one, it told us we'd reached the end of the connection. diff --git a/website/docs/guides/network-layer.md b/website/docs/guides/network-layer.md index ee35675fc6007..37e7076fa9552 100644 --- a/website/docs/guides/network-layer.md +++ b/website/docs/guides/network-layer.md @@ -22,7 +22,6 @@ In order to know how to access your GraphQL server, Relay requires developers to Currently the easiest way to create a network layer is via a helper from the `relay-runtime` package: ```javascript - import { Environment, Network, @@ -64,7 +63,6 @@ const environment = new Environment({ }); export default environment; - ``` Note that this is a basic example to help you get started. This example could be extended with additional features such as request/response caching (enabled e.g. when `cacheConfig.force` is false) and uploading form data for mutations (the `uploadables` parameter). diff --git a/website/docs/guides/persisted-queries.md b/website/docs/guides/persisted-queries.md index 8760d2407967f..16d72c50f6547 100644 --- a/website/docs/guides/persisted-queries.md +++ b/website/docs/guides/persisted-queries.md @@ -32,12 +32,10 @@ The relay compiler supports persisted queries. This is useful because: In your `npm` script in `package.json`, run the relay compiler using the `--persist-output` flag: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` The `--persist-ouput` flag does 2 things: @@ -46,8 +44,7 @@ The `--persist-ouput` flag does 2 things: For example without `--persist-output`, a generated `ConcreteRequest` might look like below: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -64,8 +61,7 @@ The `--persist-ouput` flag does 2 things: With `--persist-output ` this becomes: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -83,12 +79,10 @@ The `--persist-ouput` flag does 2 things: 2. It generates a JSON file at the `` you specify containing a mapping from query ids to the corresponding operation texts. -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./src/queryMaps/queryMap.json" } - ``` The example above writes the complete query map file to `./src/queryMaps/queryMap.json`. You need to ensure all the directories @@ -100,8 +94,7 @@ leading to the `queryMap.json` file exist. You'll need to modify your network layer fetch implementation to pass a doc_id parameter in the POST body instead of a query parameter: -```js - +```javascript function fetchQuery(operation, variables,) { return fetch('/graphql', { method: 'POST', @@ -117,7 +110,6 @@ function fetchQuery(operation, variables,) { return response.json(); }); } - ``` @@ -142,13 +134,11 @@ the query map file in a common location accessible to both the client and the se For applications where the client and server projects are separate, one option is to have an additional npm run script to push the query map at compile time to a location accessible by your server: -```js - +```javascript "scripts": { "push-queries": "node ./pushQueries.js", "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-ouput && npm run push-queries" } - ``` Some possibilities of what you can do in `./pushQueries.js`: @@ -172,8 +162,7 @@ database technologies you use, so we'll just cover the most common and basic exa If you use `express-graphql` and have access to the query map file, you can import the `--persist-output` JSON file directly and perform the matching using the `matchQueryMiddleware` from [relay-compiler-plus](https://github.com/yusinto/relay-compiler-plus). -```js - +```javascript import Express from 'express'; import expressGraphql from 'express-graphql'; import {matchQueryMiddleware} from 'relay-compiler-plus'; @@ -184,7 +173,6 @@ const app = Express(); app.use('/graphql', matchQueryMiddleware(queryMapJson), expressGraphql({schema})); - ``` ## Using `--persist-output` and `--watch` diff --git a/website/docs/guides/testing-relay-components.md b/website/docs/guides/testing-relay-components.md index cf36ac5845212..e6b33fed42169 100644 --- a/website/docs/guides/testing-relay-components.md +++ b/website/docs/guides/testing-relay-components.md @@ -162,8 +162,7 @@ Most of GraphQL type information for a specific field in the selection is not av Operation with the @relay_test_operation directive will have additional metadata that will contain GraphQL type info for fields in the operation's selection. And it will improve the quality of the generated data. You also will be able to define Mock resolvers for Scalar (not only ID and String) and Abstract types: -```js - +```javascript { Float() { return 123.456; @@ -190,8 +189,7 @@ Operation with the @relay_test_operation directive will have additional metadata Using `createMockEnvironment` and `MockPayloadGenerator` allows writing concise tests for components that are using Relay hooks. Both those modules can be imported from `relay-test-utils` -```js - +```javascript // Say you have a component with the useLazyLoadQuery or a QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { @@ -260,8 +258,7 @@ test('Error State', () => { Essentially, in the example above will `resolveMostRecentOperation` will generate data for all child fragment containers (pagination, refetch). But, usually the root component may have many child fragment components and you may want to exercise a specific component that uses `useFragment`. The solution for that would be to wrap your fragment container with the `useLazyLoadQuery` component that renders a Query that's spreads fragments from your fragment component: -```js - +```javascript test('Fragment', () => { const environment = createMockEnvironment(); const TestRenderer = () => { @@ -378,7 +375,6 @@ test('`Pagination` Container', () => { expect(loadMore.props.disabled).toBe(true); }); - ``` ### Refetch Component @@ -514,8 +510,7 @@ test('it should subscribe', () => { With `queueOperationResolver` it possible to define responses for operations that will be executed on the environment -```js - +```javascript // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { diff --git a/website/docs/guides/testing-relay-with-preloaded-queries.md b/website/docs/guides/testing-relay-with-preloaded-queries.md index cfb7279dd1950..fd3d4d4985e6e 100644 --- a/website/docs/guides/testing-relay-with-preloaded-queries.md +++ b/website/docs/guides/testing-relay-with-preloaded-queries.md @@ -30,8 +30,7 @@ In short, there are two steps that need to be performed **before rendering the c ## TL;DR -```js - +```javascript const {RelayEnvironmentProvider} = require('react-relay'); const { MockPayloadGenerator, createMockEnvironment } = require('relay-test-utils'); const {render} = require('testing-library-react'); @@ -67,7 +66,6 @@ test("...", () => { // assert // your assertions go here }); - ``` ### Configure the query resolver to generate the response @@ -105,14 +103,12 @@ The type you need seems to be the type returned by the *innermost function call* It is **possible** to return different data for different query variables via [Mock Resolver Context](../testing-relay-components/#mock-resolver-context). The query variables will be available on the `context.args`, but only to the *innermost function call* (for the query above, only `offer_ids` are available) -```js - +```javascript CurrencyAmount(context) { console.log(JSON.stringify(context, null, 2)); // <-- return { formatted_amount: mockResponse } } // <-- logs { ...snip..., "name": "subtotal_price_for_offers", args: { offer_ids: [...] } } - ``` ### Record a pending queue invocation diff --git a/website/docs/guides/type-emission.md b/website/docs/guides/type-emission.md index 437f2a4f0c1d1..15b8a11d17c35 100644 --- a/website/docs/guides/type-emission.md +++ b/website/docs/guides/type-emission.md @@ -399,21 +399,17 @@ An important caveat to note is that by default strict fragment reference type-in To enable this feature, you will have to tell the compiler to store all the artifacts in a single directory, like so: ```shell - $ relay-compiler --artifactDirectory ./src/__generated__ […] - ``` …and additionally inform the babel plugin in your `.babelrc` config where to look for the artifacts: ```json - { "plugins": [ ["relay", { "artifactDirectory": "./src/__generated__" }] ] } - ``` It is recommended to alias this directory in your module resolution configuration such that you don’t need to specify relative paths in your source files. This is what is also done in the above examples, where artifacts are imported from a `__generated__` alias, rather than relative paths like `../../../../__generated__`. @@ -433,29 +429,23 @@ At its simplest, we can consider Haste as a single directory that contains all m - Flow: This is the default and builtin language plugin. You can explicitly enable it like so: - ```shell - - $ relay-compiler --language javascript […] - - ``` +```shell +$ relay-compiler --language javascript […] +``` By default, Flow types are emitted inside of comments to avoid forcing your project to use Flow. Flow types inside of comments is perfectly valid Flow, however, some editors and IDEs (like WebStorm/IDEA) do not understand Flow unless it's in plain source code. In order to solve that, there's a language plugin maintained by the community that replicates the functionality of the default builtin plugin, but emits the Flow types as plain source and not inside comments. Installation and usage: ```shell - - $ yarn add --dev relay-compiler-language-js-flow-uncommented - $ relay-compiler --language js-flow-uncommented […] - +$ yarn add --dev relay-compiler-language-js-flow-uncommented +$ relay-compiler --language js-flow-uncommented […] ``` - [TypeScript](https://github.com/relay-tools/relay-compiler-language-typescript): This is a language plugin for the TypeScript language maintained by the community. Install and enable it like so: - ```shell - - $ yarn add --dev relay-compiler-language-typescript @types/react-relay @types/relay-runtime - $ relay-compiler --language typescript […] - - ``` +```shell +$ yarn add --dev relay-compiler-language-typescript @types/react-relay @types/relay-runtime +$ relay-compiler --language typescript […] +``` If you are looking to create your own language plugin, refer to the `relay-compiler` [language plugin interface][plugin-interface]. diff --git a/website/docs/principles-and-architecture/compiler-architecture.md b/website/docs/principles-and-architecture/compiler-architecture.md index 7846a25d6e423..f872264b8082c 100644 --- a/website/docs/principles-and-architecture/compiler-architecture.md +++ b/website/docs/principles-and-architecture/compiler-architecture.md @@ -41,7 +41,6 @@ The high-level flow of data through the compiler is represented in the following ┌─────────────┐ ┌─────────────┐ │ GraphQL │ │ Artifacts │ └─────────────┘ └─────────────┘ - ``` 1. GraphQL text is extracted from source files and "parsed" into an intermediate representation (IR) using information from the schema. @@ -69,7 +68,6 @@ Here are a few examples of some of the included transforms: - `FlattenTransform`: Reduces extraneous levels of indirection in a query, inlining fields from anonymous fragments wherever they match the parent type. This can be beneficial when generating code to read the results of a query or process query results, as it reduces duplicate field processing. For example: ``` - # before: `id` is processed twice foo { # type FooType id @@ -82,13 +80,11 @@ foo { # type FooType foo { id } - ``` - `SkipRedundantNodeTransform`: A more advanced version of flattening, this eliminates more complex cases of field duplication such as when a field is fetched both unconditionally and conditionally, or is fetched by two different sub-fragments. For example: ``` - # before: `id` processed up to 2x foo { bar { @@ -105,7 +101,6 @@ foo { id } } - ``` diff --git a/website/docs/principles-and-architecture/runtime-architecture.md b/website/docs/principles-and-architecture/runtime-architecture.md index 68e6a4bf47cba..9e1e84abcd706 100644 --- a/website/docs/principles-and-architecture/runtime-architecture.md +++ b/website/docs/principles-and-architecture/runtime-architecture.md @@ -82,7 +82,6 @@ RecordSource { city: 'Seattle', } } - ``` [1] Note that GraphQL itself does not impose this constraint, and Relay Runtime may also be used for schemas that do not conform to it. For example, both systems can be used to query a single denormalized table. However, many of the features that Relay Runtime provides, such as caching and normalization, work best when the data is represented as a normalized graph with stable identities for discrete pieces of information. diff --git a/website/docs/principles-and-architecture/thinking-in-graphql.md b/website/docs/principles-and-architecture/thinking-in-graphql.md index ceabfed2431bb..fc787bd18b318 100644 --- a/website/docs/principles-and-architecture/thinking-in-graphql.md +++ b/website/docs/principles-and-architecture/thinking-in-graphql.md @@ -18,7 +18,6 @@ In this article we'll explore what it means to build a GraphQL client framework Imagine we have a simple application that fetches a list of stories, and some details about each one. Here's how that might look in resource-oriented REST: ```javascript - // Fetch the list of story IDs but not their details: rest.get('/stories').then(stories => // This resolves to a list of items with linked resources: @@ -31,13 +30,11 @@ rest.get('/stories').then(stories => // `[ { id: "...", text: "..." } ]` console.log(stories); }); - ``` Note that this approach requires _n+1_ requests to the server: 1 to fetch the list, and _n_ to fetch each item. With GraphQL we can fetch the same data in a single network request to the server (without creating a custom endpoint that we'd then have to maintain): ```javascript - graphql.get(`query { stories { id, text } }`).then( stories => { // A list of story items: @@ -45,7 +42,6 @@ graphql.get(`query { stories { id, text } }`).then( console.log(stories); } ); - ``` So far we're just using GraphQL as a more efficient version of typical REST approaches. Note two important benefits in the GraphQL version: @@ -62,7 +58,6 @@ Repeatedly refetching information from the server can get quite slow. For exampl In a resource-oriented REST system, we can maintain a **response cache** based on URIs: ```javascript - var _cache = new Map(); rest.get = uri => { if (!_cache.has(uri)) { @@ -70,13 +65,11 @@ rest.get = uri => { } return _cache.get(uri); }; - ``` Response-caching can also be applied to GraphQL. A basic approach would work similarly to the REST version. The text of the query itself can be used as a cache key: ```javascript - var _cache = new Map(); graphql.get = queryText => { if (!_cache.has(queryText)) { @@ -84,7 +77,6 @@ graphql.get = queryText => { } return _cache.get(queryText); }; - ``` Now, requests for previously cached data can be answered immediately without making a network request. This is a practical approach to improving the perceived performance of an application. However, this method of caching can cause problems with data consistency. @@ -93,18 +85,14 @@ Now, requests for previously cached data can be answered immediately without mak With GraphQL it is very common for the results of multiple queries to overlap. However, our response cache from the previous section doesn't account for this overlap — it caches based on distinct queries. For example, if we issue a query to fetch stories: -``` - +```graphql query { stories { id, text, likeCount } } - ``` and then later refetch one of the stories whose `likeCount` has since been incremented: -``` - +```graphql query { story(id: "123") { id, text, likeCount } } - ``` We'll now see different `likeCount`s depending on how the story is accessed. A view that uses the first query will see an outdated count, while a view using the second query will see the updated count. @@ -115,8 +103,7 @@ The solution to caching GraphQL is to normalize the hierarchical response into a Here's an example query that fetches a story's text and its author's name: -``` - +```graphql query { story(id: "1") { text, @@ -125,28 +112,26 @@ query { } } } - ``` And here's a possible response: -``` - -query: { - story: { - text: "Relay is open-source!", - author: { - name: "Jan" - } +```json +{ + "query": { + "story": { + "text": "Relay is open-source!", + "author": { + "name": "Jan" + } + } } } - ``` Although the response is hierarchical, we'll cache it by flattening all the records. Here is an example of how Relay would cache this query response: ```javascript - Map { // `story(id: "1")` 1: Map { @@ -158,7 +143,6 @@ Map { name: 'Jan', }, }; - ``` This is only a simple example: in reality the cache must handle one-to-many associations and pagination (among other things). @@ -185,20 +169,16 @@ Note that this normalized cache structure allows overlapping results to be cache The first query was for a list of stories: -``` - +```graphql query { stories { id, text, likeCount } } - ``` With a normalized response cache, a record would be created for each story in the list. The `stories` field would store links to each of these records. The second query refetched the information for one of those stories: -``` - +```graphql query { story(id: "123") { id, text, likeCount } } - ``` When this response is normalized, Relay can detect that this result overlaps with existing data based on its `id`. Rather than create a new record, Relay will update the existing `123` record. The new `likeCount` is therefore available to _both_ queries, as well as any other query that might reference this story. @@ -209,8 +189,7 @@ A normalized cache ensures that the _cache_ is consistent. But what about our vi Consider rendering the text and comments of a story along with the corresponding author names and photos. Here's the GraphQL query: -``` - +```graphql query { story(id: "1") { text, @@ -221,13 +200,11 @@ query { } } } - ``` After initially fetching this story our cache might be as follows. Note that the story and comment both link to the same record as `author`: ``` - // Note: This is pseudo-code for `Map` initialization to make the structure // more obvious. Map { @@ -248,13 +225,11 @@ Map { author: Link(2), }, } - ``` The author of this story also commented on it — quite common. Now imagine that some other view fetches new information about the author, and her profile photo has changed to a new URI. Here's the _only_ part of our cached data that changes: ``` - Map { ... 2: Map { @@ -262,7 +237,6 @@ Map { photo: 'http://.../photo2.jpg', }, } - ``` The value of the `photo` field has changed; and therefore the record `2` has also changed. And that's it. Nothing else in the _cache_ is affected. But clearly our _view_ needs to reflect the update: both instances of the author in the UI (as story author and comment author) need to show the new photo. @@ -270,7 +244,6 @@ The value of the `photo` field has changed; and therefore the record `2` has als A standard response is to "just use immutable data structures" — but let's see what would happen if we did: ``` - ImmutableMap { 1: ImmutableMap // same as before 2: ImmutableMap { @@ -279,7 +252,6 @@ ImmutableMap { }, 3: ImmutableMap // same as before } - ``` If we replace `2` with a new immutable record, we'll also get a new immutable instance of the cache object. However, records `1` and `3` are untouched. Because the data is normalized, we can't tell that `story`'s contents have changed just by looking at the `story` record alone. @@ -294,8 +266,7 @@ Note that this solution will also work for _writes_: any update to the cache wil So far we've looked at the process of querying data and keeping views up to date, but we haven't looked at writes. In GraphQL, writes are called **mutations**. We can think of them as queries with side effects. Here's an example of calling a mutation that might mark a given story as being liked by the current user: -``` - +```graphql // Give a human-readable name and define the types of the inputs, // in this case the id of the story to mark as liked. mutation StoryLike($storyID: String) { @@ -305,7 +276,6 @@ mutation StoryLike($storyID: String) { likeCount } } - ``` Notice that we're querying for data that _may_ have changed as a result of the mutation. An obvious question is: why can't the server just tell us what changed? The answer is: it's complicated. GraphQL abstracts over _any_ data storage layer (or an aggregation of multiple sources), and works with any programming language. Furthermore, the goal of GraphQL is to provide data in a form that is useful to product developers building a view. diff --git a/website/docs/principles-and-architecture/thinking-in-relay.md b/website/docs/principles-and-architecture/thinking-in-relay.md index f4fd27e1f681a..2f6403d6fd6cb 100644 --- a/website/docs/principles-and-architecture/thinking-in-relay.md +++ b/website/docs/principles-and-architecture/thinking-in-relay.md @@ -29,8 +29,7 @@ Let's dive deeper to understand how Relay achieves this feat. With Relay, the data requirements for a component are specified with fragments. Fragments are named snippets of GraphQL that specify which fields to select from an object of a particular type. Fragments are written within GraphQL literals. For example, the following declares a GraphQL literal containing a fragment which selects an author's name and photo url: -```js - +```javascript // AuthorDetails.react.js const authorDetailsFragment = graphql` fragment AuthorDetails_author on Author { @@ -40,19 +39,16 @@ const authorDetailsFragment = graphql` } } `; - ``` This data is then read out from the store by calling the `useFragment(...)` hook in a functional React component. The actual author from which to read this data is determined by the second parameter passed to `useFragment`. For example: -```js - +```javascript // AuthorDetails.react.js export default function AuthorDetails(props) { const data = useFragment(authorDetailsFragment, props.author); // ... } - ``` This second parameter (`props.author`) is a fragment reference. Fragment references are obtained by **spreading** a fragment into another fragment or query. Fragments cannot be fetched directly. Instead, all fragments must ultimately be spread (either directly or transitively) into a query for the data to be fetched. @@ -63,8 +59,7 @@ Let's take a look at one such query. In order to fetch that data, we might declare a query which spreads `AuthorDetails_author` as follows: -```js - +```javascript // Story.react.js const storyQuery = graphql` query StoryQuery($storyID: ID!) { @@ -76,13 +71,11 @@ const storyQuery = graphql` } } `; - ``` Now, we can fetch the query by calling `const data = useLazyLoadQuery(storyQuery, {storyID})`. At this point, `data.author` (if it is present; all fields are nullable by default) will be a fragment reference that we can pass to `AuthorDetails`. For example: -```js - +```javascript // Story.react.js function Story(props) { const data = useLazyLoadQuery(storyQuery, props.storyId); @@ -92,7 +85,6 @@ function Story(props) { {data?.story?.author && } ); } - ``` Note what has happened here. We made a single network request which contained the data required by *both* the `Story` component *and* the `AuthorDetails` component! When that data was available, the entire view could render in a single pass. diff --git a/website/versioned_docs/version-classic/Classic-APIReference-Container.md b/website/versioned_docs/version-classic/Classic-APIReference-Container.md index 7def9b24235a6..fdde70a4e4837 100644 --- a/website/versioned_docs/version-classic/Classic-APIReference-Container.md +++ b/website/versioned_docs/version-classic/Classic-APIReference-Container.md @@ -106,7 +106,6 @@ fragments: RelayQueryFragments = { variables: {[name: string]: mixed} ) => Relay.QL`fragment on ...` }; - ``` Containers declare data requirements on `fragments` using GraphQL fragments. @@ -145,7 +144,6 @@ See also: [Containers > Relay Containers](./classic-guides-containers#relay-c ``` initialVariables: {[name: string]: mixed}; - ``` The initial set of variable values available to this component's fragments. @@ -168,7 +166,6 @@ module.exports = Relay.createContainer(ProfilePicture, { `, }, }); - ``` In this example, `profilePicture(size: 50)` will be fetched for the intial render. @@ -180,7 +177,6 @@ In this example, `profilePicture(size: 50)` will be fetched for the intial rende prepareVariables: ?( prevVariables: {[name: string]: mixed} ) => {[name: string]: mixed} - ``` Containers can define a `prepareVariables` method which provides the opportunity to modify the variables that are available to fragments. The new variables can be generated based on the previous variables (or the `initialVariables` if no previous ones exist) in addition to the runtime environment. @@ -202,7 +198,6 @@ module.exports = Relay.createContainer(ProfilePicture, { }, // ... }); - ``` ### shouldComponentUpdate @@ -210,7 +205,6 @@ module.exports = Relay.createContainer(ProfilePicture, { ``` shouldComponentUpdate: () => boolean; - ``` RelayContainer implements a conservative default `shouldComponentUpdate` that returns `false` if no fragment props have changed and all other props are equal scalar values. This may block updates to components that receive data via context. To ensure an update in this case override the default behavior by specifying a `shouldComponentUpdate` function. @@ -223,7 +217,6 @@ module.exports = Relay.createContainer(ProfilePicture, { shouldComponentUpdate: () => true, // ... }); - ``` ## Properties and Methods @@ -248,7 +241,6 @@ var name = this.props.relay.route.name; if (name === 'SuperAwesomeRoute') { // Do something super cool. } - ``` See also: [Routes](./classic-guides-routes) @@ -258,7 +250,6 @@ See also: [Routes](./classic-guides-routes) ``` variables: {[name: string]: mixed} - ``` `variables` contains the set of variables that was used to fetch the current set of props. @@ -288,7 +279,6 @@ module.exports = Relay.createContainer(ProfilePicture, { `, }, }); - ``` In this example, the `width` of the rendered image will always correspond to the `$size` variable used to fetch the current version of `profilePicture.uri`. @@ -305,7 +295,6 @@ Never mutate this.props.relay.variables directly as it will not tri ``` pendingVariables: ?{[name: string]: mixed} - ``` `pendingVariables` contains the set of variables that are being used to fetch the new props, i.e. when `this.props.relay.setVariables()` or `this.props.relay.forceFetch()` are called and the corresponding request is in flight. @@ -357,7 +346,6 @@ module.exports = Relay.createContainer(ProfilePicture, { `, }, }); - ``` In this example, whenever a picture with a new size is being loaded a spinner is displayed instead of the picture. @@ -414,7 +402,6 @@ module.exports = Relay.createContainer(Feed, { `, }, }); - ```
@@ -563,7 +550,6 @@ module.exports = Relay.createContainer(ProfilePicture, { `, }, }); - ``` `RelayMutationTransaction.getStatus` can return one of the following strings: @@ -619,7 +605,6 @@ Relay.createContainer(Child, { `, } }); - ``` In this example, whenever `Parent` is fetched, `Child`'s fragment will also be fetched. When rendering, `` will only have access to the `props.foo.id` field; data from the child fragment will be [_masked_](./thinking-in-relay#data-masking). By default, `childFragment` will use its corresponding initial variables. Relay will fetch `photo(size: 64)`. When `` is rendered it will also make the initial variables available as `props.relay.variables = {size: 64}`. @@ -641,7 +626,6 @@ Relay.createContainer(Parent, { `, } }); - ``` Now Relay will fetch the photo with size 128 - but the `Child` container won't magically know about this variable. We have to tell it by passing the variable value as a prop: @@ -656,7 +640,6 @@ const Parent = (props) => { />; ); } - ``` Now Relay will both fetch the larger photo size _and_ `Child` will know to render it. diff --git a/website/versioned_docs/version-classic/Classic-APIReference-GraphQLMutation.md b/website/versioned_docs/version-classic/Classic-APIReference-GraphQLMutation.md index d8b1337e22425..5c2e626c2539f 100644 --- a/website/versioned_docs/version-classic/Classic-APIReference-GraphQLMutation.md +++ b/website/versioned_docs/version-classic/Classic-APIReference-GraphQLMutation.md @@ -64,7 +64,6 @@ static create( variables: Object, environment: RelayEnvironmentInterface ): RelayGraphQLMutation; - ``` Convenience method that wraps the constructor, passing some default parameters and returning an instance. @@ -93,7 +92,6 @@ const mutation = Relay.GraphQLMutation.create( variables, environment ); - ``` Note: In most cases, it is possible to rely on the default singleton instance of the environment, which is exposed as `Relay.Store`. @@ -112,7 +110,6 @@ static createWithFiles( files: FileMap, environment: RelayEnvironmentInterface ): RelayGraphQLMutation; - ``` #### Example @@ -131,7 +128,6 @@ const mutation = Relay.GraphQLMutation.createWithFiles( files, environment ); - ``` See also: [GraphQLMutation > Constructor](#constructor) @@ -150,7 +146,6 @@ constructor( callbacks: ?RelayMutationTransactionCommitCallbacks, collisionKey: ?string ); - ``` This is the general constructor for creating `Relay.GraphQLMutation` instances with optional `files`, `callbacks` and `collisionKey` arguments. @@ -179,7 +174,6 @@ const mutation = new Relay.GraphQLMutation( }, collisionKey ); - ``` See also: [Relay.Mutation::getCollisionKey()](./classic-api-reference-relay-mutation#getcollisionkey) @@ -193,7 +187,6 @@ applyOptimistic( optimisticResponse: Object, configs: ?Array ): RelayMutationTransaction; - ``` Call this to optimistically apply an update to the store. @@ -229,7 +222,6 @@ const transaction = mutation.applyOptimistic( optimisticQuery, optimisticResponse, ); - ``` See also: [Relay.Mutation::getConfigs()](./classic-api-reference-relay-mutation#getconfigs-abstract-method) @@ -239,7 +231,6 @@ See also: [Relay.Mutation::getConfigs()](./classic-api-reference-relay-mutation# ``` commit(configs: ?Array): RelayMutationTransaction; - ``` Call this to send the mutation to the server. @@ -265,7 +256,6 @@ const configs = [{ }, }]; const transaction = mutation.commit(configs); - ``` See also: [Relay.Mutation::getConfigs()](./classic-api-reference-relay-mutation#getconfigs-abstract-method) @@ -275,7 +265,6 @@ See also: [Relay.Mutation::getConfigs()](./classic-api-reference-relay-mutation# ``` rollback(): void; - ``` Rolls back an optimistic mutation. diff --git a/website/versioned_docs/version-classic/Classic-APIReference-Mutation.md b/website/versioned_docs/version-classic/Classic-APIReference-Mutation.md index 354c083c674f3..84fa112760894 100644 --- a/website/versioned_docs/version-classic/Classic-APIReference-Mutation.md +++ b/website/versioned_docs/version-classic/Classic-APIReference-Mutation.md @@ -100,7 +100,6 @@ type RelayMutationFragments = { // Type of FragmentBuilder type FragmentBuilder = (variables: Variables) => RelayConcreteNode; - ``` We declare our mutations' data dependencies here, just as we would with a container. This is particularly useful to ensure that a set of fields we might want to use in this mutation's optimistic response have been fetched. @@ -125,7 +124,6 @@ class LikeStoryMutation extends Relay.Mutation { return { /* ... */ }; } } - ``` See also: @@ -137,7 +135,6 @@ See also: ``` static initialVariables: {[name: string]: mixed}; - ``` The defaults we specify here will become available to our fragment builders: @@ -156,7 +153,6 @@ class ChangeTodoStatusMutation extends Relay.Mutation { }; /* ... */ } - ``` See also: @@ -175,7 +171,6 @@ static prepareVariables: ?( type RelayMetaRoute = { name: string; } - ``` If we provide to a mutation a method that conforms to the signature described above, it will be given the opportunity to modify the fragment builders' variables, based on the previous variables (or the `initialVariables` if no previous ones exist), the meta route, and the runtime environment. Whatever variables this method returns will become available to this mutation's fragment builders. @@ -196,7 +191,6 @@ class BuySongMutation extends Relay.Mutation { }; /* ... */ } - ``` See also: @@ -214,7 +208,6 @@ Create a mutation instance using the `new` keyword, optionally passing it some p var bookFlightMutation = new BuyPlaneTicketMutation({airport: 'yvr'}); Relay.Store.commitUpdate(bookFlightMutation); - ``` ### getConfigs (abstract method) @@ -241,7 +234,6 @@ class LikeStoryMutation extends Relay.Mutation { }]; } } - ``` See also: [Mutations > Mutator configuration](./classic-guides-mutations#mutator-configuration) @@ -273,7 +265,6 @@ class BuySongMutation extends Relay.Mutation { `, } } - ``` See also: @@ -300,7 +291,6 @@ class LikeStoryMutation extends Relay.Mutation { : return Relay.QL`mutation {likeStory}`; } } - ``` ### getVariables (abstract method) @@ -308,7 +298,6 @@ class LikeStoryMutation extends Relay.Mutation { ``` abstract getVariables(): {[name: string]: mixed} - ``` Implement this required method to prepare variables to be used as input to the mutation. @@ -326,7 +315,6 @@ class DestroyShipMutation extends Relay.Mutation { }; } } - ```
@@ -347,7 +335,6 @@ static getFragment( // Type of the variableMapping argument type Variables = {[name: string]: mixed}; - ``` Gets a fragment reference for use in a parent's query fragment. @@ -368,7 +355,6 @@ class StoryComponent extends React.Component { `, }; } - ``` You can also pass variables to the mutation's fragment builder from the outer fragment that contains it. @@ -390,7 +376,6 @@ class Movie extends React.Component { `, }; } - ```
@@ -420,7 +405,6 @@ class LikeStoryMutation extends Relay.Mutation { return `like_${this.props.story.id}`; } } - ``` ### getFiles @@ -431,7 +415,6 @@ getFiles(): ?FileMap // Type of the FileMap object type FileMap = {[key: string]: File}; - ``` Implement this method to return a map of `File` objects to upload as part of a mutation. @@ -455,7 +438,6 @@ class FileUploader extends React.Component { ); } } - ``` ### getOptimisticConfigs @@ -475,7 +457,6 @@ See also: [Relay.Mutation::getConfigs()](#getconfigs-abstract-method) ``` getOptimisticResponse(): ?{[key: string]: mixed} - ``` Implement this method to craft an optimistic response having the same shape as the server response payload. This optimistic response will be used to preemptively update the client cache before the server returns, giving the impression that the mutation completed instantaneously. @@ -497,7 +478,6 @@ class LikeStoryMutation extends Relay.Mutation { }; } } - ``` See also: [Mutations > Optimistic updates](./classic-guides-mutations#optimistic-updates) diff --git a/website/versioned_docs/version-classic/Classic-APIReference-PropTypes.md b/website/versioned_docs/version-classic/Classic-APIReference-PropTypes.md index efa11da75c862..655d01b56e6a7 100644 --- a/website/versioned_docs/version-classic/Classic-APIReference-PropTypes.md +++ b/website/versioned_docs/version-classic/Classic-APIReference-PropTypes.md @@ -44,5 +44,4 @@ class MyApplication extends React.Component { ); } } - ``` diff --git a/website/versioned_docs/version-classic/Classic-APIReference-QL.md b/website/versioned_docs/version-classic/Classic-APIReference-QL.md index a882b803c7cf6..24bd766f3d589 100644 --- a/website/versioned_docs/version-classic/Classic-APIReference-QL.md +++ b/website/versioned_docs/version-classic/Classic-APIReference-QL.md @@ -12,7 +12,6 @@ var fragment = Relay.QL` name } `; - ``` To execute this code, Relay needs access to the schema - which can be too large to bundle inside the application. Instead, these `Relay.QL` template expressions are transpiled into JavaScript descriptions via the `babel-plugin-relay`. This schema information allows Relay to understand things like the types of field arguments, which fields are connections or lists, and how to efficiently refetch records from the server. @@ -62,7 +61,6 @@ Relay.createContainer(Foo, { `, } }); - ``` ### Inline Fragments @@ -100,7 +98,6 @@ Relay.createContainer(Story, { `, } }); - ``` Note that it is _highly_ recommended that `Relay.Container`s define their own fragments and avoid sharing inline `var fragment = Relay.QL...` values between containers or files. If you find yourself wanting to share inline fragments, it's likely a sign that it's time to refactor and introduce a new container. @@ -132,7 +129,6 @@ Relay.createContainer(Story, { `, } }); - ``` Wherever the inverse grammar serves you better, you can use `@skip(if: ...)` instead of `@include(if: ...)`. @@ -155,7 +151,6 @@ Relay.createContainer(Story, { `, } }); - ``` On the Relay Container the prop `bars` will be an array instead of an object. diff --git a/website/versioned_docs/version-classic/Classic-APIReference-Relay.md b/website/versioned_docs/version-classic/Classic-APIReference-Relay.md index 70f1691240140..72bdc07b6dc1d 100644 --- a/website/versioned_docs/version-classic/Classic-APIReference-Relay.md +++ b/website/versioned_docs/version-classic/Classic-APIReference-Relay.md @@ -126,7 +126,6 @@ var Container = Relay.createContainer(Component, { prepareVariables?: (variables: Object, route: string) => Object, fragments: {[key: string]: Function} }); - ``` Creates a new Relay Container - see the [Container Guide](./classic-guides-containers) for more details and examples. @@ -140,7 +139,6 @@ Relay.injectNetworkLayer(networkLayer: { sendQueries: (queries: Array) => void; supports: (...options: Array): boolean; }); - ``` Overrides the [DefaultNetworkLayer](#defaultnetworklayer-static-property). @@ -166,7 +164,6 @@ class MutationLoggingNetworkLayer extends DefaultNetworkLayer { }; Relay.injectNetworkLayer(new MutationLoggingNetworkLayer()); - ``` ### injectTaskScheduler (static method) @@ -176,7 +173,6 @@ Relay.injectNetworkLayer(new MutationLoggingNetworkLayer()); Relay.injectTaskScheduler(scheduler: Scheduler): void; type Scheduler = (task: Function) => void; - ``` Relay wraps its core processing functions inside lightweight tasks, which by default are executed immediately (i.e. synchronously). In order to customize _when_ these tasks are run - for example to avoid interrupting an animation during a touch gesture - applications can provide a custom scheduling function. @@ -188,7 +184,6 @@ The default implementation is as follows: ``` Relay.injectTaskScheduler(task => task()); - ``` Notice that it immediately executes the next task. Relay manages the order of tasks to ensure a proper order of operations - the scheduler can't skip or reorder tasks, only decide when to execute the next one. @@ -200,7 +195,6 @@ In React Native, we can schedule Relay processing so as to avoid interrupting to var {InteractionManager} = require('react-native'); Relay.injectTaskScheduler(InteractionManager.runAfterInteractions); - ``` You can read more about `InteractionManager` on the [React Native API docs](https://reactnative.dev/docs/interactionmanager.html). @@ -210,7 +204,6 @@ You can read more about `InteractionManager` on the [React Native API docs](http ``` Relay.isContainer(Component: Object): boolean; - ``` #### Example @@ -222,5 +215,4 @@ var Component = require('...'); if (Relay.isContainer(Component)) { Component.getFragment('...'); } - ``` diff --git a/website/versioned_docs/version-classic/Classic-APIReference-Route.md b/website/versioned_docs/version-classic/Classic-APIReference-Route.md index 550489f30a623..de9937dd2aada 100644 --- a/website/versioned_docs/version-classic/Classic-APIReference-Route.md +++ b/website/versioned_docs/version-classic/Classic-APIReference-Route.md @@ -60,7 +60,6 @@ _Methods_ ``` static paramDefinitions: {[param: string]: {required: boolean}} - ``` Routes can declare a set of parameter names that are required to be supplied to the constructor. This is also a convenient place to document the set of valid parameters. @@ -75,7 +74,6 @@ class ProfileRoute extends Relay.Route { }; // ... } - ``` ### prepareParams (static property) @@ -83,7 +81,6 @@ class ProfileRoute extends Relay.Route { ``` static prepareParams: ?(prevParams: {[prevParam: string]: mixed}) => {[param: string]: mixed}; - ``` Routes can use `prepareParams` to provide default parameters, or pass through, convert or suppress passed-in parameters. @@ -108,7 +105,6 @@ class ProfileRoute extends Relay.Route { } // ... } - ``` ### queries (static property) @@ -118,7 +114,6 @@ class ProfileRoute extends Relay.Route { static queries: { [queryName: string]: () => Relay.QL`query { ... }` }; - ``` Routes must declare a set of query roots using `Relay.QL`. These queries will automatically compose a matching fragment named `queryName` on @@ -134,7 +129,6 @@ class ProfileRoute extends Relay.Route { }; // ... } - ``` In this example the Route should be initialized with a `userID` which gets passed on to the query. That `userID` variable will automatically be passed down to the top-level container and can be used there if needed. Further the top-level RelayContainer is expected to have a `user` fragment with the fields to be queried. @@ -160,5 +154,4 @@ Create a route instance using the `new` keyword, optionally passing it some para ``` var profileRoute = new ProfileRoute({userID: '123'}); - ``` diff --git a/website/versioned_docs/version-classic/Classic-APIReference-Store.md b/website/versioned_docs/version-classic/Classic-APIReference-Store.md index 013d5874511ac..dfdf529e7fc07 100644 --- a/website/versioned_docs/version-classic/Classic-APIReference-Store.md +++ b/website/versioned_docs/version-classic/Classic-APIReference-Store.md @@ -44,7 +44,6 @@ static commitUpdate(mutation: RelayMutation, callbacks: { type Transaction = { getError(): ?Error; } - ``` The `commitUpdate` method is analogous to dispatching an action in Flux. Relay processes @@ -70,7 +69,6 @@ var onFailure = (transaction) => { var mutation = new MyMutation({...}); Relay.Store.commitUpdate(mutation, {onFailure, onSuccess}); - ``` ### applyUpdate (static method) @@ -107,5 +105,4 @@ var mutation = new MyMutation({...}); var transaction = Relay.Store.applyUpdate(mutation, {onFailure, onSuccess}); transaction.commit(); - ``` diff --git a/website/versioned_docs/version-classic/Classic-Guides-Containers.md b/website/versioned_docs/version-classic/Classic-Guides-Containers.md index db9e24423485d..fa88012820033 100644 --- a/website/versioned_docs/version-classic/Classic-Guides-Containers.md +++ b/website/versioned_docs/version-classic/Classic-Guides-Containers.md @@ -39,7 +39,6 @@ class ProfilePicture extends React.Component { // TODO: Fetch the profile photo URI for the given size... } } - ``` ### Data Dependencies With GraphQL @@ -89,7 +88,6 @@ module.exports = Relay.createContainer(ProfilePicture, { `, }, }); - ``` ## Containers are Higher-Order Components @@ -145,7 +143,6 @@ class ProfilePicture extends React.Component { }); } } - ``` ## Container Composition @@ -177,7 +174,6 @@ class Profile extends React.Component { ); } } - ``` ### Composing Fragments @@ -207,7 +203,6 @@ module.exports = Relay.createContainer(Profile, { `, } }); - ``` The final data declaration is equivalent to the following plain GraphQL: diff --git a/website/versioned_docs/version-classic/Classic-Guides-Mutations.md b/website/versioned_docs/version-classic/Classic-Guides-Mutations.md index 5aa97582b8887..8a623f9e326ae 100644 --- a/website/versioned_docs/version-classic/Classic-Guides-Mutations.md +++ b/website/versioned_docs/version-classic/Classic-Guides-Mutations.md @@ -69,7 +69,6 @@ class LikeStoryMutation extends Relay.Mutation { `, }; } - ``` Here's an example of this mutation in use by a `LikeButton` component: @@ -109,7 +108,6 @@ module.exports = Relay.createContainer(LikeButton, { `, }, }); - ``` In this particular example, the only field that the `LikeButton` cares about is `viewerDoesLike`. That field will form part of the tracked query that Relay will intersect with the fat query of `LikeStoryMutation` to determine what fields to request as part of the server's response payload for the mutation. Another component elsewhere in the application might be interested in the likers count, or the like sentence. Since those fields will automatically be added to Relay's tracked query, the `LikeButton` need not worry about requesting them explicitly. @@ -138,7 +136,6 @@ class LikeStoryMutation extends Relay.Mutation { } /* ... */ } - ``` ## Fragment variables @@ -174,7 +171,6 @@ class RentMovieMutation extends Relay.Mutation { `, }; } - ``` ## The fat query @@ -209,7 +205,6 @@ class AcceptFriendRequestMutation extends Relay.Mutation { `; } } - ``` This fat query looks like any other GraphQL query, with one important distinction. We know some of these fields to be non-scalar (like `friendEdge` and `friends`) but notice that we have not named any of their children by way of a subquery. In this way, we indicate to Relay that _anything_ under those non-scalar fields may change as a result of this mutation. @@ -264,7 +259,6 @@ class RenameDocumentMutation extends Relay.Mutation { } /* ... */ } - ``` ### `NODE_DELETE` @@ -320,7 +314,6 @@ class DestroyShipMutation extends Relay.Mutation { } /* ... */ } - ``` ### `RANGE_ADD` @@ -360,7 +353,6 @@ const rangeBehaviors = { // Prepend the ship, wherever the connection is sorted by age 'orderby(newest)': 'prepend', }; - ``` Or this way, with the same results: @@ -418,7 +410,6 @@ class IntroduceShipMutation extends Relay.Mutation { } /* ... */ } - ``` ### `RANGE_DELETE` @@ -464,7 +455,6 @@ class RemoveTagMutation extends Relay.Mutation { } /* ... */ } - ``` ### `REQUIRED_CHILDREN` @@ -483,7 +473,6 @@ this.props.relay.commitUpdate( }), } ); - ``` #### Arguments @@ -531,7 +520,6 @@ class CreateCouponMutation extends Relay.Mutation { }]; } } - ``` ## Optimistic updates @@ -585,7 +573,6 @@ class LikeStoryMutation extends Relay.Mutation { }; /* ... */ } - ``` You don't have to mimic the entire response payload. Here, we've punted on the like sentence, since it's difficult to localize on the client side. When the server responds, Relay will treat its payload as the source of truth, but in the meantime, the optimistic response will be applied right away, allowing the people who use our product to enjoy instant feedback after having taken an action. diff --git a/website/versioned_docs/version-classic/Classic-Guides-NetworkLayer.md b/website/versioned_docs/version-classic/Classic-Guides-NetworkLayer.md index a41f085ba09bb..f19ee2aee4f85 100644 --- a/website/versioned_docs/version-classic/Classic-Guides-NetworkLayer.md +++ b/website/versioned_docs/version-classic/Classic-Guides-NetworkLayer.md @@ -16,7 +16,6 @@ By default, Relay assumes that GraphQL is served at `/graphql` relative to the o Relay.injectNetworkLayer( new Relay.DefaultNetworkLayer('http://example.com/graphql') ); - ``` Underneath the hood, the default network layer uses `fetch` ([Living Standard](https://fetch.spec.whatwg.org)). The constructor for `Relay.DefaultNetworkLayer` takes an optional second argument that accepts any valid initialization property that `fetch` accepts. @@ -28,7 +27,6 @@ Relay.injectNetworkLayer( credentials: 'same-origin', }) ); - ``` When it sends queries, it will automatically fail requests after a 15 second timeout. Also, failed requests are automatically retried twice, with a 1 second delay and a 3 second delay, respectively. @@ -43,7 +41,6 @@ Relay.injectNetworkLayer( retryDelays: [5000], // Only retry once after a 5s delay. }) ); - ``` Unlike queries, failed requests for mutations are not automatically retried. @@ -59,7 +56,6 @@ Relay.injectNetworkLayer( }, }) ); - ``` ## Custom Network Layers @@ -85,7 +81,6 @@ var myNetworkLayer = { }; Relay.injectNetworkLayer(myNetworkLayer); - ``` You can read more about the API [RelayNetworkLayer](./classic-interfaces-relay-network-layer) interface. diff --git a/website/versioned_docs/version-classic/Classic-Guides-RootContainer.md b/website/versioned_docs/version-classic/Classic-Guides-RootContainer.md index adaad38799b3a..7e094e098aeea 100644 --- a/website/versioned_docs/version-classic/Classic-Guides-RootContainer.md +++ b/website/versioned_docs/version-classic/Classic-Guides-RootContainer.md @@ -23,7 +23,6 @@ ReactDOM.render( />, container ); - ``` When the **Relay.RootContainer** above is rendered, Relay will construct a query and send it to the GraphQL server. As soon as all required data has been fetched, `ProfilePicture` will be rendered. Props with fragments will contain data that was fetched from the server. diff --git a/website/versioned_docs/version-classic/Classic-Guides-Routes.md b/website/versioned_docs/version-classic/Classic-Guides-Routes.md index 59098aa5ae65d..bbf31713a7bd9 100644 --- a/website/versioned_docs/version-classic/Classic-Guides-Routes.md +++ b/website/versioned_docs/version-classic/Classic-Guides-Routes.md @@ -23,7 +23,6 @@ query UserQuery { name, }, } - ``` On the other hand, GraphQL **fragments** declare fields that exist on any arbitrary type. For example, the following fragment fetches the profile picture URI for _some_ `User`. @@ -35,7 +34,6 @@ fragment UserProfilePhoto on User { uri, }, } - ``` Fragments can be embedded within other fragments or queries. For example, the above fragment could be used to fetch user `123`'s profile photo: @@ -47,7 +45,6 @@ query UserQuery { ...UserProfilePhoto, }, } - ``` However, the fragment could also fetch each of user `123`'s friends' profile photos: @@ -65,7 +62,6 @@ query UserQuery { }, }, } - ``` Since Relay containers define fragments and not queries, they can be easily embedded in multiple contexts. Like React components, Relay containers are highly reusable. @@ -93,7 +89,6 @@ var profileRoute = { // Routes must also define a string name. name: 'ProfileRoute', }; - ``` If we wanted to create an instance of this route for arbitrary users, we can subclass the `Relay.Route` abstract class. `Relay.Route` makes it easy to define a set of queries and required parameters to be re-used multiple times: @@ -113,7 +108,6 @@ class ProfileRoute extends Relay.Route { }; static routeName = 'ProfileRoute'; } - ``` Now we can instantiate a `ProfileRoute` that fetches data for user `123`: @@ -122,7 +116,6 @@ Now we can instantiate a `ProfileRoute` that fetches data for user `123`: // Equivalent to the object literal we created above. var profileRoute = new ProfileRoute({userID: '123'}); - ``` But now, we can also create routes for arbitrary user IDs. For example, if we wanted to construct a route that fetched data for a user defined by the `userID` query parameter, we might use: @@ -140,5 +133,4 @@ window.addEventListener('popstate', () => { document.getElementById('app') ); }); - ``` diff --git a/website/versioned_docs/version-classic/Classic-Interfaces-MutationRequest.md b/website/versioned_docs/version-classic/Classic-Interfaces-MutationRequest.md index 41ee3b96d0cbe..e178fc3fa24a5 100644 --- a/website/versioned_docs/version-classic/Classic-Interfaces-MutationRequest.md +++ b/website/versioned_docs/version-classic/Classic-Interfaces-MutationRequest.md @@ -54,7 +54,6 @@ Gets a string representation of the GraphQL mutation. ``` getVariables(): {[name: string]: mixed} - ``` Gets the variables used by the mutation. These variables should be serialized and send in the GraphQL request. @@ -64,7 +63,6 @@ Gets the variables used by the mutation. These variables should be serialized an ``` getFiles(): ?{[key: string]: File} - ``` Gets an optional map from name to File objects. diff --git a/website/versioned_docs/version-classic/Classic-Interfaces-NetworkLayer.md b/website/versioned_docs/version-classic/Classic-Interfaces-NetworkLayer.md index 52f7012b4713a..c880b51147330 100644 --- a/website/versioned_docs/version-classic/Classic-Interfaces-NetworkLayer.md +++ b/website/versioned_docs/version-classic/Classic-Interfaces-NetworkLayer.md @@ -54,7 +54,6 @@ sendMutation(mutationRequest) { } }); } - ``` See [RelayMutationRequest](./classic-interfaces-relay-mutation-request) for methods available on the argument object. @@ -88,7 +87,6 @@ sendQueries(queryRequests) { }) )); } - ``` See [RelayQueryRequest](./classic-interfaces-relay-query-request) for methods available on the argument objects. @@ -117,5 +115,4 @@ supports(...options) { return false; }); } - ``` diff --git a/website/versioned_docs/version-classic/Classic-Interfaces-QueryRequest.md b/website/versioned_docs/version-classic/Classic-Interfaces-QueryRequest.md index 97ca2ebb63a39..86be8e399ce46 100644 --- a/website/versioned_docs/version-classic/Classic-Interfaces-QueryRequest.md +++ b/website/versioned_docs/version-classic/Classic-Interfaces-QueryRequest.md @@ -49,7 +49,6 @@ Gets a string representation of the GraphQL query. ``` getVariables(): {[name: string]: mixed} - ``` Gets the variables used by the query. These variables should be serialized and sent in the GraphQL request. diff --git a/website/versioned_docs/version-classic/PrinciplesAndArchitecture-ThinkingInRelay.md b/website/versioned_docs/version-classic/PrinciplesAndArchitecture-ThinkingInRelay.md index e61f3fd21c933..62b1914ef3ff9 100644 --- a/website/versioned_docs/version-classic/PrinciplesAndArchitecture-ThinkingInRelay.md +++ b/website/versioned_docs/version-classic/PrinciplesAndArchitecture-ThinkingInRelay.md @@ -30,13 +30,11 @@ fragment Story_story on Story { photo } } - ``` And this fragment can then be used to define the Story container: ```javascript - const {createFragmentContainer, graphql} = require('react-relay'); // Plain React component. @@ -64,7 +62,6 @@ const StoryContainer = createFragmentContainer(Story, { In React, rendering a view requires two inputs: the _component_ to render, and a _root_ DOM (UI) node to render into. Rendering Relay containers is similar: we need a _container_ to render, and a _root_ in the graph from which to start our query. We also must ensure that the queries for the container are executed and may want to show a loading indicator while data is being fetched. Similar to `ReactDOM.render(component, domNode)`, Relay provides `` for this purpose. The `query` and `variables` define what data to fetch and `render` defines what to render. Here's how we might render ``: ```javascript - ReactDOM.render( // This resolves to a list of items with linked resources: @@ -25,13 +24,11 @@ rest.get('/stories').then(stories => // `[ { id: "...", text: "..." } ]` console.log(stories); }); - ``` Note that this approach requires _n+1_ requests to the server: 1 to fetch the list, and _n_ to fetch each item. With GraphQL we can fetch the same data in a single network request to the server (without creating a custom endpoint that we'd then have to maintain): ```javascript - graphql.get(`query { stories { id, text } }`).then( stories => { // A list of story items: @@ -39,7 +36,6 @@ graphql.get(`query { stories { id, text } }`).then( console.log(stories); } ); - ``` So far we're just using GraphQL as a more efficient version of typical REST approaches. Note two important benefits in the GraphQL version: @@ -56,7 +52,6 @@ Repeatedly refetching information from the server can get quite slow. For exampl In a resource-oriented REST system, we can maintain a **response cache** based on URIs: ```javascript - var _cache = new Map(); rest.get = uri => { if (!_cache.has(uri)) { @@ -64,13 +59,11 @@ rest.get = uri => { } return _cache.get(uri); }; - ``` Response-caching can also be applied to GraphQL. A basic approach would work similarly to the REST version. The text of the query itself can be used as a cache key: ```javascript - var _cache = new Map(); graphql.get = queryText => { if (!_cache.has(queryText)) { @@ -78,7 +71,6 @@ graphql.get = queryText => { } return _cache.get(queryText); }; - ``` Now, requests for previously cached data can be answered immediately without making a network request. This is a practical approach to improving the perceived performance of an application. However, this method of caching can cause problems with data consistency. @@ -90,7 +82,6 @@ With GraphQL it is very common for the results of multiple queries to overlap. H ``` query { stories { id, text, likeCount } } - ``` and then later refetch one of the stories whose `likeCount` has since been incremented: @@ -98,7 +89,6 @@ and then later refetch one of the stories whose `likeCount` has since been incre ``` query { story(id: "123") { id, text, likeCount } } - ``` We'll now see different `likeCount`s depending on how the story is accessed. A view that uses the first query will see an outdated count, while a view using the second query will see the updated count. @@ -119,7 +109,6 @@ query { } } } - ``` And here's a possible response: @@ -134,13 +123,11 @@ query: { } } } - ``` Although the response is hierarchical, we'll cache it by flattening all the records. Here is an example of how Relay would cache this query response: ```javascript - Map { // `story(id: "1")` 1: Map { @@ -152,7 +139,6 @@ Map { name: 'Jan', }, }; - ``` This is only a simple example: in reality the cache must handle one-to-many associations and pagination (among other things). @@ -182,7 +168,6 @@ The first query was for a list of stories: ``` query { stories { id, text, likeCount } } - ``` With a normalized response cache, a record would be created for each story in the list. The `stories` field would store links to each of these records. @@ -192,7 +177,6 @@ The second query refetched the information for one of those stories: ``` query { story(id: "123") { id, text, likeCount } } - ``` When this response is normalized, Relay can detect that this result overlaps with existing data based on its `id`. Rather than create a new record, Relay will update the existing `123` record. The new `likeCount` is therefore available to _both_ queries, as well as any other query that might reference this story. @@ -215,7 +199,6 @@ query { } } } - ``` After initially fetching this story our cache might be as follows. Note that the story and comment both link to the same record as `author`: @@ -242,7 +225,6 @@ Map { author: Link(2), }, } - ``` The author of this story also commented on it — quite common. Now imagine that some other view fetches new information about the author, and her profile photo has changed to a new URI. Here's the _only_ part of our cached data that changes: @@ -256,7 +238,6 @@ Map { photo: 'http://.../photo2.jpg', }, } - ``` The value of the `photo` field has changed; and therefore the record `2` has also changed. And that's it. Nothing else in the _cache_ is affected. But clearly our _view_ needs to reflect the update: both instances of the author in the UI (as story author and comment author) need to show the new photo. @@ -273,7 +254,6 @@ ImmutableMap { }, 3: ImmutableMap // same as before } - ``` If we replace `2` with a new immutable record, we'll also get a new immutable instance of the cache object. However, records `1` and `3` are untouched. Because the data is normalized, we can't tell that `story`'s contents have changed just by looking at the `story` record alone. @@ -299,7 +279,6 @@ mutation StoryLike($storyID: String) { likeCount } } - ``` Notice that we're querying for data that _may_ have changed as a result of the mutation. An obvious question is: why can't the server just tell us what changed? The answer is: it's complicated. GraphQL abstracts over _any_ data storage layer (or an aggregation of multiple sources), and works with any programming language. Furthermore, the goal of GraphQL is to provide data in a form that is useful to product developers building a view. diff --git a/website/versioned_docs/version-experimental/PrinciplesAndArchitecture-ThinkingInRelay.md b/website/versioned_docs/version-experimental/PrinciplesAndArchitecture-ThinkingInRelay.md index e61f3fd21c933..62b1914ef3ff9 100644 --- a/website/versioned_docs/version-experimental/PrinciplesAndArchitecture-ThinkingInRelay.md +++ b/website/versioned_docs/version-experimental/PrinciplesAndArchitecture-ThinkingInRelay.md @@ -30,13 +30,11 @@ fragment Story_story on Story { photo } } - ``` And this fragment can then be used to define the Story container: ```javascript - const {createFragmentContainer, graphql} = require('react-relay'); // Plain React component. @@ -64,7 +62,6 @@ const StoryContainer = createFragmentContainer(Story, { In React, rendering a view requires two inputs: the _component_ to render, and a _root_ DOM (UI) node to render into. Rendering Relay containers is similar: we need a _container_ to render, and a _root_ in the graph from which to start our query. We also must ensure that the queries for the container are executed and may want to show a loading indicator while data is being fetched. Similar to `ReactDOM.render(component, domNode)`, Relay provides `` for this purpose. The `query` and `variables` define what data to fetch and `render` defines what to render. Here's how we might render ``: ```javascript - ReactDOM.render( {data.user?.name} ); } - ``` Lets see what's going on here: @@ -494,7 +466,6 @@ Lets see what's going on here: To fetch and render a query that includes a fragment, you can compose them in the same way fragments are composed, as shown in the [Composing Fragments](#composing-fragments) section: ```javascript - /** * UserComponent.react.js * @@ -520,11 +491,9 @@ function UserComponent(props: Props) { } module.exports = UserComponent; - ``` ```javascript - /** * App.react.js * @@ -561,7 +530,6 @@ function App() { ); } - ``` Note that: @@ -576,7 +544,6 @@ You may have noticed that the query declarations in our examples above contain r GraphQL variables are a construct that allows referencing dynamic values inside a GraphQL query. When fetching a query from the server, we also need to provide as input the actual set of values to use for the variables declared inside the query: ```graphql - # `$id` is a variable of type `ID!` query UserQuery($id: ID!) { @@ -586,13 +553,11 @@ query UserQuery($id: ID!) { name } } - ``` When sending a network request to fetch the query above, we need to provide both the query, and the variables to be used for this particular execution of the query. For example: ```graphql - # Query: query UserQuery($id: ID!) { # ... @@ -600,13 +565,11 @@ query UserQuery($id: ID!) { # Variables: {"id": 4} - ``` Fetching the above query and variables from the server would produce the following response: ```javascript - { "data": { "user": { @@ -615,7 +578,6 @@ Fetching the above query and variables from the server would produce the followi } } } - ``` - Note that changing the value of the `id` variable used as input would of course produce a different response. @@ -625,7 +587,6 @@ Fetching the above query and variables from the server would produce the followi Fragments can also reference variables that have been declared by a query: ```graphql - fragment UserFragment on User { name profile_picture(scale: $scale) { @@ -640,7 +601,6 @@ query ViewerQuery($scale: Float!) { } } } - ``` - Even though the fragment above doesn't _declare_ the `$scale` variable directly, it can still reference it. Doing so makes it so any query that includes this fragment, either directly or transitively, **_must_** declare the variable and it's type, otherwise an error will be produced by the Relay compiler. @@ -649,7 +609,6 @@ query ViewerQuery($scale: Float!) { In Relay, fragment declarations inside components can also reference query variables: ```javascript - function UserComponent(props: Props) { const data = useFragment( graphql` @@ -665,7 +624,6 @@ function UserComponent(props: Props) { return (...); } - ``` - The above fragment could be included by multiple queries, and rendered by different components, which means that any query that ends up rendering/including the above fragment **_must_** declare the `$scale` variable. @@ -676,7 +634,6 @@ function UserComponent(props: Props) { However, in order to prevent bloating queries with global variable declarations, Relay also provides a way to declare variables that are scoped locally to a fragment using the **`@arguments`** and **`@argumentDefinitions`** directives: ```javascript - /** * Declare a fragment that accepts arguments with @argumentDefinitions */ @@ -697,11 +654,9 @@ function PictureComponent(props) { props.user, ); } - ``` ```javascript - /** * Include fragment using @arguments */ @@ -719,11 +674,9 @@ function UserComponent(props) { props.user, ); } - ``` ```javascript - /** * Include same fragment using _different_ @arguments */ @@ -742,7 +695,6 @@ function OtherUserComponent(props) { props.user, ); } - ``` - Note that when passing `@arguments` to a fragment, we can pass a literal value or pass another variable. The variable can be a global query variable, or another local variable declared via `@argumentDefinitions`. @@ -753,7 +705,6 @@ function OtherUserComponent(props) { Fragments that expect arguments can also declare default values, making the arguments optional: ```javascript - /** * Declare a fragment that accepts arguments with default values */ @@ -774,11 +725,9 @@ function PictureComponent(props) { props.user, ); } - ``` ```javascript - function UserComponent(props) { const data = useFragment( graphql` @@ -792,7 +741,6 @@ function UserComponent(props) { props.user, ); } - ``` - Not passing the argument to `PictureComponent_user` makes it use the default value for its locally declared `$scale` variable, in this case 2.0. @@ -818,7 +766,6 @@ For a lot more details on Suspense, check the [React docs on Suspense](https://r When a component is suspended, we need to render a _fallback_ in place of the component while we await for it to become _"ready"_. In order to do so, we use the `Suspense` component provided by React: ```javascript - const React = require('React'); const {Suspense} = require('React'); @@ -830,7 +777,6 @@ function App() { ); } - ``` `Suspense` components can be used to wrap any component; if the target component suspends, `Suspense` will render the provided fallback until all its descendants become _"ready"_ (i.e. until _all_ of the promises thrown inside its subtree of descendants resolve). Usually, the fallback is used to render a loading state, such as a glimmer. @@ -838,7 +784,6 @@ function App() { Usually, different pieces of content in our app might suspend, so we can show loading state until they are resolved by using `Suspense` : ```javascript - /** * App.react.js */ @@ -859,7 +804,6 @@ function App() { ); } - ``` Let's distill what's going on here: @@ -869,7 +813,6 @@ Let's distill what's going on here: What's nice about Suspense is that you have granular control about how to accumulate loading states for different parts of your component tree: ```javascript - /** * App.react.js */ @@ -892,7 +835,6 @@ function App() { ); } - ``` - In this case, both `MainContent` and `SecondaryContent` may suspend while they load their asynchronous resources; by wrapping both in a `Suspense`, we can show a single loading state up until they are **_all_** ready, and then render the entire content in a single paint, after everything has successfully loaded. @@ -901,7 +843,6 @@ function App() { Conversely, you can also decide to be more granular about your loading UI and wrap Suspense components around smaller or individual parts of your component tree: ```javascript - /** * App.react.js */ @@ -935,7 +876,6 @@ function App() { ); } - ``` - In this case, we're showing 2 separate loading UIs: @@ -950,7 +890,6 @@ function App() { Whenever we're going to make a transition that might cause new content to suspend, we should use the [**`useTransition`**](https://reactjs.org/docs/concurrent-mode-patterns.html#transitions) to schedule the update for transition: ```javascript - const { useState, useTransition, @@ -978,7 +917,6 @@ function TabSwitcher() { ); } - ``` Let's take a look at what's happening here: @@ -993,7 +931,6 @@ The **_pending_** stage is the first state in a transition, and is usually rende By default, when a suspense transition occurs, if the new content suspends, React will automatically transition to the loading state and show the fallbacks from any `Suspense` boundaries that are in place for the new content. However, if we want to delay showing the loading state, and show a _pending_ state instead, we can also use [**`useTransition`**](https://reactjs.org/docs/concurrent-mode-patterns.html#transitions) to do so: ```javascript - const { useState, useTransition, @@ -1031,7 +968,6 @@ function TabSwitcher() { ); } - ```
@@ -1054,7 +990,6 @@ In our case, our query renderer components are components that can suspend, so w Say we have the following query renderer component: ```javascript - /** * MainContent.react.js * @@ -1073,11 +1008,9 @@ function MainContent() { return (...); } - ``` ```javascript - /** * App.react.js */ @@ -1098,7 +1031,6 @@ function App() { ); } - ``` Let's distill what's going on here: @@ -1123,7 +1055,6 @@ We can use [**Error Boundary**](https://reactjs.org/docs/error-boundaries.html) [Error boundaries](https://reactjs.org/docs/error-boundaries.html) are simply components that implement the static **`getDerivedStateFromError`** method: ```javascript - const React = require('React'); type State = {|error: ?Error|}; @@ -1134,13 +1065,11 @@ class ErrorBoundary extends React.Component { return {error: error}; } } - ``` Which we can use like so: ```javascript - /** * App.react.js */ @@ -1161,7 +1090,6 @@ function App() { ); } - ``` - We can use the Error Boundary to wrap subtrees and show a different UI when an error occurs within that subtree. When an error occurs, the specified `fallback` will be rendered instead of the content inside the boundary. @@ -1172,7 +1100,6 @@ function App() { In order to retry fetching a query after an error has occurred, we can attempt to re-mount the query component that produced an error: ```javascript - /** * ErrorBoundaryWithRetry.react.js */ @@ -1206,11 +1133,9 @@ class ErrorBoundaryWithRetry extends React.Component { return children; } } - ``` ```javascript - /** * App.react.js */ @@ -1237,7 +1162,6 @@ function App() { ); } - ``` - The sample Error Boundary in this example code will provide a `retry` function to re-attempt to render the content that originally produced the error. By doing so, we will attempt to re-render our query component (that uses `useLazyLoadQuery`), and consequently attempt to fetch the query again. @@ -1254,7 +1178,6 @@ If you wish to access error information in your application to display user-frie For example, you could expose a field in your schema that returns either the expected result, or an Error object if an error occurred while resolving that field (instead of returning null): ```graphql - type Error { # User friendly message message: String! @@ -1263,7 +1186,6 @@ type Error { type Foo { bar: Result | Error } - ``` ### Environment @@ -1273,7 +1195,6 @@ type Foo { In order to render Relay components, you need to render a `RelayEnvironmentProvider` component at the root of the app: ```javascript - // App root const {RelayEnvironmentProvider} = require('react-relay/hooks'); @@ -1285,7 +1206,6 @@ function Root() { ); } - ``` - The `RelayEnvironmentProvider `takes an environment, which it will make available to all descendant Relay components, and which is necessary for Relay to function. @@ -1295,7 +1215,6 @@ function Root() { If you want to access the _current_ Relay Environment within a descendant of a `RelayEnvironmentProvider` component, you can use the **`useRelayEnvironment`** Hook: ```javascript - const {useRelayEnvironment} = require('react-relay/hooks'); function UserComponent(props: Props) { @@ -1303,7 +1222,6 @@ function UserComponent(props: Props) { return (...); } - ``` ## Reusing Cached Data for Render @@ -1342,7 +1260,6 @@ function App() {

{data.user?.name}

); } - ``` The provided `fetchPolicy` will determine: @@ -1393,7 +1310,6 @@ By default, any query components using useLazyLoadQuery or our other APIs will r If you need to retain a specific query outside of the components lifecycle, you can use the [**`retain`**](#retaining-queries) operation: ```javascript - // Retain query; this will prevent the data for this query and // variables from being garbage collected by Relay const disposable = environment.retain(queryDescriptor); @@ -1402,7 +1318,6 @@ const disposable = environment.retain(queryDescriptor); // and variables, meaning that it can be deleted at any moment // by Relay's garbage collection if it hasn't been retained elsewhere disposable.dispose(); - ``` - As mentioned, this will allow you to retain the query even after a query component has unmounted, allowing other components, or future instances of the same component, to reuse the retained data. @@ -1416,7 +1331,6 @@ There are currently 2 options you can provide to your Relay Store in to control The **`gcScheduler`** is a function you can provide to the Relay Store which will determine when a GC execution should be scheduled to run: ```javascript - // Sample scheduler function // Accepts a callback and schedules it to run at some future time. function gcScheduler(run: () => void) { @@ -1424,7 +1338,6 @@ function gcScheduler(run: () => void) { } const store = new Store(source, {gcScheduler}); - ``` - By default, if a `gcScheduler` option is not provided, Relay will schedule garbage collection using the `resolveImmediate` function. @@ -1437,9 +1350,7 @@ The Relay Store internally holds a release buffer to keep a specific (configurab In order to configure the size of the release buffer, you can provide a **`gcReleaseBufferSize`** option to the Relay Store: ```javascript - const store = new Store(source, {gcReleaseBufferSize: 10}); - ``` - Note that having a buffer size of 0 is equivalent to not having the release buffer, which means that queries will be immediately released and collected. @@ -1461,11 +1372,9 @@ The coarsest type of data invalidation we can perform is invalidating the whole To invalidate the store, we can call **`invalidateStore()`** within an [updater](#updater-functions) function: ```javascript - function updater(store) { store.invalidateStore(); } - ``` - Calling `invalidateStore()` will cause **_all_** data that was written to the store before invalidation occurred to be considered stale, and will require any query to be refetched again the next time it’s evaluated. @@ -1478,14 +1387,12 @@ We can also be more granular about which data we invalidate and only invalidate To invalidate a record, we can call **`invalidateRecord()`** within an [updater](#updater-functions) function: ```javascript - function updater(store) { const user = store.get(''); if (user != null) { user.invalidateRecord(); } } - ``` - Calling `invalidateRecord()` on the user record will mark _that_ specific user in the store as stale. That means that any query that is cached and references that invalidated user will now be considered stale, and will require to be refetched again the next time it’s evaluated. @@ -1503,7 +1410,6 @@ This is useful for a lot of use cases, but there are some times when we’d like To support these use cases, Relay exposes the **`useSubscribeToInvalidationState`** hook: ```javascript - function ProfilePage(props) { // Example of querying data for the current page for a given user const data = usePreloadedQuery( @@ -1524,7 +1430,6 @@ function ProfilePage(props) { return (...); } - ``` - `useSubscribeToInvalidationState` takes an array of ids, and a callback. Whenever any of the records for those ids are marked as stale, the provided callback will fire. @@ -1547,7 +1452,6 @@ To do this, we rely on the ability of fragment containers to [_suspend_](#loadin Let's explain what this means with an example. Say we have the following fragment component: ```javascript - /** * UsernameComponent.react.js * @@ -1576,13 +1480,11 @@ function UsernameComponent(props: Props) { } module.exports = UsernameComponent; - ``` And we have the following query component, which queries for some data, and also includes the fragment above: ```javascript - /** * App.react.js * @@ -1615,7 +1517,6 @@ function App() { ); } - ``` Say that when this `App` component is rendered, we've already previously fetched _(_only_)_ the **`name`** for the `User` with `{id: 4}`, and it is locally cached in the Relay Store. @@ -1631,7 +1532,6 @@ At this point, when `UsernameComponent` suspends due to the missing **`username` In order to achieve the desired effect of rendering the **`name`** when it's available even if the **`username`** is missing, we just need to wrap the `UsernameComponent` in `Suspense,` to _allow_ the other parts of `App` to continue rendering: ```javascript - /** * App.react.js * @@ -1672,7 +1572,6 @@ function App() { ); } - ``` * * * @@ -1686,14 +1585,12 @@ In the previous section we covered how to reuse data that is fully or partially However, when using different queries, there might still be cases where different queries point to the same data, which we'd want to be able to reuse. For example, imagine the following two queries: ```graphql - // Query 1 query UserQuery { user(id: 4) { name } } - ``` ``` @@ -1706,7 +1603,6 @@ query NodeQuery { } } } - ``` These two queries are different, but reference the exact same data. Ideally, if one of the queries was already cached in the store, we should be able to reuse that data when rendering the other query. However, Relay doesn't have this knowledge by default, so we need to configure it to encode the knowledge that a `node(id: 4)` **_"is also a"_** `user(id: 4)`. @@ -1714,7 +1610,6 @@ These two queries are different, but reference the exact same data. Ideally, if To do so, we can provide **`missingFieldHandlers`** to the `RelayEnvironment`, which specify this knowledge: ```javascript - const {ROOT_TYPE, Environment} = require('react-relay'); const missingFieldHandlers = [ @@ -1749,7 +1644,6 @@ const environment = new Environment({ // and other fields missingFieldHandlers, }); - ``` - `missingFieldHandlers` is an array of _handlers_. Each handler must specify a `handle` function, and the kind of missing fields it knows how to handle. The 2 main types of fields that you'd want to handle are: @@ -1775,7 +1669,6 @@ Assuming you're not using real-time updates to update your data (e.g. using [Gra To refresh a query, you can use the **`fetchQuery`** function described in our [Fetching Queries](#fetching-queries) section. Specifically, you can call `fetchQuery` inside the component with the exact same query and variables. Given that the query component is subscribed to any changes in its own data, when the request completes, the component will automatically update and re-render with the latest data: ```javascript - import type {AppQuery} from 'AppQuery.graphql'; const React = require('React'); @@ -1814,13 +1707,11 @@ function App() { ); } - ``` If you want to know whether the request is in flight, in order to show a busy indicator or disable a UI control, you can subscribe to the observable returned by `fetchQuery`, and keep state in your component: ```javascript - import type {AppQuery} from 'AppQuery.graphql'; const React = require('React'); @@ -1868,7 +1759,6 @@ function App() { ); } - ``` #### Refreshing Fragments @@ -1878,7 +1768,6 @@ In order to refresh the data for a fragment, we can also use `fetchQuery`, but w However, we don't need to manually write the query; instead, we can use the **`@refetchable`** directive, which will make it so Relay automatically generates a query to fetch the fragment when the compiler is run: ```javascript - import type {UserComponent_user$key} from 'UserComponent_user.graphql'; const React = require('React'); @@ -1928,7 +1817,6 @@ function UserComponent(props: Props) { } module.exports = UserComponent; - ``` - Relay will autogenerate a query by adding the `@refetchable` directive to our fragment, and we can import it and pass it to `fetchQuery`. Note that `@refetchable` directive can only be added to fragments that are "refetchable", that is, on fragments that are on `Viewer`, or on `Query`, or on a type that implements `Node` (i.e. a type that has an `id` field). @@ -1951,7 +1839,6 @@ Some examples of when you might want to do this: As mentioned in the [Queries](#queries) section, passing **_different query variables_** than the ones originally passed when using `useLazyLoadQuery` will cause the query to be fetched with the new variables, and re-render your component with the new data: ```javascript - import type {AppQuery} from 'AppQuery.graphql'; const React = require('React'); @@ -1989,7 +1876,6 @@ function App() { ); } - ``` Let's distill what's going on here: @@ -2001,7 +1887,6 @@ Let's distill what's going on here: You can also provide a different **`fetchPolicy`** when refetching the query in order to specify whether to use locally cached data (as we covered in [Reusing Cached Data for Render](#reusing-cached-data-for-render)): ```javascript - import type {AppQuery} from 'AppQuery.graphql'; const React = require('React'); @@ -2046,7 +1931,6 @@ function App() { ); } - ``` - In this case, we're keeping both the `fetchPolicy` and `variables` in component state in order to trigger a refetch both with different `variables` and a different `fetchPolicy`. @@ -2058,7 +1942,6 @@ Sometimes, upon an event or user interaction, we'd like to render the _same_ exa To do so, you can use the **`useRefetchableFragment`** hook, in order to refetch a fragment under new query and variables, using the **`refetch`** function: ```javascript - import type {CommentBodyRefetchQuery} from 'CommentBodyRefetchQuery.graphql'; import type {CommentBody_comment$key} from 'CommentBody_comment.graphql'; @@ -2100,7 +1983,6 @@ function CommentBody(props: Props) { } module.exports = CommentBody; - ``` Let's distill what's happening in this example: @@ -2129,7 +2011,6 @@ More specifically, we perform _cursor-based pagination,_ in which the input used In Relay, in order to perform pagination, first you need to declare a fragment that queries for a connection: ```javascript - const {graphql} = require('react-relay'); const userFragment = graphql` @@ -2145,7 +2026,6 @@ const userFragment = graphql` } } `; - ``` - In the example above, we're querying for the `friends` field, which is a connection; in other words, it adheres to the connection spec. Specifically, we can query the `edges` and `node`s in the connection; the `edges` usually contain information about the relationship between the entities, while the `node`s are the actual entities at the other end of the relationship; in this case, the `node`s are objects of type `User` representing the user's friends. @@ -2155,7 +2035,6 @@ const userFragment = graphql` In order to render this fragment which queries for a connection, we can use the **`usePaginationFragment`** Hook: ```javascript - import type {FriendsListPaginationQuery} from 'FriendsListPaginationQuery.graphql'; import type {FriendsListComponent_user$key} from 'FriendsList_user.graphql'; @@ -2208,7 +2087,6 @@ function FriendsListComponent(props: Props) { } module.exports = FriendsListComponent; - ``` - `usePaginationFragment` behaves the same way as a `useFragment` ([Fragments](#fragments)), so our list of friends is available under **`data.friends.edges.node`**, as declared by the fragment. However, it also has a few additions: @@ -2222,7 +2100,6 @@ module.exports = FriendsListComponent; To actually perform pagination over the connection, we need use the **`loadNext`** function to fetch the next page of items, which is available from `usePaginationFragment`: ```javascript - import type {FriendsListPaginationQuery} from 'FriendsListPaginationQuery.graphql'; import type {FriendsListComponent_user$key} from 'FriendsList_user.graphql'; @@ -2283,7 +2160,6 @@ function FriendsListComponent(props: Props) { } module.exports = FriendsListComponent; - ``` Let's distill what's happening here: @@ -2296,7 +2172,6 @@ Let's distill what's happening here: Often, you will also want to access information about whether there are more items available to load. To do this, you can use the `hasNext` value, also available from `usePaginationFragment`: ```javascript - import type {FriendsListPaginationQuery} from 'FriendsListPaginationQuery.graphql'; import type {FriendsListComponent_user$key} from 'FriendsList_user.graphql'; @@ -2365,7 +2240,6 @@ function FriendsListComponent(props: Props) { } module.exports = FriendsListComponent; - ``` - `hasNext` is a boolean which indicates if the connection has more items available. This information can be useful for determining if different UI controls should be rendered. In our specific case, we only render the `Button` if there are more friends available in the connection . @@ -2384,7 +2258,6 @@ So far in the previous pagination sections, we've implicitly been referring to t However, if we want to implement **_"all at once"_** pagination, we need to use a different API, **`useBlockingPaginationFragment`**: ```javascript - import type {FriendsListPaginationQuery} from 'FriendsListPaginationQuery.graphql'; import type {FriendsListComponent_user$key} from 'FriendsList_user.graphql'; @@ -2468,7 +2341,6 @@ function FriendsListComponent(props: Props) { } module.exports = FriendsListComponent; - ``` Let's distill what's going on here: @@ -2490,7 +2362,6 @@ Some examples of this are: Specifically, in GraphQL, connection fields can accept arguments to sort or filter the set of queried results: ```graphql - fragment UserFragment on User { name friends(order_by: DATE_ADDED, search_term: "Alice", first: 10) { @@ -2502,13 +2373,11 @@ fragment UserFragment on User { } } } - ``` In Relay, we can pass those arguments as usual using GraphQL [Variables](#variables). ```javascript - type Props = {| user: FriendsListComponent_user$key, |}; @@ -2540,13 +2409,11 @@ function FriendsListComponent(props: Props) { return (...); } - ``` When paginating, the original values for those filters will be preserved: ```javascript - type Props = {| user: FriendsListComponent_user$key, |}; @@ -2585,7 +2452,6 @@ function FriendsListComponent(props: Props) { ); } - ``` - Note that calling `loadNext` will use the **_original_** **`order_by`** and **`search_term`** values used for the initial query. During pagination, these value won't (_and shouldn't_) change. @@ -2593,7 +2459,6 @@ function FriendsListComponent(props: Props) { If we want to refetch the connection with _different_ variables, we can use the **`refetch`** function provided by `usePaginationFragment`, similarly to how we do so when [Re-rendering Fragments With Different Data](#re-rendering-fragments-with-different-data): ```javascript - /** * FriendsListComponent.react.js */ @@ -2661,7 +2526,6 @@ function FriendsListComponent(props: Props) { ); } - ``` Let's distill what's going on here: @@ -2685,7 +2549,6 @@ In Relay, connection fields that are marked with the `@connection` directive are For example, given the following fragment that declares a `@connection`: ```javascript - const {graphql} = require('react-relay'); const storyFragment = graphql` @@ -2699,13 +2562,11 @@ const storyFragment = graphql` } } `; - ``` We can access the connection record inside an `updater` function using **`ConnectionHandler.getConnection`**: ```javascript - const {ConnectionHandler} = require('react-relay'); function updater(store: RecordSourceSelectorProxy) { @@ -2717,7 +2578,6 @@ function updater(store: RecordSourceSelectorProxy) { // ... } - ``` ### Adding Edges @@ -2727,7 +2587,6 @@ Once we have a connection record, we also need a record for the new edge that we For example, in the following mutation we can query for the newly created edge in the mutation response: ```javascript - const {graphql} = require('react-relay'); const createCommentMutation = graphql` @@ -2744,7 +2603,6 @@ const createCommentMutation = graphql` } } `; - ``` - 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`. @@ -2752,7 +2610,6 @@ const createCommentMutation = graphql` Inside an `updater`, we can access the edge inside the mutation response using Relay store APIs: ```javascript - const {ConnectionHandler} = require('react-relay'); function updater(store: RecordSourceSelectorProxy) { @@ -2777,7 +2634,6 @@ function updater(store: RecordSourceSelectorProxy) { // ... } - ``` - 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. @@ -2786,7 +2642,6 @@ function updater(store: RecordSourceSelectorProxy) { If you need to create a new edge from scratch, you can use **`ConnectionHandler.createEdge`**: ```javascript - const {ConnectionHandler} = require('react-relay'); function updater(store: RecordSourceSelectorProxy) { @@ -2810,13 +2665,11 @@ function updater(store: RecordSourceSelectorProxy) { // ... } - ``` Once we have a new edge record, we can add it to the the connection using **`ConnectionHandler.insertEdgeAfter`** or **`ConnectionHandler.insertEdgeBefore`**: ```javascript - const {ConnectionHandler} = require('react-relay'); function updater(store: RecordSourceSelectorProxy) { @@ -2840,7 +2693,6 @@ function updater(store: RecordSourceSelectorProxy) { newEdge, ); } - ``` - Note that these APIs will _mutate_ the connection in-place. @@ -2850,7 +2702,6 @@ function updater(store: RecordSourceSelectorProxy) { `ConnectionHandler` provides a similar API to remove an edge from a connection, via **`ConnectionHandler.deleteNode`**: ```javascript - const {ConnectionHandler} = require('react-relay'); function updater(store: RecordSourceSelectorProxy) { @@ -2866,7 +2717,6 @@ function updater(store: RecordSourceSelectorProxy) { commentIDToDelete, ); } - ``` - 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. @@ -2885,7 +2735,6 @@ In our previous examples, our connections didn't take any arguments as filters. For example, let's say the `comments` field took the following arguments, which we pass in as GraphQL [Variables](#variables): ```javascript - const {graphql} = require('react-relay'); const storyFragment = graphql` @@ -2905,7 +2754,6 @@ const storyFragment = graphql` } } `; - ``` 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. @@ -2913,7 +2761,6 @@ In the example above, this means that whatever values we used for `$orderBy`, `$ In order to do so, we need to pass a third argument to **`ConnectionHandler.getConnection`**, with concrete filter values to identify the connection: ```javascript - const {ConnectionHandler} = require('react-relay'); function updater(store: RecordSourceSelectorProxy) { @@ -2935,7 +2782,6 @@ function updater(store: RecordSourceSelectorProxy) { {order_by: null, filter_mode: 'FRIENDS_ONLY', langugage: null} ); } - ``` This implies that by default, **_each combination of values used for filters will produce a different record for the connection._** @@ -2943,7 +2789,6 @@ This implies that by default, **_each combination of values used for filters wil 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: ```javascript - const {ConnectionHandler} = require('react-relay'); function updater(store: RecordSourceSelectorProxy) { @@ -2982,7 +2827,6 @@ function updater(store: RecordSourceSelectorProxy) { ); } } - ``` _**Managing connections with many filters:**_ @@ -2994,7 +2838,6 @@ As you can see, just adding a few filters to a connection can make the complexit 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: ```javascript - const {graphql} = require('react-relay'); const storyFragment = graphql` @@ -3018,7 +2861,6 @@ const storyFragment = graphql` } } `; - ``` - 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. @@ -3040,7 +2882,6 @@ In this section we're going to cover how to implement more advanced pagination u If you need to paginate over multiple connections within the same component, you can use `usePaginationFragment` multiple times: ```javascript - import type {CombinedFriendsListComponent_user$key} from 'CombinedFriendsListComponent_user.graphql'; import type {CombinedFriendsListComponent_viewer$key} from 'CombinedFriendsListComponent_viewer.graphql'; @@ -3101,7 +2942,6 @@ function CombinedFriendsListComponent(props: Props) { return (...); } - ``` However, we recommend trying to keep a single connection per component, to keep the components easier to follow. @@ -3113,7 +2953,6 @@ In the [Pagination](#pagination) section we covered how to use `usePaginationFra Regardless of the semantic meaning of the direction, Relay also provides the same APIs to paginate in the opposite direction using **`usePaginationFragment`**, as long as the **`before`** and **`last`** connection arguments are also used along with `after` and `first`: ```javascript - import type {FriendsListComponent_user$key} from 'FriendsListComponent_user.graphql'; const React = require('React'); @@ -3275,7 +3114,6 @@ In GraphQL, data in the server is updated using [GraphQL Mutations](https://grap A GraphQL mutation looks very similar to a query, with the exception that it uses the **`mutation`** keyword: ```graphql - mutation LikePostMutation($input: LikePostData!) { like_post(data: $input) { post { @@ -3285,7 +3123,6 @@ mutation LikePostMutation($input: LikePostData!) { } } } - ``` - The mutation above modifies the server data to "like" the specified `Post` object. The **`like_post`** field is the mutation field itself, which takes specific input and will be processed by the server to update the relevant data in the backend. @@ -3304,13 +3141,11 @@ An example of a successful response for the above mutation could look like this: } } } - ``` In Relay, we can declare GraphQL mutations using the `graphql` tag too: ```javascript - const {graphql} = require('react-relay'); const likeMutation = graphql` @@ -3324,7 +3159,6 @@ const likeMutation = graphql` } } `; - ``` - Note that mutations can also reference GraphQL [Variables](#variables) in the same way queries or fragments do. @@ -3332,7 +3166,6 @@ const likeMutation = graphql` In order to _execute_ a mutation against the server in Relay, we can use the **`useMutation`** hook. ```javascript - import type {LikePostData, LikePostMutation} from 'LikePostMutation.graphql'; const {graphql, useMutation} = require('react-relay/hooks'); @@ -3367,7 +3200,6 @@ function LikeButton(props: Props) { } module.exports = LikeButton; - ``` Let's distill what's happening here: @@ -3378,7 +3210,6 @@ Let's distill what's happening here: - `commit` is a function that accepts a `UseMutationConfig`. The type of `UseMutationConfig` is as follows: ```javascript - type UseMutationConfig = {| configs?: Array, onError?: ?(error: Error) => void, @@ -3400,7 +3231,6 @@ type UseMutationConfig = {| uploadables?: UploadableMap, variables: $ElementType, |}; - ``` - The only required property in the `UseMutationConfig` object is `variables`, which is an object containing the parameters to the mutation. @@ -3416,7 +3246,6 @@ type UseMutationConfig = {| However, if the updates you wish to perform on the local data in response to the mutation are more complex than just updating the values of fields, like deleting or creating new records, or [Adding and Removing Items From a Connection](#adding-and-removing-items-from-a-connection), you can provide an **`updater`** function to `commit` for full control over how to update the store: ```javascript - import type {LikePostData, LikePostMutation} from 'LikePostMutation.graphql'; const {graphql, useMutation} = require('react-relay/hooks'); @@ -3479,7 +3308,6 @@ function LikeButton(props: Props) { } module.exports = LikeButton; - ``` Let's distill this example: @@ -3504,7 +3332,6 @@ When you can predict what the server response for a mutation is going to be, the ```javascript - ``` Let's see what's happening in this example. @@ -3522,7 +3349,6 @@ However, in some cases we can't statically predict what the server response will ```javascript - ``` Let's see what's happening here: @@ -3559,7 +3385,6 @@ This means that in more complicated scenarios you can still provide all 3 option ```javascript - ``` Let's distill this example, according to the execution order of the updaters: @@ -3594,7 +3419,6 @@ A GraphQL Subscription looks very similar to a query, with the exception that it ```graphql - ``` - Subscribing to the above subscription will notify the client whenever the specified `` object has been "liked" or "unliked". The **``** field is the subscription field itself, which takes specific input and will set up the subscription in the backend. @@ -3605,7 +3429,6 @@ An example of a subscription payload received by the client could look like this ```javascript - ``` In Relay, we can declare GraphQL subcriptions using the `` tag too: @@ -3613,7 +3436,6 @@ In Relay, we can declare GraphQL subcriptions using the `` tag too: ```javascript - ``` - Note that subscriptions can also reference GraphQL [Variables](#variables) in the same way queries or fragments do. @@ -3623,7 +3445,6 @@ In order to _execute_ a subscription against the server in Relay, we can use the ```javascript - ``` Let's distill what's happening here: @@ -3640,7 +3461,6 @@ However, if the updates you wish to perform on the local data in response to the ```javascript - ``` Let's distill this example: @@ -3663,7 +3483,6 @@ To make updates using an `` function, you can use the **``** API: ```javascript - ``` - `` update simply takes an environment and an updater function. @@ -3678,7 +3497,6 @@ To make updates using an `` function, you can use the **``** API: ```javascript - ``` - An `` can be created by using ``; it takes the query and the query variables. @@ -3702,7 +3520,6 @@ In order to extend an existing type, add a `` file to the appropriate schema ext ```graphql - ``` - In this example, we're using the **``** keyword to extend an existing type, and we're adding a new field, `` to the existing `` type, which we will be able to [read](#reading-client-only-data) in our components, and [update](#updating-client-only-data) when necessary using normal Relay APIs; you might imagine that we might use this field to render a different visual treatment for a comment if it's new, and we might set it when creating a new comment. @@ -3715,7 +3532,6 @@ You can define types using the same regular GraphQL syntax, by defining it insid ```graphql - ``` - In this contrived example, we're defining 2 new client-only types, and `` and a regular ``. Note that they can reference themselves as normal, and reference regular server defined types. Also note that we can extend server types and add fields that are of our client-only types. @@ -3728,7 +3544,6 @@ We can read client-only data by selecting it inside [fragments](#fragments) or [ ```javascript - ``` #### Updating Client-Only Data @@ -3758,7 +3573,6 @@ If you want to fetch a query outside of React, you can use the **``** function, ```javascript - ``` - `` will automatically save the fetched data to the in-memory Relay store, and notify any components subscribed to the relevant data. @@ -3771,7 +3585,6 @@ If desired, you can convert the request into a Promise using **``**: ```javascript - ``` - The returned Promise that resolves to the query data, read out from the store when the first network response is received from the server. If the request fails, the promise will reject @@ -3814,7 +3627,6 @@ In order to manually retain a query so that the data it references isn't garbage ```javascript - ``` - **NOTE:** Relay automatically manages the query data retention based on any mounted query components that are rendering the data, so\* you usually should **_not_** need to call `` directly within product code. For any advanced or special use cases, query data retention should usually be handled within infra-level code, such as a Router. diff --git a/website/versioned_docs/version-experimental/RelayHooks-ApiReference.md b/website/versioned_docs/version-experimental/RelayHooks-ApiReference.md index bcf38dbae453f..9b382301854cd 100644 --- a/website/versioned_docs/version-experimental/RelayHooks-ApiReference.md +++ b/website/versioned_docs/version-experimental/RelayHooks-ApiReference.md @@ -31,7 +31,6 @@ For a full example using Relay Hooks and our integration with [Suspense for Data This component is used to set a Relay environment in React Context. Usually, a _single_ instance of this component should be rendered at the very root of the application, in order to set the Relay environment for the whole application: ```javascript - const React = require('React'); const {RelayEnvironmentProvider} = require('react-relay/hooks'); @@ -45,7 +44,6 @@ function Root() { } module.exports = Root; - ``` #### Props @@ -61,7 +59,6 @@ module.exports = Root; Hook used to access a Relay environment that was set by a [`RelayEnvironmentProvider`](#relayenvironmentprovider): ```javascript - const React = require('React'); const {useRelayEnvironment} = require('react-relay/hooks'); @@ -79,7 +76,6 @@ function MyComponent() { } module.exports = Root; - ``` ### `useQueryLoader` @@ -89,7 +85,6 @@ Hook used to make it easy to safely load queries, while avoiding data leaking in This hook is designed to be used with [`usePreloadedQuery`](#usepreloadedquery) to implement the [“render-as-you-fetch”](https://reactjs.org/docs/concurrent-mode-suspense.html#approach-3-render-as-you-fetch-using-suspense) pattern. ```javascript - const React = require('React'); const {useQueryLoader, usePreloadedQuery} = require('react-relay/hooks'); @@ -134,7 +129,6 @@ function NameDisplay({ queryReference }) { return

{data.user?.name}

; } - ``` #### Arguments @@ -179,7 +173,6 @@ Hook used to access data fetched by an earlier call to [`loadQuery()`](#loadquer - This pattern is encouraged over `useLazyLoadQuery()` as it can allow fetching data earlier while not blocking rendering. ```javascript - const React = require('React'); const {useQueryLoader, usePreloadedQuery} = require('react-relay/hooks'); @@ -224,7 +217,6 @@ function NameDisplay({ queryReference }) { return

{data.user?.name}

; } - ``` #### Arguments @@ -253,7 +245,6 @@ function NameDisplay({ queryReference }) { Hook used to fetch a GraphQL query _during_ render. This hook can trigger multiple round trips, thereby degrading performance. Instead, prefer [`useQueryLoader()`](#usequeryloader) and [`usePreloadedQuery()`](#usepreloadedquery) instead. ```javascript - import type {AppQuery} from 'AppQuery.graphql'; const React = require('React'); @@ -275,7 +266,6 @@ function App() { return

{data.user?.name}

; } - ``` #### Arguments @@ -320,7 +310,6 @@ function App() { ### `useFragment` ```javascript - import type {UserComponent_user$key} from 'UserComponent_user.graphql'; const React = require('React'); @@ -353,7 +342,6 @@ function UserComponent(props: Props) { ); } - ``` #### Arguments @@ -378,7 +366,6 @@ function UserComponent(props: Props) { You can use `useRefetchableFragment` when you want to fetch and re-render a fragment with different data: ```javascript - import type {CommentBodyRefetchQuery} from 'CommentBodyRefetchQuery.graphql'; import type {CommentBody_comment$key} from 'CommentBody_comment.graphql'; @@ -423,7 +410,6 @@ function CommentBody(props: Props) { } module.exports = CommentBody; - ``` #### Arguments @@ -478,7 +464,6 @@ Tuple containing the following values You can use `usePaginationFragment` to render a fragment that uses a `@connection` and paginate over it: ```javascript - import type {FriendsListPaginationQuery} from 'FriendsListPaginationQuery.graphql'; import type {FriendsList_user$key} from 'FriendsList_user.graphql'; @@ -538,7 +523,6 @@ function FriendsList(props: Props) { } module.exports = FriendsList; - ``` #### Arguments @@ -636,7 +620,6 @@ In the meantime, see our **[Blocking ("all-at-once") Pagination Guide](a-guided- You can use `useMutation` to execute a mutation in a React component. ```javascript - import type {FeedbackLikeMutation} from 'FeedbackLikeMutation.graphql'; const React = require('React'); @@ -675,7 +658,6 @@ function LikeButton() { /> ); } - ``` #### Arguments @@ -711,7 +693,6 @@ Tuple containing the following values: Hook used to subscribe and unsubscribe to a subscription. ```javascript - import {graphql, useSubscription} from 'RelayHooks'; import {useMemo} from 'react'; @@ -725,7 +706,6 @@ function MyFunctionalComponent({ id }) {
Move Fast
); } - ``` This is a thin wrapper around the `requestSubscription` API. Its behavior: @@ -748,7 +728,6 @@ This function is designed to be used with the [`usePreloadedQuery()`](#usepreloa Query references returned from `loadQuery` will leak data into the Relay store if `.dispose()` is not called on them once they are no longer referenced. _As such, prefer calling [`useQueryLoader`](#usequeryloader) when possible_, which ensures that query references are disposed for you. ```javascript - const React = require('React'); const {loadQuery, useRelayEnvironment} = require('react-relay/hooks'); @@ -776,7 +755,6 @@ function MyComponent() { return
Click me
; } - ``` #### Arguments @@ -816,7 +794,6 @@ The exact format of the return value is unstable and highly likely to change. We This function is designed to be used with the `usePreloadedQuery()` hook to implement the "render-as-you-fetch" pattern in conjunction with `usePreloadedQuery`. See the [`usePreloadedQuery()`](#usepreloadedquery) docs for a more complete example. ```javascript - const {graphql, preloadQuery_DEPRECATED} = require('react-relay/hooks'); const AppEnvironment = require('./AppEnvironment'); // user-defined @@ -866,7 +843,6 @@ The exact format of the return value is _unstable and highly likely to change_. If you want to fetch a query outside of React, you can use the **`fetchQuery`** function from `react-relay/hooks`: ```javascript - import type {AppQuery} from 'AppQuery.graphql'; const {fetchQuery} = require('react-relay/hooks'); @@ -888,7 +864,6 @@ fetchQuery( error: (error) => {...}, next: (data) => {...} }); - ``` #### Arguments diff --git a/website/versioned_docs/version-experimental/RelayHooks-StepByStep.md b/website/versioned_docs/version-experimental/RelayHooks-StepByStep.md index ae5c7e08913b4..01f2479fb6a53 100644 --- a/website/versioned_docs/version-experimental/RelayHooks-StepByStep.md +++ b/website/versioned_docs/version-experimental/RelayHooks-StepByStep.md @@ -60,7 +60,6 @@ REACT_APP_GITHUB_AUTH_TOKEN= Next let's update the home screen of our app to show the name of the Relay repository. We'll start with a common approach to fetching data in React, calling our fetch function after the component mounts (note: later we'll see some limitations of this approach and a better alternative that works with React Concurrent Mode and Suspense). First we'll create a helper function to load data from the server. Again, this example will use the GitHub API, but feel free to replace it with the appropriate URL and authentication mechanism for your own GraphQL server: ```javascript - // your-app-name/src/fetchGraphQL.js async function fetchGraphQL(text, variables) { const REACT_APP_GITHUB_AUTH_TOKEN = process.env.REACT_APP_GITHUB_AUTH_TOKEN; @@ -83,7 +82,6 @@ async function fetchGraphQL(text, variables) { } export default fetchGraphQL; - ``` ### 2.3: Fetching GraphQL From React @@ -91,7 +89,6 @@ export default fetchGraphQL; Now we can use our `fetchGraphQL` function to fetch some data in our app. Open `src/App.js` and edit it as follows: ```javascript - // your-app-name/src/App.js import React from 'react'; import './App.css'; @@ -142,7 +139,6 @@ function App() { } export default App; - ``` ## Step 3: When To Use Relay @@ -200,7 +196,6 @@ Now that we have a schema we can modify `package.json` to run the compiler first }, ... } - ``` At this point, you should be able to run the following successfully: @@ -219,7 +214,6 @@ If it works, your app will open at [localhost:3000](http://localhost:3000). Now Now that the compiler is configured we can set up the runtime - we have to tell Relay how to connect to our GraphQL server. We'll reuse the `fetchGraphQL` utility we built above. Assuming you haven't modified it (or at least that it still takes `text` and `variables` as arguments), we can now define a Relay `Environment`. An `Environment` encapsulates how to talk to our server (a Relay `Network`) with a cache of data retrieved from that server. We'll create a new file, `src/RelayEnvironment.js` and add the following: ```javascript - // your-app-name/src/RelayEnvironment.js import { Environment, Network, RecordSource, Store } from 'relay-runtime'; import fetchGraphQL from './fetchGraphQL'; @@ -236,7 +230,6 @@ export default new Environment({ network: Network.create(fetchRelay), store: new Store(new RecordSource()), }); - ``` ## Step 5: Fetching a Query With Relay @@ -244,7 +237,6 @@ export default new Environment({ Now that Relay is installed and configured we can change `App.js` to use it instead. We'll prepare our data as the app starts, and wait for it to be ready in ``. Replace the contents of `src/App.js` with the following: ```javascript - import React from 'react'; import './App.css'; import fetchGraphQL from './fetchGraphQL'; @@ -309,7 +301,6 @@ function AppRoot(props) { } export default AppRoot; - ``` Note that you'll have to restart the app - `yarn start` - so that Relay compiler can see the new query and generate code for it. See the [Relay Compiler setup docs](./installation-and-setup#set-up-relay-compiler) for how to run Relay Compiler in watch mode, to regenerate code as you modify queries. diff --git a/website/versioned_docs/version-v1.4.1/GraphQL-ServerSpecification.md b/website/versioned_docs/version-v1.4.1/GraphQL-ServerSpecification.md index c862a24c0c764..9172de516465e 100644 --- a/website/versioned_docs/version-v1.4.1/GraphQL-ServerSpecification.md +++ b/website/versioned_docs/version-v1.4.1/GraphQL-ServerSpecification.md @@ -92,7 +92,6 @@ type IntroduceShipPayload { type Mutation { introduceShip(input: IntroduceShipInput!): IntroduceShipPayload } - ``` ## Object Identification @@ -111,7 +110,6 @@ query RebelsQuery { name } } - ``` returns @@ -124,7 +122,6 @@ returns "name": "Alliance to Restore the Republic" } } - ``` So now we know the ID of the Rebels in our system. We can now refetch them: @@ -139,7 +136,6 @@ query RebelsRefetchQuery { } } } - ``` returns @@ -152,7 +148,6 @@ returns "name": "Alliance to Restore the Republic" } } - ``` If we do the same thing with the Empire, we'll find that it returns a different ID, and we can refetch it as well: @@ -165,7 +160,6 @@ query EmpireQuery { name } } - ``` yields @@ -178,7 +172,6 @@ yields "name": "Galactic Empire" } } - ``` and @@ -193,7 +186,6 @@ query EmpireRefetchQuery { } } } - ``` yields @@ -206,7 +198,6 @@ yields "name": "Galactic Empire" } } - ``` The `Node` interface and `node` field assume globally unique IDs for this refetching. A system without globally unique IDs can usually synthesize them by combining the type with the type-specific ID, which is what was done in this example. @@ -235,7 +226,6 @@ query RebelsShipsQuery { } } } - ``` yields @@ -256,7 +246,6 @@ yields } } } - ``` That used the `first` argument to `ships` to slice the result set down to the first one. But what if we wanted to paginate through it? On each edge, a cursor will be exposed that we can use to paginate. Let's ask for the first two this time, and get the cursor as well: @@ -276,7 +265,6 @@ query MoreRebelShipsQuery { } } } - ``` and we get back @@ -304,7 +292,6 @@ and we get back } } } - ``` Notice that the cursor is a base64 string. That's the pattern from earlier: the server is reminding us that this is an opaque string. We can pass this string back to the server as the `after` argument to the `ships` field, which will let us ask for the next three ships after the last one in the previous result: @@ -324,7 +311,6 @@ query EndOfRebelShipsQuery { } } } - ``` gives us @@ -359,7 +345,6 @@ gives us } } } - ``` Sweet! Let's keep going and get the next four! @@ -379,7 +364,6 @@ query RebelsQuery { } } } - ``` yields @@ -394,7 +378,6 @@ yields } } } - ``` Hm. There were no more ships; guess there were only five in the system for the rebels. It would have been nice to know that we'd reached the end of the connection, without having to do another round trip in order to verify that. The connection model exposes this capability with a type called `PageInfo`. So let's issue the two queries that got us ships again, but this time ask for `hasNextPage`: @@ -426,7 +409,6 @@ query EndOfRebelShipsQuery { } } } - ``` and we get back @@ -477,7 +459,6 @@ and we get back } } } - ``` So on the first query for ships, GraphQL told us there was a next page, but on the next one, it told us we'd reached the end of the connection. @@ -507,7 +488,6 @@ type IntroduceShipPayload { ship: Ship clientMutationId: String! } - ``` With this input and payload, we can issue the following mutation: @@ -526,7 +506,6 @@ mutation AddBWingQuery($input: IntroduceShipInput!) { clientMutationId } } - ``` with these params: @@ -540,7 +519,6 @@ with these params: "clientMutationId": "abcde" } } - ``` and we'll get this result: @@ -559,7 +537,6 @@ and we'll get this result: "clientMutationId": "abcde" } } - ``` ## Further Reading diff --git a/website/versioned_docs/version-v1.4.1/Introduction-InstallationAndSetup.md b/website/versioned_docs/version-v1.4.1/Introduction-InstallationAndSetup.md index af0ff616736e9..2585b96c85c73 100644 --- a/website/versioned_docs/version-v1.4.1/Introduction-InstallationAndSetup.md +++ b/website/versioned_docs/version-v1.4.1/Introduction-InstallationAndSetup.md @@ -26,13 +26,11 @@ yarn add --dev babel-plugin-relay graphql Add `"relay"` to the list of plugins your `.babelrc` file: ```javascript - { "plugins": [ "relay" ] } - ``` Please note that the `"relay"` plugin should run before other plugins or @@ -53,12 +51,10 @@ yarn add --dev relay-compiler graphql This installs the bin script `relay-compiler` in your node_modules folder. It's recommended to run this from a `yarn`/`npm` script by adding a script to your `package.json` file: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql" } - ``` Then, after making edits to your application files, just run the `relay` script to generate new compiled artifacts: @@ -93,15 +89,13 @@ polyfill in your bundled application, such as [core-js][] or A polyfilled environment for Relay using [core-js][] to support older browsers might look like: -```js - +```javascript require('core-js/es6/map'); require('core-js/es6/set'); require('core-js/es6/promise'); require('core-js/es6/object'); require('./myRelayApplication'); - ``` [core-js]: https://github.com/zloirock/core-js diff --git a/website/versioned_docs/version-v1.4.1/Introduction-QuickStartGuide.md b/website/versioned_docs/version-v1.4.1/Introduction-QuickStartGuide.md index ccc19448789b6..646fad9f27eab 100644 --- a/website/versioned_docs/version-v1.4.1/Introduction-QuickStartGuide.md +++ b/website/versioned_docs/version-v1.4.1/Introduction-QuickStartGuide.md @@ -24,7 +24,6 @@ Before starting, make sure to check out our [Prerequisites](./prerequisites) and Fortunately, we are going to be using this [example todo list app](https://github.com/relayjs/relay-examples/tree/master/todo), which already has a [server](https://github.com/relayjs/relay-examples/blob/master/todo/server.js) and schema [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql) available for us to use: ```graphql - # From schema.graphql # https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql @@ -37,7 +36,6 @@ type Query { id: ID! ): Node } - ``` Additionally, we will be using [Flow](https://flow.org/) inside our JavaScript code examples. Flow is optional to set up in your project, but we will include it in our examples for completeness. @@ -49,7 +47,6 @@ Before we can start rendering pixels on the screen, we need to configure Relay v For the purposes of our example, we are simply going to configure our environment to communicate with our existing GraphQL server: ```javascript - import { Environment, Network, @@ -81,7 +78,6 @@ const environment = new Environment({ }); export default environment; - ``` A Relay Environment requires at least a [Store](./relay-store) and a [Network Layer](./network-layer). The above code uses the default implementation for `Store`, and creates a [Network Layer](./network-layer) using a simple `fetchQuery` function to fetch a GraphQL query from our server. @@ -95,19 +91,16 @@ Now that we've configured our Relay Environment, we can start fetching queries a To start, let's assume we just want to render the user id on the screen. From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L66), we know that we can get the current `User` via the `viewer` field, so let's write a sample query to fetch the current user id: ```graphql - query UserQuery { viewer { id } } - ``` Now, let's see what it would take to create a component that fetches and renders the above query: ```javascript - // App.js import React from 'react'; import {graphql, QueryRenderer} from 'react-relay'; @@ -140,7 +133,6 @@ export default App extends React.Component { ); } } - ``` Our app is rendering a `QueryRenderer` in the above code, like any other React Component, but let's see what's going on in the props that we are passing to it: @@ -159,19 +151,16 @@ For more details on `QueryRenderer`, check out the [docs](./query-renderer). Let's assume for a moment that in our app we want to be able to view data for different users, so we're going to somehow need to query users by id. From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L69), we know we can query nodes given an id, so let's write a parametrized query to get a user by id: ```graphql - query UserQuery($userID: ID!) { node(id: $userID) { id } } - ``` Now, let's see how we would fetch the above query using a `QueryRenderer`: ```javascript - // UserTodoList.js // @flow import React from 'react'; @@ -212,7 +201,6 @@ export default UserTodoList extends React.Component { ); } } - ``` The above code is doing something very similar to our [previous example](#rendering-graphql-queries), however, we are now passing a `$userID` variable to the GraphQL query, via the `variables` prop. This has a couple of important implications: @@ -229,7 +217,6 @@ Now that we know how to define and fetch queries, let's actually start building First, let's start at the bottom; let's say that we want to render a component that given a todo item, simply displays the item's text and completed state: ```javascript - // Todo.js import React from 'react'; @@ -259,7 +246,6 @@ export default class Todo extends React.Component { ); } } - ``` From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L107), we know that we can query this data on the `Todo` type. However, we don't want to have to send a separate query for each todo item; that would defeat the purpose of using GraphQL over a traditional REST API. We could manually query for these fields directly in our `QueryRenderer` query, but that would hurt re-usability: what if we want to query the same set of fields as part of a different query? Additionally, we wouldn't know which component needs the data we're querying, a problem Relay directly tries to address. @@ -267,18 +253,15 @@ From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/dat Instead, we can define a reusable [Fragment](http://graphql.org/learn/queries/#fragments), which allows us to define a set of fields on a type and reuse them within our queries wherever we need to: ```graphql - fragment TodoItemFragment on Todo { complete text } - ``` Our component can then use this fragment to declare its data dependency on the `Todo` GraphQL type: ```javascript - // Todo.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -338,7 +321,6 @@ Before proceeding, don't forget to run the Relay Compiler with `yarn relay`. Given that [Fragment Containers](./fragment-container) are just React components, we can compose them as such, and even re-use fragment containers within other fragment containers. As an example, let's see how we would define a `TodoList` component that just renders a list of todo items, and whether all have been completed or not: ```javascript - // TodoList.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -397,7 +379,6 @@ export default createFragmentContainer( } `, ); - ``` As with the first fragment container we defined, `TodoList` declares it's data dependencies via a fragment. However, this component additionally re-uses the fragment previously defined by the `Todo` component, and passes the appropriate data to when rendering the child `Todo` components (a.k.a. fragment containers). @@ -412,7 +393,6 @@ fragment containers do not directly fetch data. Instead, containers declare a sp A `QueryRenderer` rendering these fragment containers could look like the following: ```javascript - // ViewerTodoList.js import React from 'react'; import PropTypes from 'prop-types'; @@ -454,7 +434,6 @@ export default ViewerTodoList extends React.Component { ); } } - ``` Check out or docs for [Fragment Containers](./fragment-container) for more details, and our guides on [Refetch](./refetch-container) and [Pagination](./pagination-container) for more advanced usage of containers. @@ -466,7 +445,6 @@ Now that we know how to query for and render data, let's move on to changing our From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L35), we know that we have some mutations available to us, so let's start by writing a mutation to change the `complete` status of a given todo item (i.e. mark or unmark it as done): ```graphql - mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { changeTodoStatus(input: $input) { todo { @@ -475,7 +453,6 @@ mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { } } } - ``` This mutation allows us to query back some data as a [result of the mutation](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L18), so we're going to query for the updated `complete` status on the todo item. @@ -483,7 +460,6 @@ This mutation allows us to query back some data as a [result of the mutation](ht In order to execute this mutation in Relay, we're going to write a new mutation using Relay's `commitMutation` api: ```javascript - // ChangeTodoStatusMutation.js import {graphql, commitMutation} from 'react-relay'; @@ -517,7 +493,6 @@ function commit( } export default {commit}; - ``` Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mutation to the server, and in our case, upon receiving a response it will automatically update the local data store with the latest data from the server. This also means that upon receiving the response, Relay will ensure that any components (i.e. containers) that depend on the updated data are re-rendered. @@ -525,7 +500,6 @@ Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mut In order to actually use this mutation in our component, we could update our `Todo` component in the following way: ```javascript - // Todo.js // ... @@ -559,7 +533,6 @@ In order to make the experience better, we can configure our mutation to do an o In Relay, there's a couple of options we can pass to `commitMutation` to enable optimistic updates. Let's see what that would look like in our `ChangeTodoStatusMutation`: ```javascript - // ChangeTodoStatusMutation.js // ... @@ -594,7 +567,6 @@ function commit( } export default {commit}; - ``` In the simplest case above, we just need to pass an `optimisticResponse` option, which should refer to an object having the same shape as the mutation response payload. When we pass this option, Relay will know to immediately update our local data with the optimistic response, and then update it with the actual server response, or roll it back if an error occurs. diff --git a/website/versioned_docs/version-v1.4.1/Modern-ConvertingMutations.md b/website/versioned_docs/version-v1.4.1/Modern-ConvertingMutations.md index 288ac18ab0872..96410a4589cef 100644 --- a/website/versioned_docs/version-v1.4.1/Modern-ConvertingMutations.md +++ b/website/versioned_docs/version-v1.4.1/Modern-ConvertingMutations.md @@ -12,19 +12,16 @@ FatQueries in Relay Classic mutations was a concept that was confusing for a num Example of existing fat query: ```javascript - RelayClassic.QL` fragment on MarkReadNotificationResponsePayload @relay(pattern: true) { notification } `; - ``` Example of converted mutation query: ```javascript - graphql` mutation MarkReadNotificationMutation( $input: MarkReadNotificationData! @@ -37,7 +34,6 @@ graphql` } } `; - ``` ## Migrating Configs @@ -63,7 +59,6 @@ This is no longer needed in Compatibility Mode for neither environments. Relay w Take this example of a simple mutation in Relay Classic: ```javascript - class LikeStoryMutation extends RelayClassic.Mutation { getMutation() { return RelayClassic.QL`mutation {likeStory}`; @@ -102,7 +97,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { `, }; } - ``` ### Converting `getMutation()` and `getFatQuery()` @@ -110,7 +104,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { We combine these two into a regular GraphQL mutation, which list out specific fields that needs to be updated. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story(data: $input) { @@ -122,7 +115,6 @@ const mutation = graphql` } } `; - ``` ### Converting `getConfigs()` @@ -134,13 +126,11 @@ As specified above, `FIELDS_CHANGE` configs can be omitted. To convert `getVariables()`, we take the return value from the original function and wrap it in an object that contains a property that matches the variable name for the mutation. In this case, the mutation has a `input` variable that is of type `LikeStoryData`. ```javascript - const variables = { input: { storyID: args.storyID } } - ``` ### Final Result @@ -148,7 +138,6 @@ const variables = { As you can see, our resulting mutation is a lot simpler and more like regular GraphQL than the Relay Classic version we started out with. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story { @@ -174,7 +163,6 @@ function commit(environment: CompatEnvironment, args) { variables, }); } - ``` See [Mutation](./mutations) for additional options on `commitMutation` for more complex mutations. diff --git a/website/versioned_docs/version-v1.4.1/Modern-FragmentContainer.md b/website/versioned_docs/version-v1.4.1/Modern-FragmentContainer.md index e86b79995c1c7..7bbd0a9f22899 100644 --- a/website/versioned_docs/version-v1.4.1/Modern-FragmentContainer.md +++ b/website/versioned_docs/version-v1.4.1/Modern-FragmentContainer.md @@ -17,12 +17,10 @@ Table of Contents: `createFragmentContainer` has the following signature: ```javascript - createFragmentContainer( component: ReactComponentClass, fragmentSpec: GraphQLTaggedNode | {[string]: GraphQLTaggedNode}, ): ReactComponentClass; - ``` ### Arguments @@ -46,7 +44,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -61,7 +58,6 @@ To start, let's build the plain React version of a hypothetical `` c Here's a basic implementation of `` that ignores styling in order to highlight the functionality: ```javascript - // TodoItem.js class TodoItem extends React.Component { render() { @@ -81,7 +77,6 @@ class TodoItem extends React.Component { ); } } - ``` ### Data Dependencies With GraphQL @@ -89,7 +84,6 @@ class TodoItem extends React.Component { In Relay, data dependencies are described using [GraphQL](https://github.com/facebook/graphql). For ``, the dependency can be expressed as follows. Note that this exactly matches the shape that the component expected for the `item` prop. ```javascript - graphql` # This fragment only applies to objects of type 'Todo'. fragment TodoItem_item on Todo { @@ -105,7 +99,6 @@ graphql` Given the plain React component and a GraphQL fragment, we can now define a Fragment Container to specify this component's data requirements. Let's look at the code first and then see what's happening: ```javascript - // TodoItem.js import {createFragmentContainer, graphql} from 'react-relay'; @@ -123,13 +116,11 @@ export default createFragmentContainer(TodoItem, { } `, }); - ``` Relay will infer the prop name from the fragment name according to the fragment naming convention `<...>_`. The example below is equivalent to the one above: ```javascript - export default createFragmentContainer( TodoItem, graphql` @@ -139,13 +130,11 @@ export default createFragmentContainer( } `, ); - ``` If there is no `_` suffix, the `data` prop name will be used: ```javascript - class TodoItem extends React.Component { render() { const item = this.props.data; @@ -162,7 +151,6 @@ export default createFragmentContainer( } `, ); - ``` ## Container Composition @@ -176,7 +164,6 @@ Let's explore how this works via a `` component that composes the `< View composition is _exactly_ what you're used to — Relay containers are just standard React components. Here's the `` component: ```javascript - class TodoList extends React.Component { render() { // Expects a `list` with a string `title`, as well as the information @@ -191,7 +178,6 @@ class TodoList extends React.Component { ); } } - ``` ### Composing Fragments @@ -199,7 +185,6 @@ class TodoList extends React.Component { Fragment composition works similarly — a parent container's fragment composes the fragment for each of its children. In this case, `` needs to fetch information about the `Todo`s that are required by ``. ```javascript - class TodoList extends React.Component // as above export default createFragmentContainer( @@ -217,7 +202,6 @@ export default createFragmentContainer( } `, ); - ``` Note that when composing fragments, the type of the composed fragment must match the field on the parent in which it is embedded. For example, it wouldn't make sense to embed a fragment of type `Story` into a parent's field of type `User`. Relay and GraphQL will provide helpful error messages if you get this wrong (and if they aren't helpful, let us know!). @@ -231,7 +215,6 @@ When defining a fragment, you can use the [`@argumentDefinitions`](./graphql-in- For example, let's redefine our `TodoList_list` fragment to take some arguments using `@argumentDefinitions`: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -241,7 +224,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` Any arguments defined inside `@argumentDefinitions` will be local variables available inside the fragment's scope. However, a fragment can also reference global variables that were defined in the root query. @@ -253,11 +235,9 @@ In order to pass arguments to a fragment that has `@argumentDefinitions`, you ne Following our `TodoList_list` example, we would pass arguments to the fragment like so: ```graphql - query TodoListQuery($count: Int, $userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` ### Calling Component Instance Methods @@ -268,7 +248,6 @@ Since Relay composes these component instances in a container, you need to use t Consider an input with a server-defined placeholder text and an imperative method to focus the input node: ```javascript - export default createFragmentContainer( class TodoInput extends React.Component { focus() { @@ -288,13 +267,11 @@ export default createFragmentContainer( } `, ); - ``` To call this method on the underlying component, first provide a `componentRef` function to the Relay container. This differs from providing a [`ref`](https://facebook.github.io/react/docs/refs-and-the-dom.html) function which would provide a reference to the Relay container itself, not the underlying React Component. ```javascript - export default createFragmentContainer( class TodoListView extends React.Component { render() { @@ -312,7 +289,6 @@ export default createFragmentContainer( } `, ); - ``` ## Rendering Containers diff --git a/website/versioned_docs/version-v1.4.1/Modern-GraphQLInRelay.md b/website/versioned_docs/version-v1.4.1/Modern-GraphQLInRelay.md index 45ed05dc9670e..7cb555b6ce502 100644 --- a/website/versioned_docs/version-v1.4.1/Modern-GraphQLInRelay.md +++ b/website/versioned_docs/version-v1.4.1/Modern-GraphQLInRelay.md @@ -14,7 +14,6 @@ Table of Contents: The `graphql` template tag provided by Relay serves as the mechanism to write queries, fragments, mutations or subscriptions in the [GraphQL](http://graphql.org/learn/) language. For example: ```javascript - import {graphql} from 'react-relay'; graphql` @@ -24,7 +23,6 @@ graphql` } } `; - ``` The result of using the `graphql` template tag are `GraphQLTaggedNode`s, which are used to define [Query Renderers](./query-renderer), [Fragment Containers](./fragment-container), [Refetch Containers](./refetch-container), [Pagination Containers](./pagination-container), etc. @@ -42,11 +40,9 @@ Relay uses directives to add additional information to GraphQL documents, which `@arguments` is a directive used to pass arguments to a fragment that was defined using [`@argumentDefinitions`](#argumentdefinitions). For example: ```graphql - query TodoListQuery($userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` See [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -56,7 +52,6 @@ See [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragme `@argumentDefinitions` is a directive used to specify arguments taken by a fragment. For example: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -66,7 +61,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` See [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -82,13 +76,11 @@ When using the [Pagination Container](./pagination-container), Relay expects con When defining a fragment, you can use the `@relay(plural: true)` directive to indicate that the fragment is backed by a [GraphQL list](http://graphql.org/learn/schema/#lists-and-non-null), meaning that it will inform Relay that this particular field is an array. For example: ```javascript - graphql` fragment TodoItems_items on TodoItem @relay(plural: true) { id text }`; - ``` ### `@relay(mask: Boolean)` @@ -104,7 +96,6 @@ Keep in mind that it is typically considered an **anti-pattern** to create a sin In the example below, the `user` prop will include the data for `id` and `name` fields wherever `...Component_internUser` is included, instead of Relay's normal behavior to mask those fields: ```javascript - graphql` fragment Component_internUser on InternUser { id @@ -132,7 +123,6 @@ export default createFragmentContainer( } `, ); - ``` ## Relay Compiler @@ -142,7 +132,6 @@ Relay uses the Relay Compiler to convert [`graphql`](#graphql) literals into gen A query like the following: ```javascript - graphql` fragment MyComponent on Type { field @@ -166,7 +155,6 @@ See our relay-compiler section in our [Installation and Setup guide](./installat To use the Relay Compiler, you need either a .graphql or .json GraphQL schema file, describing your GraphQL server's API. Typically these files are local representations of a server source of truth and are not edited directly. For example, we might have a `schema.graphql` like: ```graphql - schema { query: Root } @@ -184,7 +172,6 @@ type WordDefinition { text: String image: String } - ``` ### Source files @@ -200,7 +187,6 @@ For example, given the two files: - `src/Components/DictionaryComponent.js` ```javascript - const DictionaryWordFragment = graphql` fragment DictionaryComponent_word on Word { id @@ -222,7 +208,6 @@ For example, given the two files: - `src/Queries/DictionaryQuery.js` ```javascript - const DictionaryQuery = graphql` query DictionaryQuery { dictionary { @@ -246,9 +231,7 @@ Typically you will not need to import your generated definitions. The [Relay Bab However the Relay Compiler also automatically generates [Flow](https://flow.org) types as [type comments](https://flow.org/en/docs/types/comments/). For example, you can import the generated flow types like so: ```javascript - import type {DictionaryComponent_word} from './__generated__/DictionaryComponent_word.graphql'; - ``` ### Advanced usage diff --git a/website/versioned_docs/version-v1.4.1/Modern-LocalStateManagement.md b/website/versioned_docs/version-v1.4.1/Modern-LocalStateManagement.md index f3427f392a611..dc50079ca5fbe 100644 --- a/website/versioned_docs/version-v1.4.1/Modern-LocalStateManagement.md +++ b/website/versioned_docs/version-v1.4.1/Modern-LocalStateManagement.md @@ -23,23 +23,19 @@ It can even be used to extend an existing server schema. For example, we can create a new type called `Note`: ```graphql - type Note { id: ID! title: String body: String } - ``` And then extend the server schema type `User`, with a list of `Note`, called `notes`. ```graphql - extend type User { notes: [Note] } - ``` ## Querying local state @@ -50,7 +46,6 @@ The field can be from the server schema, or it can be schema agnostic, like an i Here, we use a [QueryRenderer](./query-renderer) to get the current `User` via the `viewer` field, along with their id, name and the local list of notes. ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -96,7 +91,6 @@ const Example = (props) => { /> ); } - ``` ## Mutating local state @@ -110,7 +104,6 @@ To build upon the previous example, let's try creating, updating and deleting a ### Create ```javascript - import {commitLocalUpdate} from 'react-relay'; let tempID = 0; @@ -130,7 +123,6 @@ function createUserNote() { user.setLinkedRecords([...userNoteRecords, newNoteRecord], 'notes'); }); } - ``` Note that since this record will be rendered by the `ExampleQuery` in our `QueryRenderer`, the QueryRenderer will automatically retain this data so it isn't garbage collected. @@ -138,7 +130,6 @@ Note that since this record will be rendered by the `ExampleQuery` in our `Query If no component is rendering the local data and you want to manually retain it, you can do so by calling `environment.retain()`: ```javascript - import {createOperationDescriptor, getRequest} from 'relay-runtime'; // Create a query that references that record @@ -165,13 +156,11 @@ const disposable = environment.retain(operation); // Whenever you don't need that data anymore and it's okay for Relay to garbage collect it, // you can dispose of the retain disposable.dispose(); - ``` ### Update ```javascript - import {commitLocalUpdate} from 'react-relay'; function updateUserNote(dataID, body, title) { @@ -182,13 +171,11 @@ function updateUserNote(dataID, body, title) { note.setValue(title, 'title') }); } - ``` ### Delete ```javascript - import {commitLocalUpdate} from 'react-relay'; function deleteUserNote(dataID) { @@ -206,7 +193,6 @@ function deleteUserNote(dataID) { user.setLinkedRecords(newUserNoteRecords, 'notes'); }); } - ``` ## Initial local state @@ -215,7 +201,6 @@ All new client-side schema fields default to `undefined` value. Often however, y You can use an updater function via `commitLocalUpdate` to prime local state. ```javascript - import {commitLocalUpdate} from 'react-relay'; commitLocalUpdate(environment, store => { @@ -224,5 +209,4 @@ commitLocalUpdate(environment, store => { // initialize user notes to an empty array. user.setLinkedRecords([], 'notes'); }); - ``` diff --git a/website/versioned_docs/version-v1.4.1/Modern-MigrationSetup.md b/website/versioned_docs/version-v1.4.1/Modern-MigrationSetup.md index 66f1145357e25..a89c0e178e0e5 100644 --- a/website/versioned_docs/version-v1.4.1/Modern-MigrationSetup.md +++ b/website/versioned_docs/version-v1.4.1/Modern-MigrationSetup.md @@ -13,13 +13,11 @@ With some additional configuration, the `"relay"` babel plugin can also translat Relay Classic `Relay.QL` literals. Most importantly, include a reference to your GraphQL Schema as either a json file or graphql schema file. ```javascript - { "plugins": [ ["relay", {"schema": "path/schema.graphql"}] ] } - ``` ## Set up babel-plugin-relay for "[compatibility mode](./relay-compat)" @@ -29,13 +27,11 @@ literals can be translated to be usable by _both_ runtimes if configured to use compatibility mode: ```javascript - { "plugins": [ ["relay", {"compat": true, "schema": "path/schema.graphql"}] ] } - ``` ## Additional Options @@ -47,7 +43,6 @@ thrown at runtime. When compiling code for production deployment, the plugin can be configured to immediately throw upon encountering a validation problem. The plugin can be further customized for different environments with the following options: ```javascript - { "plugins": [ ["relay", { @@ -56,5 +51,4 @@ When compiling code for production deployment, the plugin can be configured to i }] ] } - ``` diff --git a/website/versioned_docs/version-v1.4.1/Modern-Mutations.md b/website/versioned_docs/version-v1.4.1/Modern-Mutations.md index d879216bdd5e3..ebb1797237203 100644 --- a/website/versioned_docs/version-v1.4.1/Modern-Mutations.md +++ b/website/versioned_docs/version-v1.4.1/Modern-Mutations.md @@ -16,7 +16,6 @@ Table of Contents: Use `commitMutation` to create and execute mutations. `commitMutation` has the following signature: ```javascript - commitMutation( environment: Environment, config: { @@ -30,7 +29,6 @@ commitMutation( configs?: Array, }, ); - ``` ### Arguments @@ -57,7 +55,6 @@ commitMutation( Example of a simple mutation: ```javascript - import {commitMutation, graphql} from 'react-relay'; const mutation = graphql` @@ -92,7 +89,6 @@ function markNotificationAsRead(environment, source, storyID) { }, ); } - ``` ## Optimistic Updates @@ -100,7 +96,6 @@ function markNotificationAsRead(environment, source, storyID) { To improve perceived responsiveness, you may wish to perform an "optimistic update", in which the client immediately updates to reflect the anticipated new value even before the response from the server has come back. The simplest way to do this is by providing an `optimisticResponse` and adding it to the `config` that we pass into `commitMutation`: ```javascript - const mutation = graphql` mutation MarkReadNotificationMutation( $input: MarkReadNotificationData! @@ -129,7 +124,6 @@ commitMutation( variables, }, ); - ``` Another way to enable optimistic updates is via the `optimisticUpdater`, which can be used for more complicated update scenarios. Using `optimisticUpdater` is covered in the section [below](#using-updater-and-optimisticupdater). @@ -149,7 +143,6 @@ Given a deletedIDFieldName, Relay will remove the node(s) from the connection. #### Example ```javascript - const mutation = graphql` mutation DestroyShipMutation($input: DestroyShipData!) { destroyShip(input: $input) { @@ -167,7 +160,6 @@ const configs = [{ type: 'NODE_DELETE', deletedIDFieldName: 'destroyedShipId', }]; - ``` ### RANGE_ADD @@ -187,7 +179,6 @@ Given a parent, information about the connection, and the name of the newly crea #### Example ```javascript - const mutation = graphql` mutation AddShipMutation($input: AddShipData!) { addShip(input: $input) { @@ -210,7 +201,6 @@ const configs = [{ }], edgeName: 'newShipEdge', }]; - ``` ### RANGE_DELETE @@ -232,7 +222,6 @@ from the connection but leave the associated record(s) in the store. #### Example ```javascript - const mutation = graphql` mutation RemoveTagsMutation($input: RemoveTagsData!) { removeTags(input: $input) { @@ -255,7 +244,6 @@ const configs = [{ pathToConnection: ['todo', 'tags'], deletedIDFieldName: removedTagId }]; - ``` ## Using updater and optimisticUpdater @@ -273,7 +261,6 @@ When you provide these functions, this is roughly what happens during the mutati Here are a quick example of adding a todo item to a Todo list using this [example schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L36): ```javascript - // AddTodoMutation.js import {commitMutation, graphql} from 'react-relay'; import {ConnectionHandler} from 'relay-runtime'; @@ -365,7 +352,6 @@ function commit( } ); } - ``` For details on how to interact with the Relay Store, please refer to our Relay Store [docs](./relay-store). diff --git a/website/versioned_docs/version-v1.4.1/Modern-NetworkLayer.md b/website/versioned_docs/version-v1.4.1/Modern-NetworkLayer.md index c5813a18609e8..e0d5a012a0ecf 100644 --- a/website/versioned_docs/version-v1.4.1/Modern-NetworkLayer.md +++ b/website/versioned_docs/version-v1.4.1/Modern-NetworkLayer.md @@ -8,7 +8,6 @@ In order to know how to access your GraphQL server, Relay Modern requires develo Currently the easiest way to create a network layer is via a helper from the `relay-runtime` package: ```javascript - const {Environment, Network} = require('relay-runtime'); // Define a function that fetches the results of an operation (query/mutation/etc) @@ -42,7 +41,6 @@ const environment = new Environment({ ..., // other options network, }); - ``` Note that this is a basic example to help you get started. This example could be extended with additional features such as request/response caching (enabled e.g. when `cacheConfig.force` is false) and uploading form data for mutations (the `uploadables` parameter). diff --git a/website/versioned_docs/version-v1.4.1/Modern-PaginationContainer.md b/website/versioned_docs/version-v1.4.1/Modern-PaginationContainer.md index 8a9ee1c315691..7cd45d706b42d 100644 --- a/website/versioned_docs/version-v1.4.1/Modern-PaginationContainer.md +++ b/website/versioned_docs/version-v1.4.1/Modern-PaginationContainer.md @@ -24,7 +24,6 @@ However, when [specifying connection fragments](#createpaginationcontainer) for The purpose of the `@connection` directive is to allow Relay to uniquely identify different connections under a parent type. The `@connection` directive takes 2 arguments that help identify the connection: ```graphql - @connection(key: String!, filters: [String]) ``` @@ -37,7 +36,6 @@ The purpose of the `@connection` directive is to allow Relay to uniquely identif Specifying just the `key`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and the value of `$orderBy` (given that no `filters` were provided) @@ -53,13 +51,11 @@ fragment Feed_user on User { } } } - ``` Specifying `key` and `filters`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and /only/ the value of `$searchTerm`, i.e. @@ -77,7 +73,6 @@ fragment Feed_user on User { } } } - ``` ## `createPaginationContainer` @@ -85,7 +80,6 @@ fragment Feed_user on User { `createPaginationContainer` has the following signature: ```javascript - createPaginationContainer( component: ReactComponentClass, fragmentSpec: GraphQLTaggedNode | {[string]: GraphQLTaggedNode}, @@ -113,7 +107,6 @@ type ConnectionData = { startCursor: ?string, }, }; - ``` ### Arguments @@ -137,7 +130,6 @@ type ConnectionData = { The Component resulting from `createPaginationContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -148,7 +140,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -163,7 +154,6 @@ type Props = { `hasMore` is a function available on the `relay` [prop](#available-props). This function indicates wether there are more pages to fetch from the server or not. ```javascript - hasMore: () => boolean, ``` @@ -173,7 +163,6 @@ hasMore: () => boolean, `isLoading` is a function available on the `relay` [prop](#available-props). This function indicates if a previous call to [`loadMore()`](#loadmore) is still pending. This is convenient for avoiding duplicate load calls. ```javascript - isLoading: () => boolean, ``` @@ -183,7 +172,6 @@ isLoading: () => boolean, `loadMore` is a function available on the `relay` [prop](#available-props). You can call `loadMore()` to fetch more items from the server based on the `connectionConfig` provided to the container. This will return null if there are no more items to fetch, otherwise it will fetch more items and return a Disposable that can be used to cancel the fetch. ```javascript - loadMore(pageSize: number, callback: ?(error: ?Error) => void): ?Disposable ``` @@ -198,7 +186,6 @@ loadMore(pageSize: number, callback: ?(error: ?Error) => void): ?Disposable `refetchConnection` is a function available on the `relay` [prop](#available-props). You can call `refetchConnection` to restart pagination on a connection from scratch, with optionally a completely new set of variables to pass to the pagination `query`. This is useful for example if you are paginating over a collection based on a userID and the userID changes, you'd want to start paginating over the new collection for the new user. ```javascript - refetchConnection:( count: number, callback: (error: ?Error) => void, @@ -216,7 +203,6 @@ refetchConnection:( ## Pagination Example ```javascript - // Feed.js import {createPaginationContainer, graphql} from 'react-relay'; @@ -311,5 +297,4 @@ module.exports = createPaginationContainer( ` } ); - ``` diff --git a/website/versioned_docs/version-v1.4.1/Modern-PersistedQueries.md b/website/versioned_docs/version-v1.4.1/Modern-PersistedQueries.md index 74b5c3c5d13c6..aadc6710f63bb 100644 --- a/website/versioned_docs/version-v1.4.1/Modern-PersistedQueries.md +++ b/website/versioned_docs/version-v1.4.1/Modern-PersistedQueries.md @@ -16,12 +16,10 @@ The relay compiler supports persisted queries which is useful because: In your `npm` script in `package.json`, run the relay compiler using the `--persist-output` flag: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` The `--persist-ouput` flag does 2 things: @@ -30,8 +28,7 @@ The `--persist-ouput` flag does 2 things: For example without `--persist-output`, a generated `ConcreteRequest` might look like below: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -48,8 +45,7 @@ The `--persist-ouput` flag does 2 things: With `--persist-output ` this becomes: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -67,12 +63,10 @@ The `--persist-ouput` flag does 2 things: 2. It generates a JSON file at the `` you specify containing a mapping from query ids to the corresponding operation texts. -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./src/queryMaps/queryMap.json" } - ``` The example above writes the complete query map file to `./src/queryMaps/queryMap.json`. You need to ensure all the directories @@ -82,8 +76,7 @@ leading to the `queryMap.json` file exist. You'll need to modify your network layer fetch implementation to pass a documentId parameter in the POST body instead of a query parameter: -```js - +```javascript function fetchQuery(operation, variables,) { return fetch('/graphql', { method: 'POST', @@ -99,7 +92,6 @@ function fetchQuery(operation, variables,) { return response.json(); }); } - ``` ## Executing Persisted Queries on the Server @@ -115,13 +107,11 @@ the query map file in a common location accessible to both the client and the se For applications where the client and server projects are separate, one option is to have an additional npm run script to push the query map at compile time to a location accessible by your server: -```js - +```javascript "scripts": { "push-queries": "node ./pushQueries.js", "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-ouput && npm run push-queries" } - ``` Some possibilities of what you can do in `./pushQueries.js`: @@ -145,8 +135,7 @@ database technologies you use, so we'll just cover the most common and basic exa If you use `express-graphql` and have access to the query map file, you can import the `--persist-output` JSON file directly and perform the matching using the `matchQueryMiddleware` from [relay-compiler-plus](https://github.com/yusinto/relay-compiler-plus). -```js - +```javascript import Express from 'express'; import expressGraphql from 'express-graphql'; import {matchQueryMiddleware} from 'relay-compiler-plus'; @@ -157,7 +146,6 @@ const app = Express(); app.use('/graphql', matchQueryMiddleware(queryMapJson), expressGraphql({schema})); - ``` ## Using `--persist-output` and `--watch` diff --git a/website/versioned_docs/version-v1.4.1/Modern-QueryRenderer.md b/website/versioned_docs/version-v1.4.1/Modern-QueryRenderer.md index 5b5fc9c90a237..6914b030ccd25 100644 --- a/website/versioned_docs/version-v1.4.1/Modern-QueryRenderer.md +++ b/website/versioned_docs/version-v1.4.1/Modern-QueryRenderer.md @@ -21,7 +21,6 @@ However, a `QueryRenderer` will not start loading its data until it is mounted, ## Example ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -53,5 +52,4 @@ class Example extends React.Component { ); } } - ``` diff --git a/website/versioned_docs/version-v1.4.1/Modern-RefetchContainer.md b/website/versioned_docs/version-v1.4.1/Modern-RefetchContainer.md index 25839f6aed901..416e049a71403 100644 --- a/website/versioned_docs/version-v1.4.1/Modern-RefetchContainer.md +++ b/website/versioned_docs/version-v1.4.1/Modern-RefetchContainer.md @@ -16,13 +16,11 @@ Table of Contents: `createRefetchContainer` has the following signature: ```javascript - createRefetchContainer( component: ReactComponentClass, fragmentSpec: GraphQLTaggedNode | {[string]: GraphQLTaggedNode}, refetchQuery: GraphQLTaggedNode, ): ReactComponentClass; - ``` ### Arguments @@ -40,7 +38,6 @@ createRefetchContainer( The Component resulting from `createRefetchContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -48,7 +45,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -64,7 +60,6 @@ type Props = { `refetch` has the following signature: ```javascript - type RefetchOptions = { force?: boolean, }; @@ -104,7 +99,6 @@ Returns a `Disposable` on which you could call `dispose()` to cancel the refetch In this simple example, let's assume we want to fetch the latest data for a `TodoItem` from the server: ```javascript - // TodoItem.js import {createRefetchContainer, graphql} from 'react-relay'; @@ -148,7 +142,6 @@ export default createRefetchContainer( } ` ); - ``` ### Loading more data @@ -156,7 +149,6 @@ export default createRefetchContainer( In this example we are using a Refetch Container to fetch more stories in a story feed component. ```javascript - import {createRefetchContainer, graphql} from 'react-relay'; class FeedStories extends React.Component { @@ -212,5 +204,4 @@ export default createRefetchContainer( } `, ); - ``` diff --git a/website/versioned_docs/version-v1.4.1/Modern-RelayCompat.md b/website/versioned_docs/version-v1.4.1/Modern-RelayCompat.md index 36632d3a8f1a1..f47dbd845ba3e 100644 --- a/website/versioned_docs/version-v1.4.1/Modern-RelayCompat.md +++ b/website/versioned_docs/version-v1.4.1/Modern-RelayCompat.md @@ -31,7 +31,6 @@ Relay Modern. The components using Relay Compat can be referred to by both other Relay Modern and Relay Classic components. ```javascript - const {createFragmentContainer, graphql} = require('react-relay/compat'); class TodoItem extends React.Component { @@ -47,5 +46,4 @@ module.exports = createFragmentContainer(TodoItem, graphql` isComplete } `); - ``` diff --git a/website/versioned_docs/version-v1.4.1/Modern-RelayEnvironment.md b/website/versioned_docs/version-v1.4.1/Modern-RelayEnvironment.md index b356b5deecdc5..ed75bc69d1f86 100644 --- a/website/versioned_docs/version-v1.4.1/Modern-RelayEnvironment.md +++ b/website/versioned_docs/version-v1.4.1/Modern-RelayEnvironment.md @@ -12,7 +12,6 @@ Most applications will create a single Environment instance and use it throughou To create an environment instance in Relay Modern, use the `RelayModernEnvironment` class: ```javascript - const { Environment, Network, @@ -30,7 +29,6 @@ const environment = new Environment({ network, store, }); - ``` For more details on creating a Network, see the [NetworkLayer guide](./network-layer). @@ -44,7 +42,6 @@ The example above did not configure a `handlerProvider`, which means that a defa If you wish to provide your own `handlerProvider`, you can do so: ```javascript - const { ConnectionHandler, ViewerHandler, @@ -60,5 +57,4 @@ function handlerProvider(handle) { `handlerProvider: No handler provided for ${handle}` ); } - ``` diff --git a/website/versioned_docs/version-v1.4.1/Modern-RelayStore.md b/website/versioned_docs/version-v1.4.1/Modern-RelayStore.md index 91845846694f4..e8e2df3d9efcf 100644 --- a/website/versioned_docs/version-v1.4.1/Modern-RelayStore.md +++ b/website/versioned_docs/version-v1.4.1/Modern-RelayStore.md @@ -16,7 +16,6 @@ Table of Contents: The `RecordSourceSelectorProxy` is the type of the `store` that [`updater` functions](./mutations#using-updater-and-optimisticupdater) receive as an argument. The following is the `RecordSourceSelectorProxy` interface: ```javascript - interface RecordSourceSelectorProxy { create(dataID: string, typeName: string): RecordProxy; delete(dataID: string): void; @@ -25,7 +24,6 @@ interface RecordSourceSelectorProxy { getRootField(fieldName: string): ?RecordProxy; getPluralRootField(fieldName: string): ?Array; } - ``` ### `create(dataID: string, typeName: string): RecordProxy` @@ -35,9 +33,7 @@ Creates a new record in the store given a `dataID` and the `typeName` as defined #### Example ```javascript - const record = store.create(dataID, 'Todo'); - ``` ### `delete(dataID: string): void` @@ -47,9 +43,7 @@ Deletes a record from the store given its `dataID`. #### Example ```javascript - store.delete(dataID); - ``` ### `get(dataID: string): ?RecordProxy` @@ -59,9 +53,7 @@ Retrieves a record from the store given its `dataID`. Returns a [`RecordProxy`]( #### Example ```javascript - const record = store.get(dataID); - ``` ### `getRoot(): RecordProxy` @@ -73,20 +65,16 @@ Returns the [`RecordProxy`](#recordproxy) representing the root of the GraphQL d Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - // Represents root query const root = store.getRoot(); - ``` ### `getRootField(fieldName: string): ?RecordProxy` @@ -98,19 +86,15 @@ Retrieves a root field from the store given the `fieldName`, as defined by the G Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - const viewer = store.getRootField('viewer'); - ``` ### `getPluralRootField(fieldName: string): ?Array` @@ -122,19 +106,15 @@ Retrieves a root field that represents a collection from the store given the `fi Given the GraphQL document: ```graphql - nodes(first: 10) { # ... } - ``` Usage: ```javascript - const nodes = store.getPluralRootField('nodes'); - ``` ## RecordProxy @@ -142,7 +122,6 @@ const nodes = store.getPluralRootField('nodes'); The `RecordProxy` serves as an interface to mutate records: ```javascript - interface RecordProxy { copyFieldsFrom(sourceRecord: RecordProxy): void; getDataID(): string; @@ -167,7 +146,6 @@ interface RecordProxy { ): RecordProxy; setValue(value: mixed, name: string, arguments?: ?Object): RecordProxy; } - ``` ### `getDataID(): string` @@ -177,9 +155,7 @@ Returns the dataID of the current record. #### Example ```javascript - const id = record.getDataID(); - ``` ### `getType(): string` @@ -189,7 +165,6 @@ Gets the type of the current record, as defined by the GraphQL schema. #### Example ```javascript - const type = user.getType(); // User ``` @@ -203,20 +178,16 @@ Gets the value of a field in the current record given the field name. Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - const name = viewer.getValue('name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. @@ -226,20 +197,16 @@ Optionally, if the field takes arguments, you can pass a bag of `variables`. Given the GraphQL document: ```graphql - viewer { id name(arg: $arg) } - ``` Usage: ```javascript - const name = viewer.getValue('name', {arg: 'value'}); - ``` ### `getLinkedRecord(name: string, arguments?: ?Object): ?RecordProxy` @@ -251,23 +218,19 @@ Retrieves the a record associated with the current record given the field name, Given the GraphQL document: ```graphql - rootField { viewer { id name } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -277,22 +240,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { viewer(arg: $arg) { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {arg: 'value'}); - ``` ### `getLinkedRecords(name: string, arguments?: ?Object): ?Array` @@ -304,22 +263,18 @@ Retrieves the set of records associated with the current record given the field Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const nodes = rootField.getLinkedRecord('nodes'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -329,22 +284,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { nodes(first: $count) { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {count: 10}); - ``` ### `getOrCreateLinkedRecord(name: string, typeName: string, arguments?: ?Object)` @@ -356,19 +307,16 @@ Retrieves the a record associated with the current record given the field name, Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = rootField.getOrCreateLinkedRecord('viewer', 'User'); // Will create if it doesn't exist @@ -383,28 +331,22 @@ Mutates the current record by setting a new value on the specified field. Return Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - viewer.setValue('New Name', 'name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. ```javascript - viewer.setValue('New Name', 'name', {arg: 'value'}); - ``` ### `copyFieldsFrom(sourceRecord: RecordProxy): void` @@ -414,7 +356,6 @@ Mutates the current record by copying the fields over from the passed in record #### Example ```javascript - const record = store.get(id1); const otherRecord = store.get(id2); record.copyFieldsFrom(otherRecord); // Mutates `record` @@ -430,19 +371,16 @@ Mutates the current record by setting a new linked record on the given the field Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = store.create(/* ... */)'' rootField.setLinkedRecord(newViewer, 'viewer'); // @@ -460,19 +398,16 @@ Mutates the current record by setting a new set of linked records on the given t Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newNode = store.create(/* ... */); const newNodes = [...rootField.getLinkedRecords('nodes'), newNode]; @@ -487,7 +422,6 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl `ConnectionHandler` is a utility module exposed by `relay-runtime` that aids in the manipulation of connections. `ConnectionHandler` exposes the following interface: ```javascript - interface ConnectionHandler { getConnection( record: RecordProxy, @@ -512,7 +446,6 @@ interface ConnectionHandler { ): void, deleteNode(connection: RecordProxy, nodeID: string): void } - ``` ### `getConnection(record: RecordProxy, key: string, filters?: ?Object)` @@ -522,7 +455,6 @@ Given a record and a connection key, and optionally a set of filters, `getConnec First, let's take a look at a plain connection: ```graphql - fragment FriendsFragment on User { friends(first: 10) { edges { @@ -532,26 +464,22 @@ fragment FriendsFragment on User { } } } - ``` Accessing a plain connection field like this is the same as other regular field: ```javascript - // The `friends` connection record can be accessed with: const user = store.get(userID); const friends = user && user.getLinkedRecord(user, 'friends'); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` In a [pagination container](./pagination-container), we usually annotate the actual connection field with `@connection` to tell Relay which part needs to be paginated: ```graphql - fragment FriendsFragment on User { friends(first: 10, orderby: "firstname") @connection( key: "FriendsFragment_friends", @@ -563,7 +491,6 @@ fragment FriendsFragment on User { } } } - ``` For connections like the above, `ConnectionHandler` helps us find the record: @@ -581,7 +508,6 @@ const friends = ConnectionHandler.getConnection( ); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` ### Edge creation and insertion @@ -611,7 +537,6 @@ ConnectionHandler.insertEdgeAfter(friends, edge); // No cursor provided, Insert the edge at the front: ConnectionHandler.insertEdgeBefore(friends, edge); - ``` ### `deleteNode(connection: RecordProxy, nodeID: string): void` @@ -625,5 +550,4 @@ Given a connection, deletes any edges whose id matches the given id. const user = store.get(userID); const friends = ConnectionHandler.getConnection(user, 'friends'); ConnectionHandler.deleteNode(friends, idToDelete); - ``` diff --git a/website/versioned_docs/version-v1.4.1/Modern-Subscriptions.md b/website/versioned_docs/version-v1.4.1/Modern-Subscriptions.md index a02a27933c40a..c4e9b324730f0 100644 --- a/website/versioned_docs/version-v1.4.1/Modern-Subscriptions.md +++ b/website/versioned_docs/version-v1.4.1/Modern-Subscriptions.md @@ -6,7 +6,6 @@ original_id: subscriptions Relay exposes the following APIs to create subscriptions. ```javascript - const {requestSubscription} = require('react-relay'); type Variables = {[name: string]: any}; @@ -23,7 +22,6 @@ requestSubscription( configs?: Array, }, ); - ``` Now let's take a closer look at the `config`: @@ -47,7 +45,6 @@ appropriate when you are only changing the properties of existing records that can be identified by their `id`: ```javascript - const { requestSubscription, graphql, @@ -81,7 +78,6 @@ requestSubscription( onError: error => console.error(error), } ); - ``` # Updating the client on each response @@ -91,7 +87,6 @@ Relay's in-memory cache when each subscription response is received. To do so, pass an `updater` function: ```javascript - const {ConnectionHandler} = require('relay-runtime'); requestSubscription( @@ -117,5 +112,4 @@ requestSubscription( }, }, ); - ``` diff --git a/website/versioned_docs/version-v1.4.1/Modern-TestingRelayComponents.md b/website/versioned_docs/version-v1.4.1/Modern-TestingRelayComponents.md index f30317b146e96..eaa443bd20147 100644 --- a/website/versioned_docs/version-v1.4.1/Modern-TestingRelayComponents.md +++ b/website/versioned_docs/version-v1.4.1/Modern-TestingRelayComponents.md @@ -64,7 +64,6 @@ With the `MockPayloadGenerator` and `@relay_test_operation`, we want to get rid Example of a simple Mock Resolver: ```javascript - { ID() { // Return mock value for a scalar filed with type ID @@ -75,13 +74,11 @@ Example of a simple Mock Resolver: return "Lorem Ipsum" } } - ``` It is possible to define more resolvers for Object types: ```javascript - { // This will be the default values for User object in the query response User() { @@ -94,7 +91,6 @@ It is possible to define more resolvers for Object types: }; }, } - ``` ### Mock Resolver Context @@ -102,7 +98,6 @@ It is possible to define more resolvers for Object types: The first argument of the MockResolver is the object that contains Mock Resolver Context. It is possible to return dynamic values from mock resolvers based on the context - for instance, name or alias of the field, a path in the selection, arguments, or parent type. ```javascript - { String(context) { if (context.name === 'zip') { @@ -116,7 +111,6 @@ The first argument of the MockResolver is the object that contains Mock Resolver } } } - ``` ### ID Generation @@ -124,14 +118,12 @@ The first argument of the MockResolver is the object that contains Mock Resolver The second argument of the Mock Resolver its a function that will generate a sequence of integers, useful to generate unique IDs in the tests: ```javascript - { // will generate strings "my-id-1", "my-id-2", etc. ID(_, generateId) { return `my-id-${generateId()}`; }, } - ``` ### `@relay_test_operation` @@ -141,7 +133,6 @@ Most of GraphQL type information for a specific field in the selection is not av Operations with the `@relay_test_operation` directive will have additional metadata that will contain GraphQL type info for fields in the operation's selection. And it will improve the quality of the generated data. You also will be able to define Mock resolvers for Scalar (not only ID and String) and Abstract types: ```javascript - { Float() { return 123.456; @@ -159,7 +150,6 @@ Operations with the `@relay_test_operation` directive will have additional metad }; } } - ``` ## Examples @@ -169,7 +159,6 @@ Operations with the `@relay_test_operation` directive will have additional metad Using `createMockEnvironment` and `MockPayloadGenerator` allows writing concise tests for components that are using Relay Containers and Renderers. Both those modules can be imported from `relay-test-utils`. ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { @@ -222,7 +211,6 @@ test('Error State', () => { renderer.root.find(item => (item.props.testID = 'errorMessage')), ).toBeDefined(); }); - ``` ### Fragment Container Tests @@ -230,7 +218,6 @@ test('Error State', () => { Essentially, in the example above, `resolveMostRecentOperation` will generate data for all child fragment containers (pagination, refetch). Usually, the Root Components container may have many child fragment components and you may want to exercise a specific Fragment Container. The solution for that would be to wrap your fragment container with the QueryRenderer that renders a Query that's spreads fragments from your fragment container. ```javascript - test('Fragment Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -261,7 +248,6 @@ test('Fragment Container', () => { expect(renderer).toMatchSnapshot(); }); - ``` ### Pagination Container Test @@ -269,7 +255,6 @@ test('Fragment Container', () => { Essentially, tests for Pagination container are not different from Fragment Container tests. We can also do more here. We can actually see how the pagination works by asserting the behavior of our components when performing pagination (load more, refetch). ```javascript - // Pagination Example test('Pagination Container', () => { const environment = createMockEnvironment(); @@ -343,7 +328,6 @@ test('Pagination Container', () => { We can use similar approach here with wrapping container with Query Renderer. And for the sake of completeness, we will add example here: ```javascript - test('Refetch Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -385,7 +369,6 @@ test('Refetch Container', () => { ); // expect(renderer).toMatchSnapshot(); }); - ``` ### Mutations @@ -393,7 +376,6 @@ test('Refetch Container', () => { Mutations itself are operations so we can test them independently (unit-test) for specific mutation, or in combination with the view from which this mutation is called. ```javascript - // Say, you have a mutation function function sendMutation(environment, onCompleted, onError, variables) commitMutation(environment, { @@ -416,7 +398,6 @@ test('it should send mutation', () => { ); expect(onCompleted).toBeCalled(); }); - ``` ### Subscription @@ -424,7 +405,6 @@ test('it should send mutation', () => { We can test subscription in a similar way we test mutations ```javascript - // Example subscribe function function subscribe(environment, onNext, onError, variables) requestSubscription(environment, { @@ -447,7 +427,6 @@ test('it should subscribe', () => { ); expect(onNext).toBeCalled(); }); - ``` ### Example with `queueOperationResolver` @@ -455,7 +434,6 @@ test('it should subscribe', () => { With `queueOpeararionResolver`, it possible to define responses for operations that will be executed on the environment ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { diff --git a/website/versioned_docs/version-v1.4.1/Modern-TypeEmission.md b/website/versioned_docs/version-v1.4.1/Modern-TypeEmission.md index c25bc737d5684..9f41810a3618b 100644 --- a/website/versioned_docs/version-v1.4.1/Modern-TypeEmission.md +++ b/website/versioned_docs/version-v1.4.1/Modern-TypeEmission.md @@ -15,7 +15,6 @@ In this example the emitted type-information would require the variables object #### Flow ```javascript - /** * export type ExampleQueryVariables = {| * +artistID: string @@ -43,7 +42,6 @@ const variables: ExampleQueryVariables = { #### TypeScript ```javascript - /** * export type ExampleQueryVariables = { * readonly artistID: string @@ -78,7 +76,6 @@ In this example the emitted type-information describes the response data availab #### Flow ```javascript - /** * export type ExampleQueryResponse = {| * +artist: ?{| @@ -109,7 +106,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * export type ExampleQueryResponse = { * readonly artist?: { @@ -145,7 +141,6 @@ Similarly, in this example the emitted type-information describes the prop data #### Flow ```javascript - /** * export type ExampleFragment_artist = {| * +name: string @@ -171,7 +166,6 @@ export const ExampleFragment = createFragmentContainer( #### TypeScript ```javascript - /** * export type ExampleFragment_artist = { * readonly name: string @@ -205,7 +199,6 @@ Consider a component that composes the above fragment container example. In this #### Flow ```javascript - /** * import type { FragmentReference } from "relay-runtime"; * declare export opaque type ExampleFragment_artist$ref: FragmentReference; @@ -249,7 +242,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * declare const _ExampleFragment_artist$ref: unique symbol; * export type ExampleFragment_artist$ref = typeof _ExampleFragment_artist$ref; @@ -314,7 +306,6 @@ $ relay-compiler --artifactDirectory ./src/__generated__ […] ["relay", { "artifactDirectory": "./src/__generated__" }] ] } - ``` It is recommended to alias this directory in your module resolution configuration such that you don’t need to specify relative paths in your source files. This is what is also done in the above examples, where artifacts are imported from a `__generated__` alias, rather than relative paths like `../../../../__generated__`. diff --git a/website/versioned_docs/version-v1.4.1/Modern-UpgradingSetVariables.md b/website/versioned_docs/version-v1.4.1/Modern-UpgradingSetVariables.md index d5b086fafce20..ff73feec04f8b 100644 --- a/website/versioned_docs/version-v1.4.1/Modern-UpgradingSetVariables.md +++ b/website/versioned_docs/version-v1.4.1/Modern-UpgradingSetVariables.md @@ -36,7 +36,6 @@ fragment on User { # ... } } - ``` This should be upgraded to use a [`PaginationContainer`](./pagination-container). @@ -61,7 +60,6 @@ fragment on User { # ... } } - ``` This can be upgraded by using a [`RefetchContainer`](./refetch-container) which allows you to specify the exact query to use to fetch the new data. @@ -86,7 +84,6 @@ fragment on FeedbackTarget { # ... } } - ``` This can be upgraded by conditionally rendering a [`QueryRenderer`](./query-renderer) which will load the data once it is rendered. The code overhead of doing this is dramatically reduced with the new API. diff --git a/website/versioned_docs/version-v1.4.1/Modern-fetchQuery.md b/website/versioned_docs/version-v1.4.1/Modern-fetchQuery.md index 19e9b57c4219a..223c01ccc75c2 100644 --- a/website/versioned_docs/version-v1.4.1/Modern-fetchQuery.md +++ b/website/versioned_docs/version-v1.4.1/Modern-fetchQuery.md @@ -5,7 +5,6 @@ title: fetchQuery You can use the `fetchQuery` function to imperatively make GraphQL Requests. This is useful for cases where you want to make requests outside of React but still utilize the Relay store and network layer. ```javascript - import {fetchQuery, graphql} from 'relay-runtime'; const query = graphql` @@ -24,7 +23,6 @@ fetchQuery(environment, query, variables) .then(data => { // access the graphql response }); - ``` ## Arguments diff --git a/website/versioned_docs/version-v1.4.1/PrinciplesAndArchitecture-Compiler.md b/website/versioned_docs/version-v1.4.1/PrinciplesAndArchitecture-Compiler.md index c195491682b1f..fcd0490cb724f 100644 --- a/website/versioned_docs/version-v1.4.1/PrinciplesAndArchitecture-Compiler.md +++ b/website/versioned_docs/version-v1.4.1/PrinciplesAndArchitecture-Compiler.md @@ -74,7 +74,6 @@ foo { # type FooType foo { id } - ``` - `SkipRedundantNodeTransform`: A more advanced version of flattening, this eliminates more complex cases of field duplication such as when a field is fetched both unconditionally and conditionally, or is fetched by two different sub-fragments. For example: @@ -97,7 +96,6 @@ foo { id } } - ``` - `GenerateRequisiteFieldTransform`: This optional, Relay-specific transform inserts `id` fields for globally identifiable objects and `__typename` fields wherever the type cannot be statically determined (e.g. for unions). diff --git a/website/versioned_docs/version-v1.4.1/PrinciplesAndArchitecture-Runtime.md b/website/versioned_docs/version-v1.4.1/PrinciplesAndArchitecture-Runtime.md index f012908d090c5..e9c88a4b2ae0c 100644 --- a/website/versioned_docs/version-v1.4.1/PrinciplesAndArchitecture-Runtime.md +++ b/website/versioned_docs/version-v1.4.1/PrinciplesAndArchitecture-Runtime.md @@ -77,7 +77,6 @@ RecordSource { city: 'Seattle', } } - ``` [1] Note that GraphQL itself does not impose this constraint, and Relay Runtime may also be used for schemas that do not conform to it. For example, both systems can be used to query a single denormalized table. However, many of the features that Relay Runtime provides, such as caching and normalization, work best when the data is represented as a normalized graph with stable identities for discrete pieces of information. diff --git a/website/versioned_docs/version-v1.4.1/PrinciplesAndArchitecture-ThinkingInGraphQL.md b/website/versioned_docs/version-v1.4.1/PrinciplesAndArchitecture-ThinkingInGraphQL.md index 14b1119288f23..9527e65e8950e 100644 --- a/website/versioned_docs/version-v1.4.1/PrinciplesAndArchitecture-ThinkingInGraphQL.md +++ b/website/versioned_docs/version-v1.4.1/PrinciplesAndArchitecture-ThinkingInGraphQL.md @@ -12,7 +12,6 @@ In this article we'll explore what it means to build a GraphQL client framework Imagine we have a simple application that fetches a list of stories, and some details about each one. Here's how that might look in resource-oriented REST: ```javascript - // Fetch the list of story IDs but not their details: rest.get('/stories').then(stories => // This resolves to a list of items with linked resources: @@ -25,13 +24,11 @@ rest.get('/stories').then(stories => // `[ { id: "...", text: "..." } ]` console.log(stories); }); - ``` Note that this approach requires _n+1_ requests to the server: 1 to fetch the list, and _n_ to fetch each item. With GraphQL we can fetch the same data in a single network request to the server (without creating a custom endpoint that we'd then have to maintain): ```javascript - graphql.get(`query { stories { id, text } }`).then( stories => { // A list of story items: @@ -39,7 +36,6 @@ graphql.get(`query { stories { id, text } }`).then( console.log(stories); } ); - ``` So far we're just using GraphQL as a more efficient version of typical REST approaches. Note two important benefits in the GraphQL version: @@ -56,7 +52,6 @@ Repeatedly refetching information from the server can get quite slow. For exampl In a resource-oriented REST system, we can maintain a **response cache** based on URIs: ```javascript - var _cache = new Map(); rest.get = uri => { if (!_cache.has(uri)) { @@ -64,13 +59,11 @@ rest.get = uri => { } return _cache.get(uri); }; - ``` Response-caching can also be applied to GraphQL. A basic approach would work similarly to the REST version. The text of the query itself can be used as a cache key: ```javascript - var _cache = new Map(); graphql.get = queryText => { if (!_cache.has(queryText)) { @@ -78,7 +71,6 @@ graphql.get = queryText => { } return _cache.get(queryText); }; - ``` Now, requests for previously cached data can be answered immediately without making a network request. This is a practical approach to improving the perceived performance of an application. However, this method of caching can cause problems with data consistency. @@ -90,7 +82,6 @@ With GraphQL it is very common for the results of multiple queries to overlap. H ``` query { stories { id, text, likeCount } } - ``` and then later refetch one of the stories whose `likeCount` has since been incremented: @@ -98,7 +89,6 @@ and then later refetch one of the stories whose `likeCount` has since been incre ``` query { story(id: "123") { id, text, likeCount } } - ``` We'll now see different `likeCount`s depending on how the story is accessed. A view that uses the first query will see an outdated count, while a view using the second query will see the updated count. @@ -119,7 +109,6 @@ query { } } } - ``` And here's a possible response: @@ -134,13 +123,11 @@ query: { } } } - ``` Although the response is hierarchical, we'll cache it by flattening all the records. Here is an example of how Relay would cache this query response: ```javascript - Map { // `story(id: "1")` 1: Map { @@ -152,7 +139,6 @@ Map { name: 'Jan', }, }; - ``` This is only a simple example: in reality the cache must handle one-to-many associations and pagination (among other things). @@ -182,7 +168,6 @@ The first query was for a list of stories: ``` query { stories { id, text, likeCount } } - ``` With a normalized response cache, a record would be created for each story in the list. The `stories` field would store links to each of these records. @@ -192,7 +177,6 @@ The second query refetched the information for one of those stories: ``` query { story(id: "123") { id, text, likeCount } } - ``` When this response is normalized, Relay can detect that this result overlaps with existing data based on its `id`. Rather than create a new record, Relay will update the existing `123` record. The new `likeCount` is therefore available to _both_ queries, as well as any other query that might reference this story. @@ -215,7 +199,6 @@ query { } } } - ``` After initially fetching this story our cache might be as follows. Note that the story and comment both link to the same record as `author`: @@ -242,7 +225,6 @@ Map { author: Link(2), }, } - ``` The author of this story also commented on it — quite common. Now imagine that some other view fetches new information about the author, and her profile photo has changed to a new URI. Here's the _only_ part of our cached data that changes: @@ -256,7 +238,6 @@ Map { photo: 'http://.../photo2.jpg', }, } - ``` The value of the `photo` field has changed; and therefore the record `2` has also changed. And that's it. Nothing else in the _cache_ is affected. But clearly our _view_ needs to reflect the update: both instances of the author in the UI (as story author and comment author) need to show the new photo. @@ -273,7 +254,6 @@ ImmutableMap { }, 3: ImmutableMap // same as before } - ``` If we replace `2` with a new immutable record, we'll also get a new immutable instance of the cache object. However, records `1` and `3` are untouched. Because the data is normalized, we can't tell that `story`'s contents have changed just by looking at the `story` record alone. @@ -299,7 +279,6 @@ mutation StoryLike($storyID: String) { likeCount } } - ``` Notice that we're querying for data that _may_ have changed as a result of the mutation. An obvious question is: why can't the server just tell us what changed? The answer is: it's complicated. GraphQL abstracts over _any_ data storage layer (or an aggregation of multiple sources), and works with any programming language. Furthermore, the goal of GraphQL is to provide data in a form that is useful to product developers building a view. diff --git a/website/versioned_docs/version-v1.4.1/PrinciplesAndArchitecture-ThinkingInRelay.md b/website/versioned_docs/version-v1.4.1/PrinciplesAndArchitecture-ThinkingInRelay.md index 47c27f92ab909..1ffea144589ad 100644 --- a/website/versioned_docs/version-v1.4.1/PrinciplesAndArchitecture-ThinkingInRelay.md +++ b/website/versioned_docs/version-v1.4.1/PrinciplesAndArchitecture-ThinkingInRelay.md @@ -30,13 +30,11 @@ fragment Story_story on Story { photo } } - ``` And this fragment can then be used to define the Story container: ```javascript - const {createFragmentContainer, graphql} = require('react-relay'); // Plain React component. @@ -64,7 +62,6 @@ const StoryContainer = createFragmentContainer(Story, { In React, rendering a view requires two inputs: the _component_ to render, and a _root_ DOM (UI) node to render into. Rendering Relay containers is similar: we need a _container_ to render, and a _root_ in the graph from which to start our query. We also must ensure that the queries for the container are executed and may want to show a loading indicator while data is being fetched. Similar to `ReactDOM.render(component, domNode)`, Relay provides `` for this purpose. The `query` and `variables` define what data to fetch and `render` defines what to render. Here's how we might render ``: ```javascript - ReactDOM.render( { ); } } - ``` The above code is doing something very similar to our [previous example](#rendering-graphql-queries), however, we are now passing a `$userID` variable to the GraphQL query, via the `variables` prop. This has a couple of important implications: @@ -229,7 +217,6 @@ Now that we know how to define and fetch queries, let's actually start building First, let's start at the bottom; let's say that we want to render a component that given a todo item, simply displays the item's text and completed state: ```javascript - // Todo.js import React from 'react'; @@ -259,7 +246,6 @@ export default class Todo extends React.Component { ); } } - ``` From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L107), we know that we can query this data on the `Todo` type. However, we don't want to have to send a separate query for each todo item; that would defeat the purpose of using GraphQL over a traditional REST API. We could manually query for these fields directly in our `QueryRenderer` query, but that would hurt re-usability: what if we want to query the same set of fields as part of a different query? Additionally, we wouldn't know which component needs the data we're querying, a problem Relay directly tries to address. @@ -267,18 +253,15 @@ From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/dat Instead, we can define a reusable [Fragment](http://graphql.org/learn/queries/#fragments), which allows us to define a set of fields on a type and reuse them within our queries wherever we need to: ```graphql - fragment TodoItemFragment on Todo { complete text } - ``` Our component can then use this fragment to declare its data dependency on the `Todo` GraphQL type: ```javascript - // Todo.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -338,7 +321,6 @@ Before proceeding, don't forget to run the Relay Compiler with `yarn relay`. Given that [Fragment Containers](./fragment-container) are just React components, we can compose them as such, and even re-use fragment containers within other fragment containers. As an example, let's see how we would define a `TodoList` component that just renders a list of todo items, and whether all have been completed or not: ```javascript - // TodoList.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -397,7 +379,6 @@ export default createFragmentContainer( } `, ); - ``` As with the first fragment container we defined, `TodoList` declares it's data dependencies via a fragment. However, this component additionally re-uses the fragment previously defined by the `Todo` component, and passes the appropriate data to when rendering the child `Todo` components (a.k.a. fragment containers). @@ -412,7 +393,6 @@ fragment containers do not directly fetch data. Instead, containers declare a sp A `QueryRenderer` rendering these fragment containers could look like the following: ```javascript - // ViewerTodoList.js import React from 'react'; import PropTypes from 'prop-types'; @@ -454,7 +434,6 @@ export default ViewerTodoList extends React.Component { ); } } - ``` Check out or docs for [Fragment Containers](./fragment-container) for more details, and our guides on [Refetch](./refetch-container) and [Pagination](./pagination-container) for more advanced usage of containers. @@ -466,7 +445,6 @@ Now that we know how to query for and render data, let's move on to changing our From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L35), we know that we have some mutations available to us, so let's start by writing a mutation to change the `complete` status of a given todo item (i.e. mark or unmark it as done): ```graphql - mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { changeTodoStatus(input: $input) { todo { @@ -475,7 +453,6 @@ mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { } } } - ``` This mutation allows us to query back some data as a [result of the mutation](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L18), so we're going to query for the updated `complete` status on the todo item. @@ -483,7 +460,6 @@ This mutation allows us to query back some data as a [result of the mutation](ht In order to execute this mutation in Relay, we're going to write a new mutation using Relay's `commitMutation` api: ```javascript - // ChangeTodoStatusMutation.js import {graphql, commitMutation} from 'react-relay'; @@ -517,7 +493,6 @@ function commit( } export default {commit}; - ``` Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mutation to the server, and in our case, upon receiving a response it will automatically update the local data store with the latest data from the server. This also means that upon receiving the response, Relay will ensure that any components (i.e. containers) that depend on the updated data are re-rendered. @@ -525,7 +500,6 @@ Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mut In order to actually use this mutation in our component, we could update our `Todo` component in the following way: ```javascript - // Todo.js // ... @@ -559,7 +533,6 @@ In order to make the experience better, we can configure our mutation to do an o In Relay, there's a couple of options we can pass to `commitMutation` to enable optimistic updates. Let's see what that would look like in our `ChangeTodoStatusMutation`: ```javascript - // ChangeTodoStatusMutation.js // ... @@ -594,7 +567,6 @@ function commit( } export default {commit}; - ``` In the simplest case above, we just need to pass an `optimisticResponse` option, which should refer to an object having the same shape as the mutation response payload. When we pass this option, Relay will know to immediately update our local data with the optimistic response, and then update it with the actual server response, or roll it back if an error occurs. diff --git a/website/versioned_docs/version-v1.5.0/Modern-ConvertingMutations.md b/website/versioned_docs/version-v1.5.0/Modern-ConvertingMutations.md index 288ac18ab0872..96410a4589cef 100644 --- a/website/versioned_docs/version-v1.5.0/Modern-ConvertingMutations.md +++ b/website/versioned_docs/version-v1.5.0/Modern-ConvertingMutations.md @@ -12,19 +12,16 @@ FatQueries in Relay Classic mutations was a concept that was confusing for a num Example of existing fat query: ```javascript - RelayClassic.QL` fragment on MarkReadNotificationResponsePayload @relay(pattern: true) { notification } `; - ``` Example of converted mutation query: ```javascript - graphql` mutation MarkReadNotificationMutation( $input: MarkReadNotificationData! @@ -37,7 +34,6 @@ graphql` } } `; - ``` ## Migrating Configs @@ -63,7 +59,6 @@ This is no longer needed in Compatibility Mode for neither environments. Relay w Take this example of a simple mutation in Relay Classic: ```javascript - class LikeStoryMutation extends RelayClassic.Mutation { getMutation() { return RelayClassic.QL`mutation {likeStory}`; @@ -102,7 +97,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { `, }; } - ``` ### Converting `getMutation()` and `getFatQuery()` @@ -110,7 +104,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { We combine these two into a regular GraphQL mutation, which list out specific fields that needs to be updated. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story(data: $input) { @@ -122,7 +115,6 @@ const mutation = graphql` } } `; - ``` ### Converting `getConfigs()` @@ -134,13 +126,11 @@ As specified above, `FIELDS_CHANGE` configs can be omitted. To convert `getVariables()`, we take the return value from the original function and wrap it in an object that contains a property that matches the variable name for the mutation. In this case, the mutation has a `input` variable that is of type `LikeStoryData`. ```javascript - const variables = { input: { storyID: args.storyID } } - ``` ### Final Result @@ -148,7 +138,6 @@ const variables = { As you can see, our resulting mutation is a lot simpler and more like regular GraphQL than the Relay Classic version we started out with. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story { @@ -174,7 +163,6 @@ function commit(environment: CompatEnvironment, args) { variables, }); } - ``` See [Mutation](./mutations) for additional options on `commitMutation` for more complex mutations. diff --git a/website/versioned_docs/version-v1.5.0/Modern-FragmentContainer.md b/website/versioned_docs/version-v1.5.0/Modern-FragmentContainer.md index e86b79995c1c7..7bbd0a9f22899 100644 --- a/website/versioned_docs/version-v1.5.0/Modern-FragmentContainer.md +++ b/website/versioned_docs/version-v1.5.0/Modern-FragmentContainer.md @@ -17,12 +17,10 @@ Table of Contents: `createFragmentContainer` has the following signature: ```javascript - createFragmentContainer( component: ReactComponentClass, fragmentSpec: GraphQLTaggedNode | {[string]: GraphQLTaggedNode}, ): ReactComponentClass; - ``` ### Arguments @@ -46,7 +44,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -61,7 +58,6 @@ To start, let's build the plain React version of a hypothetical `` c Here's a basic implementation of `` that ignores styling in order to highlight the functionality: ```javascript - // TodoItem.js class TodoItem extends React.Component { render() { @@ -81,7 +77,6 @@ class TodoItem extends React.Component { ); } } - ``` ### Data Dependencies With GraphQL @@ -89,7 +84,6 @@ class TodoItem extends React.Component { In Relay, data dependencies are described using [GraphQL](https://github.com/facebook/graphql). For ``, the dependency can be expressed as follows. Note that this exactly matches the shape that the component expected for the `item` prop. ```javascript - graphql` # This fragment only applies to objects of type 'Todo'. fragment TodoItem_item on Todo { @@ -105,7 +99,6 @@ graphql` Given the plain React component and a GraphQL fragment, we can now define a Fragment Container to specify this component's data requirements. Let's look at the code first and then see what's happening: ```javascript - // TodoItem.js import {createFragmentContainer, graphql} from 'react-relay'; @@ -123,13 +116,11 @@ export default createFragmentContainer(TodoItem, { } `, }); - ``` Relay will infer the prop name from the fragment name according to the fragment naming convention `<...>_`. The example below is equivalent to the one above: ```javascript - export default createFragmentContainer( TodoItem, graphql` @@ -139,13 +130,11 @@ export default createFragmentContainer( } `, ); - ``` If there is no `_` suffix, the `data` prop name will be used: ```javascript - class TodoItem extends React.Component { render() { const item = this.props.data; @@ -162,7 +151,6 @@ export default createFragmentContainer( } `, ); - ``` ## Container Composition @@ -176,7 +164,6 @@ Let's explore how this works via a `` component that composes the `< View composition is _exactly_ what you're used to — Relay containers are just standard React components. Here's the `` component: ```javascript - class TodoList extends React.Component { render() { // Expects a `list` with a string `title`, as well as the information @@ -191,7 +178,6 @@ class TodoList extends React.Component { ); } } - ``` ### Composing Fragments @@ -199,7 +185,6 @@ class TodoList extends React.Component { Fragment composition works similarly — a parent container's fragment composes the fragment for each of its children. In this case, `` needs to fetch information about the `Todo`s that are required by ``. ```javascript - class TodoList extends React.Component // as above export default createFragmentContainer( @@ -217,7 +202,6 @@ export default createFragmentContainer( } `, ); - ``` Note that when composing fragments, the type of the composed fragment must match the field on the parent in which it is embedded. For example, it wouldn't make sense to embed a fragment of type `Story` into a parent's field of type `User`. Relay and GraphQL will provide helpful error messages if you get this wrong (and if they aren't helpful, let us know!). @@ -231,7 +215,6 @@ When defining a fragment, you can use the [`@argumentDefinitions`](./graphql-in- For example, let's redefine our `TodoList_list` fragment to take some arguments using `@argumentDefinitions`: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -241,7 +224,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` Any arguments defined inside `@argumentDefinitions` will be local variables available inside the fragment's scope. However, a fragment can also reference global variables that were defined in the root query. @@ -253,11 +235,9 @@ In order to pass arguments to a fragment that has `@argumentDefinitions`, you ne Following our `TodoList_list` example, we would pass arguments to the fragment like so: ```graphql - query TodoListQuery($count: Int, $userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` ### Calling Component Instance Methods @@ -268,7 +248,6 @@ Since Relay composes these component instances in a container, you need to use t Consider an input with a server-defined placeholder text and an imperative method to focus the input node: ```javascript - export default createFragmentContainer( class TodoInput extends React.Component { focus() { @@ -288,13 +267,11 @@ export default createFragmentContainer( } `, ); - ``` To call this method on the underlying component, first provide a `componentRef` function to the Relay container. This differs from providing a [`ref`](https://facebook.github.io/react/docs/refs-and-the-dom.html) function which would provide a reference to the Relay container itself, not the underlying React Component. ```javascript - export default createFragmentContainer( class TodoListView extends React.Component { render() { @@ -312,7 +289,6 @@ export default createFragmentContainer( } `, ); - ``` ## Rendering Containers diff --git a/website/versioned_docs/version-v1.5.0/Modern-GraphQLInRelay.md b/website/versioned_docs/version-v1.5.0/Modern-GraphQLInRelay.md index 45ed05dc9670e..7cb555b6ce502 100644 --- a/website/versioned_docs/version-v1.5.0/Modern-GraphQLInRelay.md +++ b/website/versioned_docs/version-v1.5.0/Modern-GraphQLInRelay.md @@ -14,7 +14,6 @@ Table of Contents: The `graphql` template tag provided by Relay serves as the mechanism to write queries, fragments, mutations or subscriptions in the [GraphQL](http://graphql.org/learn/) language. For example: ```javascript - import {graphql} from 'react-relay'; graphql` @@ -24,7 +23,6 @@ graphql` } } `; - ``` The result of using the `graphql` template tag are `GraphQLTaggedNode`s, which are used to define [Query Renderers](./query-renderer), [Fragment Containers](./fragment-container), [Refetch Containers](./refetch-container), [Pagination Containers](./pagination-container), etc. @@ -42,11 +40,9 @@ Relay uses directives to add additional information to GraphQL documents, which `@arguments` is a directive used to pass arguments to a fragment that was defined using [`@argumentDefinitions`](#argumentdefinitions). For example: ```graphql - query TodoListQuery($userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` See [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -56,7 +52,6 @@ See [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragme `@argumentDefinitions` is a directive used to specify arguments taken by a fragment. For example: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -66,7 +61,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` See [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -82,13 +76,11 @@ When using the [Pagination Container](./pagination-container), Relay expects con When defining a fragment, you can use the `@relay(plural: true)` directive to indicate that the fragment is backed by a [GraphQL list](http://graphql.org/learn/schema/#lists-and-non-null), meaning that it will inform Relay that this particular field is an array. For example: ```javascript - graphql` fragment TodoItems_items on TodoItem @relay(plural: true) { id text }`; - ``` ### `@relay(mask: Boolean)` @@ -104,7 +96,6 @@ Keep in mind that it is typically considered an **anti-pattern** to create a sin In the example below, the `user` prop will include the data for `id` and `name` fields wherever `...Component_internUser` is included, instead of Relay's normal behavior to mask those fields: ```javascript - graphql` fragment Component_internUser on InternUser { id @@ -132,7 +123,6 @@ export default createFragmentContainer( } `, ); - ``` ## Relay Compiler @@ -142,7 +132,6 @@ Relay uses the Relay Compiler to convert [`graphql`](#graphql) literals into gen A query like the following: ```javascript - graphql` fragment MyComponent on Type { field @@ -166,7 +155,6 @@ See our relay-compiler section in our [Installation and Setup guide](./installat To use the Relay Compiler, you need either a .graphql or .json GraphQL schema file, describing your GraphQL server's API. Typically these files are local representations of a server source of truth and are not edited directly. For example, we might have a `schema.graphql` like: ```graphql - schema { query: Root } @@ -184,7 +172,6 @@ type WordDefinition { text: String image: String } - ``` ### Source files @@ -200,7 +187,6 @@ For example, given the two files: - `src/Components/DictionaryComponent.js` ```javascript - const DictionaryWordFragment = graphql` fragment DictionaryComponent_word on Word { id @@ -222,7 +208,6 @@ For example, given the two files: - `src/Queries/DictionaryQuery.js` ```javascript - const DictionaryQuery = graphql` query DictionaryQuery { dictionary { @@ -246,9 +231,7 @@ Typically you will not need to import your generated definitions. The [Relay Bab However the Relay Compiler also automatically generates [Flow](https://flow.org) types as [type comments](https://flow.org/en/docs/types/comments/). For example, you can import the generated flow types like so: ```javascript - import type {DictionaryComponent_word} from './__generated__/DictionaryComponent_word.graphql'; - ``` ### Advanced usage diff --git a/website/versioned_docs/version-v1.5.0/Modern-LocalStateManagement.md b/website/versioned_docs/version-v1.5.0/Modern-LocalStateManagement.md index f3427f392a611..dc50079ca5fbe 100644 --- a/website/versioned_docs/version-v1.5.0/Modern-LocalStateManagement.md +++ b/website/versioned_docs/version-v1.5.0/Modern-LocalStateManagement.md @@ -23,23 +23,19 @@ It can even be used to extend an existing server schema. For example, we can create a new type called `Note`: ```graphql - type Note { id: ID! title: String body: String } - ``` And then extend the server schema type `User`, with a list of `Note`, called `notes`. ```graphql - extend type User { notes: [Note] } - ``` ## Querying local state @@ -50,7 +46,6 @@ The field can be from the server schema, or it can be schema agnostic, like an i Here, we use a [QueryRenderer](./query-renderer) to get the current `User` via the `viewer` field, along with their id, name and the local list of notes. ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -96,7 +91,6 @@ const Example = (props) => { /> ); } - ``` ## Mutating local state @@ -110,7 +104,6 @@ To build upon the previous example, let's try creating, updating and deleting a ### Create ```javascript - import {commitLocalUpdate} from 'react-relay'; let tempID = 0; @@ -130,7 +123,6 @@ function createUserNote() { user.setLinkedRecords([...userNoteRecords, newNoteRecord], 'notes'); }); } - ``` Note that since this record will be rendered by the `ExampleQuery` in our `QueryRenderer`, the QueryRenderer will automatically retain this data so it isn't garbage collected. @@ -138,7 +130,6 @@ Note that since this record will be rendered by the `ExampleQuery` in our `Query If no component is rendering the local data and you want to manually retain it, you can do so by calling `environment.retain()`: ```javascript - import {createOperationDescriptor, getRequest} from 'relay-runtime'; // Create a query that references that record @@ -165,13 +156,11 @@ const disposable = environment.retain(operation); // Whenever you don't need that data anymore and it's okay for Relay to garbage collect it, // you can dispose of the retain disposable.dispose(); - ``` ### Update ```javascript - import {commitLocalUpdate} from 'react-relay'; function updateUserNote(dataID, body, title) { @@ -182,13 +171,11 @@ function updateUserNote(dataID, body, title) { note.setValue(title, 'title') }); } - ``` ### Delete ```javascript - import {commitLocalUpdate} from 'react-relay'; function deleteUserNote(dataID) { @@ -206,7 +193,6 @@ function deleteUserNote(dataID) { user.setLinkedRecords(newUserNoteRecords, 'notes'); }); } - ``` ## Initial local state @@ -215,7 +201,6 @@ All new client-side schema fields default to `undefined` value. Often however, y You can use an updater function via `commitLocalUpdate` to prime local state. ```javascript - import {commitLocalUpdate} from 'react-relay'; commitLocalUpdate(environment, store => { @@ -224,5 +209,4 @@ commitLocalUpdate(environment, store => { // initialize user notes to an empty array. user.setLinkedRecords([], 'notes'); }); - ``` diff --git a/website/versioned_docs/version-v1.5.0/Modern-MigrationSetup.md b/website/versioned_docs/version-v1.5.0/Modern-MigrationSetup.md index 66f1145357e25..a89c0e178e0e5 100644 --- a/website/versioned_docs/version-v1.5.0/Modern-MigrationSetup.md +++ b/website/versioned_docs/version-v1.5.0/Modern-MigrationSetup.md @@ -13,13 +13,11 @@ With some additional configuration, the `"relay"` babel plugin can also translat Relay Classic `Relay.QL` literals. Most importantly, include a reference to your GraphQL Schema as either a json file or graphql schema file. ```javascript - { "plugins": [ ["relay", {"schema": "path/schema.graphql"}] ] } - ``` ## Set up babel-plugin-relay for "[compatibility mode](./relay-compat)" @@ -29,13 +27,11 @@ literals can be translated to be usable by _both_ runtimes if configured to use compatibility mode: ```javascript - { "plugins": [ ["relay", {"compat": true, "schema": "path/schema.graphql"}] ] } - ``` ## Additional Options @@ -47,7 +43,6 @@ thrown at runtime. When compiling code for production deployment, the plugin can be configured to immediately throw upon encountering a validation problem. The plugin can be further customized for different environments with the following options: ```javascript - { "plugins": [ ["relay", { @@ -56,5 +51,4 @@ When compiling code for production deployment, the plugin can be configured to i }] ] } - ``` diff --git a/website/versioned_docs/version-v1.5.0/Modern-Mutations.md b/website/versioned_docs/version-v1.5.0/Modern-Mutations.md index d879216bdd5e3..ebb1797237203 100644 --- a/website/versioned_docs/version-v1.5.0/Modern-Mutations.md +++ b/website/versioned_docs/version-v1.5.0/Modern-Mutations.md @@ -16,7 +16,6 @@ Table of Contents: Use `commitMutation` to create and execute mutations. `commitMutation` has the following signature: ```javascript - commitMutation( environment: Environment, config: { @@ -30,7 +29,6 @@ commitMutation( configs?: Array, }, ); - ``` ### Arguments @@ -57,7 +55,6 @@ commitMutation( Example of a simple mutation: ```javascript - import {commitMutation, graphql} from 'react-relay'; const mutation = graphql` @@ -92,7 +89,6 @@ function markNotificationAsRead(environment, source, storyID) { }, ); } - ``` ## Optimistic Updates @@ -100,7 +96,6 @@ function markNotificationAsRead(environment, source, storyID) { To improve perceived responsiveness, you may wish to perform an "optimistic update", in which the client immediately updates to reflect the anticipated new value even before the response from the server has come back. The simplest way to do this is by providing an `optimisticResponse` and adding it to the `config` that we pass into `commitMutation`: ```javascript - const mutation = graphql` mutation MarkReadNotificationMutation( $input: MarkReadNotificationData! @@ -129,7 +124,6 @@ commitMutation( variables, }, ); - ``` Another way to enable optimistic updates is via the `optimisticUpdater`, which can be used for more complicated update scenarios. Using `optimisticUpdater` is covered in the section [below](#using-updater-and-optimisticupdater). @@ -149,7 +143,6 @@ Given a deletedIDFieldName, Relay will remove the node(s) from the connection. #### Example ```javascript - const mutation = graphql` mutation DestroyShipMutation($input: DestroyShipData!) { destroyShip(input: $input) { @@ -167,7 +160,6 @@ const configs = [{ type: 'NODE_DELETE', deletedIDFieldName: 'destroyedShipId', }]; - ``` ### RANGE_ADD @@ -187,7 +179,6 @@ Given a parent, information about the connection, and the name of the newly crea #### Example ```javascript - const mutation = graphql` mutation AddShipMutation($input: AddShipData!) { addShip(input: $input) { @@ -210,7 +201,6 @@ const configs = [{ }], edgeName: 'newShipEdge', }]; - ``` ### RANGE_DELETE @@ -232,7 +222,6 @@ from the connection but leave the associated record(s) in the store. #### Example ```javascript - const mutation = graphql` mutation RemoveTagsMutation($input: RemoveTagsData!) { removeTags(input: $input) { @@ -255,7 +244,6 @@ const configs = [{ pathToConnection: ['todo', 'tags'], deletedIDFieldName: removedTagId }]; - ``` ## Using updater and optimisticUpdater @@ -273,7 +261,6 @@ When you provide these functions, this is roughly what happens during the mutati Here are a quick example of adding a todo item to a Todo list using this [example schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L36): ```javascript - // AddTodoMutation.js import {commitMutation, graphql} from 'react-relay'; import {ConnectionHandler} from 'relay-runtime'; @@ -365,7 +352,6 @@ function commit( } ); } - ``` For details on how to interact with the Relay Store, please refer to our Relay Store [docs](./relay-store). diff --git a/website/versioned_docs/version-v1.5.0/Modern-NetworkLayer.md b/website/versioned_docs/version-v1.5.0/Modern-NetworkLayer.md index c5813a18609e8..e0d5a012a0ecf 100644 --- a/website/versioned_docs/version-v1.5.0/Modern-NetworkLayer.md +++ b/website/versioned_docs/version-v1.5.0/Modern-NetworkLayer.md @@ -8,7 +8,6 @@ In order to know how to access your GraphQL server, Relay Modern requires develo Currently the easiest way to create a network layer is via a helper from the `relay-runtime` package: ```javascript - const {Environment, Network} = require('relay-runtime'); // Define a function that fetches the results of an operation (query/mutation/etc) @@ -42,7 +41,6 @@ const environment = new Environment({ ..., // other options network, }); - ``` Note that this is a basic example to help you get started. This example could be extended with additional features such as request/response caching (enabled e.g. when `cacheConfig.force` is false) and uploading form data for mutations (the `uploadables` parameter). diff --git a/website/versioned_docs/version-v1.5.0/Modern-PaginationContainer.md b/website/versioned_docs/version-v1.5.0/Modern-PaginationContainer.md index 8a9ee1c315691..7cd45d706b42d 100644 --- a/website/versioned_docs/version-v1.5.0/Modern-PaginationContainer.md +++ b/website/versioned_docs/version-v1.5.0/Modern-PaginationContainer.md @@ -24,7 +24,6 @@ However, when [specifying connection fragments](#createpaginationcontainer) for The purpose of the `@connection` directive is to allow Relay to uniquely identify different connections under a parent type. The `@connection` directive takes 2 arguments that help identify the connection: ```graphql - @connection(key: String!, filters: [String]) ``` @@ -37,7 +36,6 @@ The purpose of the `@connection` directive is to allow Relay to uniquely identif Specifying just the `key`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and the value of `$orderBy` (given that no `filters` were provided) @@ -53,13 +51,11 @@ fragment Feed_user on User { } } } - ``` Specifying `key` and `filters`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and /only/ the value of `$searchTerm`, i.e. @@ -77,7 +73,6 @@ fragment Feed_user on User { } } } - ``` ## `createPaginationContainer` @@ -85,7 +80,6 @@ fragment Feed_user on User { `createPaginationContainer` has the following signature: ```javascript - createPaginationContainer( component: ReactComponentClass, fragmentSpec: GraphQLTaggedNode | {[string]: GraphQLTaggedNode}, @@ -113,7 +107,6 @@ type ConnectionData = { startCursor: ?string, }, }; - ``` ### Arguments @@ -137,7 +130,6 @@ type ConnectionData = { The Component resulting from `createPaginationContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -148,7 +140,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -163,7 +154,6 @@ type Props = { `hasMore` is a function available on the `relay` [prop](#available-props). This function indicates wether there are more pages to fetch from the server or not. ```javascript - hasMore: () => boolean, ``` @@ -173,7 +163,6 @@ hasMore: () => boolean, `isLoading` is a function available on the `relay` [prop](#available-props). This function indicates if a previous call to [`loadMore()`](#loadmore) is still pending. This is convenient for avoiding duplicate load calls. ```javascript - isLoading: () => boolean, ``` @@ -183,7 +172,6 @@ isLoading: () => boolean, `loadMore` is a function available on the `relay` [prop](#available-props). You can call `loadMore()` to fetch more items from the server based on the `connectionConfig` provided to the container. This will return null if there are no more items to fetch, otherwise it will fetch more items and return a Disposable that can be used to cancel the fetch. ```javascript - loadMore(pageSize: number, callback: ?(error: ?Error) => void): ?Disposable ``` @@ -198,7 +186,6 @@ loadMore(pageSize: number, callback: ?(error: ?Error) => void): ?Disposable `refetchConnection` is a function available on the `relay` [prop](#available-props). You can call `refetchConnection` to restart pagination on a connection from scratch, with optionally a completely new set of variables to pass to the pagination `query`. This is useful for example if you are paginating over a collection based on a userID and the userID changes, you'd want to start paginating over the new collection for the new user. ```javascript - refetchConnection:( count: number, callback: (error: ?Error) => void, @@ -216,7 +203,6 @@ refetchConnection:( ## Pagination Example ```javascript - // Feed.js import {createPaginationContainer, graphql} from 'react-relay'; @@ -311,5 +297,4 @@ module.exports = createPaginationContainer( ` } ); - ``` diff --git a/website/versioned_docs/version-v1.5.0/Modern-PersistedQueries.md b/website/versioned_docs/version-v1.5.0/Modern-PersistedQueries.md index 74b5c3c5d13c6..aadc6710f63bb 100644 --- a/website/versioned_docs/version-v1.5.0/Modern-PersistedQueries.md +++ b/website/versioned_docs/version-v1.5.0/Modern-PersistedQueries.md @@ -16,12 +16,10 @@ The relay compiler supports persisted queries which is useful because: In your `npm` script in `package.json`, run the relay compiler using the `--persist-output` flag: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` The `--persist-ouput` flag does 2 things: @@ -30,8 +28,7 @@ The `--persist-ouput` flag does 2 things: For example without `--persist-output`, a generated `ConcreteRequest` might look like below: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -48,8 +45,7 @@ The `--persist-ouput` flag does 2 things: With `--persist-output ` this becomes: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -67,12 +63,10 @@ The `--persist-ouput` flag does 2 things: 2. It generates a JSON file at the `` you specify containing a mapping from query ids to the corresponding operation texts. -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./src/queryMaps/queryMap.json" } - ``` The example above writes the complete query map file to `./src/queryMaps/queryMap.json`. You need to ensure all the directories @@ -82,8 +76,7 @@ leading to the `queryMap.json` file exist. You'll need to modify your network layer fetch implementation to pass a documentId parameter in the POST body instead of a query parameter: -```js - +```javascript function fetchQuery(operation, variables,) { return fetch('/graphql', { method: 'POST', @@ -99,7 +92,6 @@ function fetchQuery(operation, variables,) { return response.json(); }); } - ``` ## Executing Persisted Queries on the Server @@ -115,13 +107,11 @@ the query map file in a common location accessible to both the client and the se For applications where the client and server projects are separate, one option is to have an additional npm run script to push the query map at compile time to a location accessible by your server: -```js - +```javascript "scripts": { "push-queries": "node ./pushQueries.js", "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-ouput && npm run push-queries" } - ``` Some possibilities of what you can do in `./pushQueries.js`: @@ -145,8 +135,7 @@ database technologies you use, so we'll just cover the most common and basic exa If you use `express-graphql` and have access to the query map file, you can import the `--persist-output` JSON file directly and perform the matching using the `matchQueryMiddleware` from [relay-compiler-plus](https://github.com/yusinto/relay-compiler-plus). -```js - +```javascript import Express from 'express'; import expressGraphql from 'express-graphql'; import {matchQueryMiddleware} from 'relay-compiler-plus'; @@ -157,7 +146,6 @@ const app = Express(); app.use('/graphql', matchQueryMiddleware(queryMapJson), expressGraphql({schema})); - ``` ## Using `--persist-output` and `--watch` diff --git a/website/versioned_docs/version-v1.5.0/Modern-QueryRenderer.md b/website/versioned_docs/version-v1.5.0/Modern-QueryRenderer.md index 5b5fc9c90a237..6914b030ccd25 100644 --- a/website/versioned_docs/version-v1.5.0/Modern-QueryRenderer.md +++ b/website/versioned_docs/version-v1.5.0/Modern-QueryRenderer.md @@ -21,7 +21,6 @@ However, a `QueryRenderer` will not start loading its data until it is mounted, ## Example ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -53,5 +52,4 @@ class Example extends React.Component { ); } } - ``` diff --git a/website/versioned_docs/version-v1.5.0/Modern-RefetchContainer.md b/website/versioned_docs/version-v1.5.0/Modern-RefetchContainer.md index 25839f6aed901..416e049a71403 100644 --- a/website/versioned_docs/version-v1.5.0/Modern-RefetchContainer.md +++ b/website/versioned_docs/version-v1.5.0/Modern-RefetchContainer.md @@ -16,13 +16,11 @@ Table of Contents: `createRefetchContainer` has the following signature: ```javascript - createRefetchContainer( component: ReactComponentClass, fragmentSpec: GraphQLTaggedNode | {[string]: GraphQLTaggedNode}, refetchQuery: GraphQLTaggedNode, ): ReactComponentClass; - ``` ### Arguments @@ -40,7 +38,6 @@ createRefetchContainer( The Component resulting from `createRefetchContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -48,7 +45,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -64,7 +60,6 @@ type Props = { `refetch` has the following signature: ```javascript - type RefetchOptions = { force?: boolean, }; @@ -104,7 +99,6 @@ Returns a `Disposable` on which you could call `dispose()` to cancel the refetch In this simple example, let's assume we want to fetch the latest data for a `TodoItem` from the server: ```javascript - // TodoItem.js import {createRefetchContainer, graphql} from 'react-relay'; @@ -148,7 +142,6 @@ export default createRefetchContainer( } ` ); - ``` ### Loading more data @@ -156,7 +149,6 @@ export default createRefetchContainer( In this example we are using a Refetch Container to fetch more stories in a story feed component. ```javascript - import {createRefetchContainer, graphql} from 'react-relay'; class FeedStories extends React.Component { @@ -212,5 +204,4 @@ export default createRefetchContainer( } `, ); - ``` diff --git a/website/versioned_docs/version-v1.5.0/Modern-RelayCompat.md b/website/versioned_docs/version-v1.5.0/Modern-RelayCompat.md index 36632d3a8f1a1..f47dbd845ba3e 100644 --- a/website/versioned_docs/version-v1.5.0/Modern-RelayCompat.md +++ b/website/versioned_docs/version-v1.5.0/Modern-RelayCompat.md @@ -31,7 +31,6 @@ Relay Modern. The components using Relay Compat can be referred to by both other Relay Modern and Relay Classic components. ```javascript - const {createFragmentContainer, graphql} = require('react-relay/compat'); class TodoItem extends React.Component { @@ -47,5 +46,4 @@ module.exports = createFragmentContainer(TodoItem, graphql` isComplete } `); - ``` diff --git a/website/versioned_docs/version-v1.5.0/Modern-RelayEnvironment.md b/website/versioned_docs/version-v1.5.0/Modern-RelayEnvironment.md index b356b5deecdc5..ed75bc69d1f86 100644 --- a/website/versioned_docs/version-v1.5.0/Modern-RelayEnvironment.md +++ b/website/versioned_docs/version-v1.5.0/Modern-RelayEnvironment.md @@ -12,7 +12,6 @@ Most applications will create a single Environment instance and use it throughou To create an environment instance in Relay Modern, use the `RelayModernEnvironment` class: ```javascript - const { Environment, Network, @@ -30,7 +29,6 @@ const environment = new Environment({ network, store, }); - ``` For more details on creating a Network, see the [NetworkLayer guide](./network-layer). @@ -44,7 +42,6 @@ The example above did not configure a `handlerProvider`, which means that a defa If you wish to provide your own `handlerProvider`, you can do so: ```javascript - const { ConnectionHandler, ViewerHandler, @@ -60,5 +57,4 @@ function handlerProvider(handle) { `handlerProvider: No handler provided for ${handle}` ); } - ``` diff --git a/website/versioned_docs/version-v1.5.0/Modern-RelayStore.md b/website/versioned_docs/version-v1.5.0/Modern-RelayStore.md index 91845846694f4..e8e2df3d9efcf 100644 --- a/website/versioned_docs/version-v1.5.0/Modern-RelayStore.md +++ b/website/versioned_docs/version-v1.5.0/Modern-RelayStore.md @@ -16,7 +16,6 @@ Table of Contents: The `RecordSourceSelectorProxy` is the type of the `store` that [`updater` functions](./mutations#using-updater-and-optimisticupdater) receive as an argument. The following is the `RecordSourceSelectorProxy` interface: ```javascript - interface RecordSourceSelectorProxy { create(dataID: string, typeName: string): RecordProxy; delete(dataID: string): void; @@ -25,7 +24,6 @@ interface RecordSourceSelectorProxy { getRootField(fieldName: string): ?RecordProxy; getPluralRootField(fieldName: string): ?Array; } - ``` ### `create(dataID: string, typeName: string): RecordProxy` @@ -35,9 +33,7 @@ Creates a new record in the store given a `dataID` and the `typeName` as defined #### Example ```javascript - const record = store.create(dataID, 'Todo'); - ``` ### `delete(dataID: string): void` @@ -47,9 +43,7 @@ Deletes a record from the store given its `dataID`. #### Example ```javascript - store.delete(dataID); - ``` ### `get(dataID: string): ?RecordProxy` @@ -59,9 +53,7 @@ Retrieves a record from the store given its `dataID`. Returns a [`RecordProxy`]( #### Example ```javascript - const record = store.get(dataID); - ``` ### `getRoot(): RecordProxy` @@ -73,20 +65,16 @@ Returns the [`RecordProxy`](#recordproxy) representing the root of the GraphQL d Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - // Represents root query const root = store.getRoot(); - ``` ### `getRootField(fieldName: string): ?RecordProxy` @@ -98,19 +86,15 @@ Retrieves a root field from the store given the `fieldName`, as defined by the G Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - const viewer = store.getRootField('viewer'); - ``` ### `getPluralRootField(fieldName: string): ?Array` @@ -122,19 +106,15 @@ Retrieves a root field that represents a collection from the store given the `fi Given the GraphQL document: ```graphql - nodes(first: 10) { # ... } - ``` Usage: ```javascript - const nodes = store.getPluralRootField('nodes'); - ``` ## RecordProxy @@ -142,7 +122,6 @@ const nodes = store.getPluralRootField('nodes'); The `RecordProxy` serves as an interface to mutate records: ```javascript - interface RecordProxy { copyFieldsFrom(sourceRecord: RecordProxy): void; getDataID(): string; @@ -167,7 +146,6 @@ interface RecordProxy { ): RecordProxy; setValue(value: mixed, name: string, arguments?: ?Object): RecordProxy; } - ``` ### `getDataID(): string` @@ -177,9 +155,7 @@ Returns the dataID of the current record. #### Example ```javascript - const id = record.getDataID(); - ``` ### `getType(): string` @@ -189,7 +165,6 @@ Gets the type of the current record, as defined by the GraphQL schema. #### Example ```javascript - const type = user.getType(); // User ``` @@ -203,20 +178,16 @@ Gets the value of a field in the current record given the field name. Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - const name = viewer.getValue('name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. @@ -226,20 +197,16 @@ Optionally, if the field takes arguments, you can pass a bag of `variables`. Given the GraphQL document: ```graphql - viewer { id name(arg: $arg) } - ``` Usage: ```javascript - const name = viewer.getValue('name', {arg: 'value'}); - ``` ### `getLinkedRecord(name: string, arguments?: ?Object): ?RecordProxy` @@ -251,23 +218,19 @@ Retrieves the a record associated with the current record given the field name, Given the GraphQL document: ```graphql - rootField { viewer { id name } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -277,22 +240,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { viewer(arg: $arg) { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {arg: 'value'}); - ``` ### `getLinkedRecords(name: string, arguments?: ?Object): ?Array` @@ -304,22 +263,18 @@ Retrieves the set of records associated with the current record given the field Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const nodes = rootField.getLinkedRecord('nodes'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -329,22 +284,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { nodes(first: $count) { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {count: 10}); - ``` ### `getOrCreateLinkedRecord(name: string, typeName: string, arguments?: ?Object)` @@ -356,19 +307,16 @@ Retrieves the a record associated with the current record given the field name, Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = rootField.getOrCreateLinkedRecord('viewer', 'User'); // Will create if it doesn't exist @@ -383,28 +331,22 @@ Mutates the current record by setting a new value on the specified field. Return Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - viewer.setValue('New Name', 'name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. ```javascript - viewer.setValue('New Name', 'name', {arg: 'value'}); - ``` ### `copyFieldsFrom(sourceRecord: RecordProxy): void` @@ -414,7 +356,6 @@ Mutates the current record by copying the fields over from the passed in record #### Example ```javascript - const record = store.get(id1); const otherRecord = store.get(id2); record.copyFieldsFrom(otherRecord); // Mutates `record` @@ -430,19 +371,16 @@ Mutates the current record by setting a new linked record on the given the field Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = store.create(/* ... */)'' rootField.setLinkedRecord(newViewer, 'viewer'); // @@ -460,19 +398,16 @@ Mutates the current record by setting a new set of linked records on the given t Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newNode = store.create(/* ... */); const newNodes = [...rootField.getLinkedRecords('nodes'), newNode]; @@ -487,7 +422,6 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl `ConnectionHandler` is a utility module exposed by `relay-runtime` that aids in the manipulation of connections. `ConnectionHandler` exposes the following interface: ```javascript - interface ConnectionHandler { getConnection( record: RecordProxy, @@ -512,7 +446,6 @@ interface ConnectionHandler { ): void, deleteNode(connection: RecordProxy, nodeID: string): void } - ``` ### `getConnection(record: RecordProxy, key: string, filters?: ?Object)` @@ -522,7 +455,6 @@ Given a record and a connection key, and optionally a set of filters, `getConnec First, let's take a look at a plain connection: ```graphql - fragment FriendsFragment on User { friends(first: 10) { edges { @@ -532,26 +464,22 @@ fragment FriendsFragment on User { } } } - ``` Accessing a plain connection field like this is the same as other regular field: ```javascript - // The `friends` connection record can be accessed with: const user = store.get(userID); const friends = user && user.getLinkedRecord(user, 'friends'); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` In a [pagination container](./pagination-container), we usually annotate the actual connection field with `@connection` to tell Relay which part needs to be paginated: ```graphql - fragment FriendsFragment on User { friends(first: 10, orderby: "firstname") @connection( key: "FriendsFragment_friends", @@ -563,7 +491,6 @@ fragment FriendsFragment on User { } } } - ``` For connections like the above, `ConnectionHandler` helps us find the record: @@ -581,7 +508,6 @@ const friends = ConnectionHandler.getConnection( ); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` ### Edge creation and insertion @@ -611,7 +537,6 @@ ConnectionHandler.insertEdgeAfter(friends, edge); // No cursor provided, Insert the edge at the front: ConnectionHandler.insertEdgeBefore(friends, edge); - ``` ### `deleteNode(connection: RecordProxy, nodeID: string): void` @@ -625,5 +550,4 @@ Given a connection, deletes any edges whose id matches the given id. const user = store.get(userID); const friends = ConnectionHandler.getConnection(user, 'friends'); ConnectionHandler.deleteNode(friends, idToDelete); - ``` diff --git a/website/versioned_docs/version-v1.5.0/Modern-Subscriptions.md b/website/versioned_docs/version-v1.5.0/Modern-Subscriptions.md index a02a27933c40a..c4e9b324730f0 100644 --- a/website/versioned_docs/version-v1.5.0/Modern-Subscriptions.md +++ b/website/versioned_docs/version-v1.5.0/Modern-Subscriptions.md @@ -6,7 +6,6 @@ original_id: subscriptions Relay exposes the following APIs to create subscriptions. ```javascript - const {requestSubscription} = require('react-relay'); type Variables = {[name: string]: any}; @@ -23,7 +22,6 @@ requestSubscription( configs?: Array, }, ); - ``` Now let's take a closer look at the `config`: @@ -47,7 +45,6 @@ appropriate when you are only changing the properties of existing records that can be identified by their `id`: ```javascript - const { requestSubscription, graphql, @@ -81,7 +78,6 @@ requestSubscription( onError: error => console.error(error), } ); - ``` # Updating the client on each response @@ -91,7 +87,6 @@ Relay's in-memory cache when each subscription response is received. To do so, pass an `updater` function: ```javascript - const {ConnectionHandler} = require('relay-runtime'); requestSubscription( @@ -117,5 +112,4 @@ requestSubscription( }, }, ); - ``` diff --git a/website/versioned_docs/version-v1.5.0/Modern-TestingRelayComponents.md b/website/versioned_docs/version-v1.5.0/Modern-TestingRelayComponents.md index f30317b146e96..eaa443bd20147 100644 --- a/website/versioned_docs/version-v1.5.0/Modern-TestingRelayComponents.md +++ b/website/versioned_docs/version-v1.5.0/Modern-TestingRelayComponents.md @@ -64,7 +64,6 @@ With the `MockPayloadGenerator` and `@relay_test_operation`, we want to get rid Example of a simple Mock Resolver: ```javascript - { ID() { // Return mock value for a scalar filed with type ID @@ -75,13 +74,11 @@ Example of a simple Mock Resolver: return "Lorem Ipsum" } } - ``` It is possible to define more resolvers for Object types: ```javascript - { // This will be the default values for User object in the query response User() { @@ -94,7 +91,6 @@ It is possible to define more resolvers for Object types: }; }, } - ``` ### Mock Resolver Context @@ -102,7 +98,6 @@ It is possible to define more resolvers for Object types: The first argument of the MockResolver is the object that contains Mock Resolver Context. It is possible to return dynamic values from mock resolvers based on the context - for instance, name or alias of the field, a path in the selection, arguments, or parent type. ```javascript - { String(context) { if (context.name === 'zip') { @@ -116,7 +111,6 @@ The first argument of the MockResolver is the object that contains Mock Resolver } } } - ``` ### ID Generation @@ -124,14 +118,12 @@ The first argument of the MockResolver is the object that contains Mock Resolver The second argument of the Mock Resolver its a function that will generate a sequence of integers, useful to generate unique IDs in the tests: ```javascript - { // will generate strings "my-id-1", "my-id-2", etc. ID(_, generateId) { return `my-id-${generateId()}`; }, } - ``` ### `@relay_test_operation` @@ -141,7 +133,6 @@ Most of GraphQL type information for a specific field in the selection is not av Operations with the `@relay_test_operation` directive will have additional metadata that will contain GraphQL type info for fields in the operation's selection. And it will improve the quality of the generated data. You also will be able to define Mock resolvers for Scalar (not only ID and String) and Abstract types: ```javascript - { Float() { return 123.456; @@ -159,7 +150,6 @@ Operations with the `@relay_test_operation` directive will have additional metad }; } } - ``` ## Examples @@ -169,7 +159,6 @@ Operations with the `@relay_test_operation` directive will have additional metad Using `createMockEnvironment` and `MockPayloadGenerator` allows writing concise tests for components that are using Relay Containers and Renderers. Both those modules can be imported from `relay-test-utils`. ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { @@ -222,7 +211,6 @@ test('Error State', () => { renderer.root.find(item => (item.props.testID = 'errorMessage')), ).toBeDefined(); }); - ``` ### Fragment Container Tests @@ -230,7 +218,6 @@ test('Error State', () => { Essentially, in the example above, `resolveMostRecentOperation` will generate data for all child fragment containers (pagination, refetch). Usually, the Root Components container may have many child fragment components and you may want to exercise a specific Fragment Container. The solution for that would be to wrap your fragment container with the QueryRenderer that renders a Query that's spreads fragments from your fragment container. ```javascript - test('Fragment Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -261,7 +248,6 @@ test('Fragment Container', () => { expect(renderer).toMatchSnapshot(); }); - ``` ### Pagination Container Test @@ -269,7 +255,6 @@ test('Fragment Container', () => { Essentially, tests for Pagination container are not different from Fragment Container tests. We can also do more here. We can actually see how the pagination works by asserting the behavior of our components when performing pagination (load more, refetch). ```javascript - // Pagination Example test('Pagination Container', () => { const environment = createMockEnvironment(); @@ -343,7 +328,6 @@ test('Pagination Container', () => { We can use similar approach here with wrapping container with Query Renderer. And for the sake of completeness, we will add example here: ```javascript - test('Refetch Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -385,7 +369,6 @@ test('Refetch Container', () => { ); // expect(renderer).toMatchSnapshot(); }); - ``` ### Mutations @@ -393,7 +376,6 @@ test('Refetch Container', () => { Mutations itself are operations so we can test them independently (unit-test) for specific mutation, or in combination with the view from which this mutation is called. ```javascript - // Say, you have a mutation function function sendMutation(environment, onCompleted, onError, variables) commitMutation(environment, { @@ -416,7 +398,6 @@ test('it should send mutation', () => { ); expect(onCompleted).toBeCalled(); }); - ``` ### Subscription @@ -424,7 +405,6 @@ test('it should send mutation', () => { We can test subscription in a similar way we test mutations ```javascript - // Example subscribe function function subscribe(environment, onNext, onError, variables) requestSubscription(environment, { @@ -447,7 +427,6 @@ test('it should subscribe', () => { ); expect(onNext).toBeCalled(); }); - ``` ### Example with `queueOperationResolver` @@ -455,7 +434,6 @@ test('it should subscribe', () => { With `queueOpeararionResolver`, it possible to define responses for operations that will be executed on the environment ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { diff --git a/website/versioned_docs/version-v1.5.0/Modern-TypeEmission.md b/website/versioned_docs/version-v1.5.0/Modern-TypeEmission.md index c25bc737d5684..9f41810a3618b 100644 --- a/website/versioned_docs/version-v1.5.0/Modern-TypeEmission.md +++ b/website/versioned_docs/version-v1.5.0/Modern-TypeEmission.md @@ -15,7 +15,6 @@ In this example the emitted type-information would require the variables object #### Flow ```javascript - /** * export type ExampleQueryVariables = {| * +artistID: string @@ -43,7 +42,6 @@ const variables: ExampleQueryVariables = { #### TypeScript ```javascript - /** * export type ExampleQueryVariables = { * readonly artistID: string @@ -78,7 +76,6 @@ In this example the emitted type-information describes the response data availab #### Flow ```javascript - /** * export type ExampleQueryResponse = {| * +artist: ?{| @@ -109,7 +106,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * export type ExampleQueryResponse = { * readonly artist?: { @@ -145,7 +141,6 @@ Similarly, in this example the emitted type-information describes the prop data #### Flow ```javascript - /** * export type ExampleFragment_artist = {| * +name: string @@ -171,7 +166,6 @@ export const ExampleFragment = createFragmentContainer( #### TypeScript ```javascript - /** * export type ExampleFragment_artist = { * readonly name: string @@ -205,7 +199,6 @@ Consider a component that composes the above fragment container example. In this #### Flow ```javascript - /** * import type { FragmentReference } from "relay-runtime"; * declare export opaque type ExampleFragment_artist$ref: FragmentReference; @@ -249,7 +242,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * declare const _ExampleFragment_artist$ref: unique symbol; * export type ExampleFragment_artist$ref = typeof _ExampleFragment_artist$ref; @@ -314,7 +306,6 @@ $ relay-compiler --artifactDirectory ./src/__generated__ […] ["relay", { "artifactDirectory": "./src/__generated__" }] ] } - ``` It is recommended to alias this directory in your module resolution configuration such that you don’t need to specify relative paths in your source files. This is what is also done in the above examples, where artifacts are imported from a `__generated__` alias, rather than relative paths like `../../../../__generated__`. diff --git a/website/versioned_docs/version-v1.5.0/Modern-UpgradingSetVariables.md b/website/versioned_docs/version-v1.5.0/Modern-UpgradingSetVariables.md index d5b086fafce20..ff73feec04f8b 100644 --- a/website/versioned_docs/version-v1.5.0/Modern-UpgradingSetVariables.md +++ b/website/versioned_docs/version-v1.5.0/Modern-UpgradingSetVariables.md @@ -36,7 +36,6 @@ fragment on User { # ... } } - ``` This should be upgraded to use a [`PaginationContainer`](./pagination-container). @@ -61,7 +60,6 @@ fragment on User { # ... } } - ``` This can be upgraded by using a [`RefetchContainer`](./refetch-container) which allows you to specify the exact query to use to fetch the new data. @@ -86,7 +84,6 @@ fragment on FeedbackTarget { # ... } } - ``` This can be upgraded by conditionally rendering a [`QueryRenderer`](./query-renderer) which will load the data once it is rendered. The code overhead of doing this is dramatically reduced with the new API. diff --git a/website/versioned_docs/version-v1.5.0/Modern-fetchQuery.md b/website/versioned_docs/version-v1.5.0/Modern-fetchQuery.md index 19e9b57c4219a..223c01ccc75c2 100644 --- a/website/versioned_docs/version-v1.5.0/Modern-fetchQuery.md +++ b/website/versioned_docs/version-v1.5.0/Modern-fetchQuery.md @@ -5,7 +5,6 @@ title: fetchQuery You can use the `fetchQuery` function to imperatively make GraphQL Requests. This is useful for cases where you want to make requests outside of React but still utilize the Relay store and network layer. ```javascript - import {fetchQuery, graphql} from 'relay-runtime'; const query = graphql` @@ -24,7 +23,6 @@ fetchQuery(environment, query, variables) .then(data => { // access the graphql response }); - ``` ## Arguments diff --git a/website/versioned_docs/version-v1.5.0/PrinciplesAndArchitecture-Compiler.md b/website/versioned_docs/version-v1.5.0/PrinciplesAndArchitecture-Compiler.md index c195491682b1f..fcd0490cb724f 100644 --- a/website/versioned_docs/version-v1.5.0/PrinciplesAndArchitecture-Compiler.md +++ b/website/versioned_docs/version-v1.5.0/PrinciplesAndArchitecture-Compiler.md @@ -74,7 +74,6 @@ foo { # type FooType foo { id } - ``` - `SkipRedundantNodeTransform`: A more advanced version of flattening, this eliminates more complex cases of field duplication such as when a field is fetched both unconditionally and conditionally, or is fetched by two different sub-fragments. For example: @@ -97,7 +96,6 @@ foo { id } } - ``` - `GenerateRequisiteFieldTransform`: This optional, Relay-specific transform inserts `id` fields for globally identifiable objects and `__typename` fields wherever the type cannot be statically determined (e.g. for unions). diff --git a/website/versioned_docs/version-v1.5.0/PrinciplesAndArchitecture-Runtime.md b/website/versioned_docs/version-v1.5.0/PrinciplesAndArchitecture-Runtime.md index f012908d090c5..e9c88a4b2ae0c 100644 --- a/website/versioned_docs/version-v1.5.0/PrinciplesAndArchitecture-Runtime.md +++ b/website/versioned_docs/version-v1.5.0/PrinciplesAndArchitecture-Runtime.md @@ -77,7 +77,6 @@ RecordSource { city: 'Seattle', } } - ``` [1] Note that GraphQL itself does not impose this constraint, and Relay Runtime may also be used for schemas that do not conform to it. For example, both systems can be used to query a single denormalized table. However, many of the features that Relay Runtime provides, such as caching and normalization, work best when the data is represented as a normalized graph with stable identities for discrete pieces of information. diff --git a/website/versioned_docs/version-v1.5.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md b/website/versioned_docs/version-v1.5.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md index 14b1119288f23..9527e65e8950e 100644 --- a/website/versioned_docs/version-v1.5.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md +++ b/website/versioned_docs/version-v1.5.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md @@ -12,7 +12,6 @@ In this article we'll explore what it means to build a GraphQL client framework Imagine we have a simple application that fetches a list of stories, and some details about each one. Here's how that might look in resource-oriented REST: ```javascript - // Fetch the list of story IDs but not their details: rest.get('/stories').then(stories => // This resolves to a list of items with linked resources: @@ -25,13 +24,11 @@ rest.get('/stories').then(stories => // `[ { id: "...", text: "..." } ]` console.log(stories); }); - ``` Note that this approach requires _n+1_ requests to the server: 1 to fetch the list, and _n_ to fetch each item. With GraphQL we can fetch the same data in a single network request to the server (without creating a custom endpoint that we'd then have to maintain): ```javascript - graphql.get(`query { stories { id, text } }`).then( stories => { // A list of story items: @@ -39,7 +36,6 @@ graphql.get(`query { stories { id, text } }`).then( console.log(stories); } ); - ``` So far we're just using GraphQL as a more efficient version of typical REST approaches. Note two important benefits in the GraphQL version: @@ -56,7 +52,6 @@ Repeatedly refetching information from the server can get quite slow. For exampl In a resource-oriented REST system, we can maintain a **response cache** based on URIs: ```javascript - var _cache = new Map(); rest.get = uri => { if (!_cache.has(uri)) { @@ -64,13 +59,11 @@ rest.get = uri => { } return _cache.get(uri); }; - ``` Response-caching can also be applied to GraphQL. A basic approach would work similarly to the REST version. The text of the query itself can be used as a cache key: ```javascript - var _cache = new Map(); graphql.get = queryText => { if (!_cache.has(queryText)) { @@ -78,7 +71,6 @@ graphql.get = queryText => { } return _cache.get(queryText); }; - ``` Now, requests for previously cached data can be answered immediately without making a network request. This is a practical approach to improving the perceived performance of an application. However, this method of caching can cause problems with data consistency. @@ -90,7 +82,6 @@ With GraphQL it is very common for the results of multiple queries to overlap. H ``` query { stories { id, text, likeCount } } - ``` and then later refetch one of the stories whose `likeCount` has since been incremented: @@ -98,7 +89,6 @@ and then later refetch one of the stories whose `likeCount` has since been incre ``` query { story(id: "123") { id, text, likeCount } } - ``` We'll now see different `likeCount`s depending on how the story is accessed. A view that uses the first query will see an outdated count, while a view using the second query will see the updated count. @@ -119,7 +109,6 @@ query { } } } - ``` And here's a possible response: @@ -134,13 +123,11 @@ query: { } } } - ``` Although the response is hierarchical, we'll cache it by flattening all the records. Here is an example of how Relay would cache this query response: ```javascript - Map { // `story(id: "1")` 1: Map { @@ -152,7 +139,6 @@ Map { name: 'Jan', }, }; - ``` This is only a simple example: in reality the cache must handle one-to-many associations and pagination (among other things). @@ -182,7 +168,6 @@ The first query was for a list of stories: ``` query { stories { id, text, likeCount } } - ``` With a normalized response cache, a record would be created for each story in the list. The `stories` field would store links to each of these records. @@ -192,7 +177,6 @@ The second query refetched the information for one of those stories: ``` query { story(id: "123") { id, text, likeCount } } - ``` When this response is normalized, Relay can detect that this result overlaps with existing data based on its `id`. Rather than create a new record, Relay will update the existing `123` record. The new `likeCount` is therefore available to _both_ queries, as well as any other query that might reference this story. @@ -215,7 +199,6 @@ query { } } } - ``` After initially fetching this story our cache might be as follows. Note that the story and comment both link to the same record as `author`: @@ -242,7 +225,6 @@ Map { author: Link(2), }, } - ``` The author of this story also commented on it — quite common. Now imagine that some other view fetches new information about the author, and her profile photo has changed to a new URI. Here's the _only_ part of our cached data that changes: @@ -256,7 +238,6 @@ Map { photo: 'http://.../photo2.jpg', }, } - ``` The value of the `photo` field has changed; and therefore the record `2` has also changed. And that's it. Nothing else in the _cache_ is affected. But clearly our _view_ needs to reflect the update: both instances of the author in the UI (as story author and comment author) need to show the new photo. @@ -273,7 +254,6 @@ ImmutableMap { }, 3: ImmutableMap // same as before } - ``` If we replace `2` with a new immutable record, we'll also get a new immutable instance of the cache object. However, records `1` and `3` are untouched. Because the data is normalized, we can't tell that `story`'s contents have changed just by looking at the `story` record alone. @@ -299,7 +279,6 @@ mutation StoryLike($storyID: String) { likeCount } } - ``` Notice that we're querying for data that _may_ have changed as a result of the mutation. An obvious question is: why can't the server just tell us what changed? The answer is: it's complicated. GraphQL abstracts over _any_ data storage layer (or an aggregation of multiple sources), and works with any programming language. Furthermore, the goal of GraphQL is to provide data in a form that is useful to product developers building a view. diff --git a/website/versioned_docs/version-v1.5.0/PrinciplesAndArchitecture-ThinkingInRelay.md b/website/versioned_docs/version-v1.5.0/PrinciplesAndArchitecture-ThinkingInRelay.md index 47c27f92ab909..1ffea144589ad 100644 --- a/website/versioned_docs/version-v1.5.0/PrinciplesAndArchitecture-ThinkingInRelay.md +++ b/website/versioned_docs/version-v1.5.0/PrinciplesAndArchitecture-ThinkingInRelay.md @@ -30,13 +30,11 @@ fragment Story_story on Story { photo } } - ``` And this fragment can then be used to define the Story container: ```javascript - const {createFragmentContainer, graphql} = require('react-relay'); // Plain React component. @@ -64,7 +62,6 @@ const StoryContainer = createFragmentContainer(Story, { In React, rendering a view requires two inputs: the _component_ to render, and a _root_ DOM (UI) node to render into. Rendering Relay containers is similar: we need a _container_ to render, and a _root_ in the graph from which to start our query. We also must ensure that the queries for the container are executed and may want to show a loading indicator while data is being fetched. Similar to `ReactDOM.render(component, domNode)`, Relay provides `` for this purpose. The `query` and `variables` define what data to fetch and `render` defines what to render. Here's how we might render ``: ```javascript - ReactDOM.render( { ); } } - ``` The above code is doing something very similar to our [previous example](#rendering-graphql-queries), however, we are now passing a `$userID` variable to the GraphQL query, via the `variables` prop. This has a couple of important implications: @@ -229,7 +217,6 @@ Now that we know how to define and fetch queries, let's actually start building First, let's start at the bottom; let's say that we want to render a component that given a todo item, simply displays the item's text and completed state: ```javascript - // Todo.js import React from 'react'; @@ -259,7 +246,6 @@ export default class Todo extends React.Component { ); } } - ``` From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L107), we know that we can query this data on the `Todo` type. However, we don't want to have to send a separate query for each todo item; that would defeat the purpose of using GraphQL over a traditional REST API. We could manually query for these fields directly in our `QueryRenderer` query, but that would hurt re-usability: what if we want to query the same set of fields as part of a different query? Additionally, we wouldn't know which component needs the data we're querying, a problem Relay directly tries to address. @@ -267,18 +253,15 @@ From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/dat Instead, we can define a reusable [Fragment](http://graphql.org/learn/queries/#fragments), which allows us to define a set of fields on a type and reuse them within our queries wherever we need to: ```graphql - fragment TodoItemFragment on Todo { complete text } - ``` Our component can then use this fragment to declare its data dependency on the `Todo` GraphQL type: ```javascript - // Todo.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -338,7 +321,6 @@ Before proceeding, don't forget to run the Relay Compiler with `yarn relay`. Given that [Fragment Containers](./fragment-container) are just React components, we can compose them as such, and even re-use fragment containers within other fragment containers. As an example, let's see how we would define a `TodoList` component that just renders a list of todo items, and whether all have been completed or not: ```javascript - // TodoList.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -397,7 +379,6 @@ export default createFragmentContainer( } `, ); - ``` As with the first fragment container we defined, `TodoList` declares it's data dependencies via a fragment. However, this component additionally re-uses the fragment previously defined by the `Todo` component, and passes the appropriate data to when rendering the child `Todo` components (a.k.a. fragment containers). @@ -412,7 +393,6 @@ fragment containers do not directly fetch data. Instead, containers declare a sp A `QueryRenderer` rendering these fragment containers could look like the following: ```javascript - // ViewerTodoList.js import React from 'react'; import PropTypes from 'prop-types'; @@ -454,7 +434,6 @@ export default ViewerTodoList extends React.Component { ); } } - ``` Check out or docs for [Fragment Containers](./fragment-container) for more details, and our guides on [Refetch](./refetch-container) and [Pagination](./pagination-container) for more advanced usage of containers. @@ -466,7 +445,6 @@ Now that we know how to query for and render data, let's move on to changing our From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L35), we know that we have some mutations available to us, so let's start by writing a mutation to change the `complete` status of a given todo item (i.e. mark or unmark it as done): ```graphql - mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { changeTodoStatus(input: $input) { todo { @@ -475,7 +453,6 @@ mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { } } } - ``` This mutation allows us to query back some data as a [result of the mutation](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L18), so we're going to query for the updated `complete` status on the todo item. @@ -483,7 +460,6 @@ This mutation allows us to query back some data as a [result of the mutation](ht In order to execute this mutation in Relay, we're going to write a new mutation using Relay's `commitMutation` api: ```javascript - // ChangeTodoStatusMutation.js import {graphql, commitMutation} from 'react-relay'; @@ -517,7 +493,6 @@ function commit( } export default {commit}; - ``` Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mutation to the server, and in our case, upon receiving a response it will automatically update the local data store with the latest data from the server. This also means that upon receiving the response, Relay will ensure that any components (i.e. containers) that depend on the updated data are re-rendered. @@ -525,7 +500,6 @@ Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mut In order to actually use this mutation in our component, we could update our `Todo` component in the following way: ```javascript - // Todo.js // ... @@ -559,7 +533,6 @@ In order to make the experience better, we can configure our mutation to do an o In Relay, there's a couple of options we can pass to `commitMutation` to enable optimistic updates. Let's see what that would look like in our `ChangeTodoStatusMutation`: ```javascript - // ChangeTodoStatusMutation.js // ... @@ -594,7 +567,6 @@ function commit( } export default {commit}; - ``` In the simplest case above, we just need to pass an `optimisticResponse` option, which should refer to an object having the same shape as the mutation response payload. When we pass this option, Relay will know to immediately update our local data with the optimistic response, and then update it with the actual server response, or roll it back if an error occurs. diff --git a/website/versioned_docs/version-v1.6.0/Modern-ConvertingMutations.md b/website/versioned_docs/version-v1.6.0/Modern-ConvertingMutations.md index 288ac18ab0872..96410a4589cef 100644 --- a/website/versioned_docs/version-v1.6.0/Modern-ConvertingMutations.md +++ b/website/versioned_docs/version-v1.6.0/Modern-ConvertingMutations.md @@ -12,19 +12,16 @@ FatQueries in Relay Classic mutations was a concept that was confusing for a num Example of existing fat query: ```javascript - RelayClassic.QL` fragment on MarkReadNotificationResponsePayload @relay(pattern: true) { notification } `; - ``` Example of converted mutation query: ```javascript - graphql` mutation MarkReadNotificationMutation( $input: MarkReadNotificationData! @@ -37,7 +34,6 @@ graphql` } } `; - ``` ## Migrating Configs @@ -63,7 +59,6 @@ This is no longer needed in Compatibility Mode for neither environments. Relay w Take this example of a simple mutation in Relay Classic: ```javascript - class LikeStoryMutation extends RelayClassic.Mutation { getMutation() { return RelayClassic.QL`mutation {likeStory}`; @@ -102,7 +97,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { `, }; } - ``` ### Converting `getMutation()` and `getFatQuery()` @@ -110,7 +104,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { We combine these two into a regular GraphQL mutation, which list out specific fields that needs to be updated. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story(data: $input) { @@ -122,7 +115,6 @@ const mutation = graphql` } } `; - ``` ### Converting `getConfigs()` @@ -134,13 +126,11 @@ As specified above, `FIELDS_CHANGE` configs can be omitted. To convert `getVariables()`, we take the return value from the original function and wrap it in an object that contains a property that matches the variable name for the mutation. In this case, the mutation has a `input` variable that is of type `LikeStoryData`. ```javascript - const variables = { input: { storyID: args.storyID } } - ``` ### Final Result @@ -148,7 +138,6 @@ const variables = { As you can see, our resulting mutation is a lot simpler and more like regular GraphQL than the Relay Classic version we started out with. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story { @@ -174,7 +163,6 @@ function commit(environment: CompatEnvironment, args) { variables, }); } - ``` See [Mutation](./mutations) for additional options on `commitMutation` for more complex mutations. diff --git a/website/versioned_docs/version-v1.6.0/Modern-FragmentContainer.md b/website/versioned_docs/version-v1.6.0/Modern-FragmentContainer.md index e86b79995c1c7..7bbd0a9f22899 100644 --- a/website/versioned_docs/version-v1.6.0/Modern-FragmentContainer.md +++ b/website/versioned_docs/version-v1.6.0/Modern-FragmentContainer.md @@ -17,12 +17,10 @@ Table of Contents: `createFragmentContainer` has the following signature: ```javascript - createFragmentContainer( component: ReactComponentClass, fragmentSpec: GraphQLTaggedNode | {[string]: GraphQLTaggedNode}, ): ReactComponentClass; - ``` ### Arguments @@ -46,7 +44,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -61,7 +58,6 @@ To start, let's build the plain React version of a hypothetical `` c Here's a basic implementation of `` that ignores styling in order to highlight the functionality: ```javascript - // TodoItem.js class TodoItem extends React.Component { render() { @@ -81,7 +77,6 @@ class TodoItem extends React.Component { ); } } - ``` ### Data Dependencies With GraphQL @@ -89,7 +84,6 @@ class TodoItem extends React.Component { In Relay, data dependencies are described using [GraphQL](https://github.com/facebook/graphql). For ``, the dependency can be expressed as follows. Note that this exactly matches the shape that the component expected for the `item` prop. ```javascript - graphql` # This fragment only applies to objects of type 'Todo'. fragment TodoItem_item on Todo { @@ -105,7 +99,6 @@ graphql` Given the plain React component and a GraphQL fragment, we can now define a Fragment Container to specify this component's data requirements. Let's look at the code first and then see what's happening: ```javascript - // TodoItem.js import {createFragmentContainer, graphql} from 'react-relay'; @@ -123,13 +116,11 @@ export default createFragmentContainer(TodoItem, { } `, }); - ``` Relay will infer the prop name from the fragment name according to the fragment naming convention `<...>_`. The example below is equivalent to the one above: ```javascript - export default createFragmentContainer( TodoItem, graphql` @@ -139,13 +130,11 @@ export default createFragmentContainer( } `, ); - ``` If there is no `_` suffix, the `data` prop name will be used: ```javascript - class TodoItem extends React.Component { render() { const item = this.props.data; @@ -162,7 +151,6 @@ export default createFragmentContainer( } `, ); - ``` ## Container Composition @@ -176,7 +164,6 @@ Let's explore how this works via a `` component that composes the `< View composition is _exactly_ what you're used to — Relay containers are just standard React components. Here's the `` component: ```javascript - class TodoList extends React.Component { render() { // Expects a `list` with a string `title`, as well as the information @@ -191,7 +178,6 @@ class TodoList extends React.Component { ); } } - ``` ### Composing Fragments @@ -199,7 +185,6 @@ class TodoList extends React.Component { Fragment composition works similarly — a parent container's fragment composes the fragment for each of its children. In this case, `` needs to fetch information about the `Todo`s that are required by ``. ```javascript - class TodoList extends React.Component // as above export default createFragmentContainer( @@ -217,7 +202,6 @@ export default createFragmentContainer( } `, ); - ``` Note that when composing fragments, the type of the composed fragment must match the field on the parent in which it is embedded. For example, it wouldn't make sense to embed a fragment of type `Story` into a parent's field of type `User`. Relay and GraphQL will provide helpful error messages if you get this wrong (and if they aren't helpful, let us know!). @@ -231,7 +215,6 @@ When defining a fragment, you can use the [`@argumentDefinitions`](./graphql-in- For example, let's redefine our `TodoList_list` fragment to take some arguments using `@argumentDefinitions`: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -241,7 +224,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` Any arguments defined inside `@argumentDefinitions` will be local variables available inside the fragment's scope. However, a fragment can also reference global variables that were defined in the root query. @@ -253,11 +235,9 @@ In order to pass arguments to a fragment that has `@argumentDefinitions`, you ne Following our `TodoList_list` example, we would pass arguments to the fragment like so: ```graphql - query TodoListQuery($count: Int, $userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` ### Calling Component Instance Methods @@ -268,7 +248,6 @@ Since Relay composes these component instances in a container, you need to use t Consider an input with a server-defined placeholder text and an imperative method to focus the input node: ```javascript - export default createFragmentContainer( class TodoInput extends React.Component { focus() { @@ -288,13 +267,11 @@ export default createFragmentContainer( } `, ); - ``` To call this method on the underlying component, first provide a `componentRef` function to the Relay container. This differs from providing a [`ref`](https://facebook.github.io/react/docs/refs-and-the-dom.html) function which would provide a reference to the Relay container itself, not the underlying React Component. ```javascript - export default createFragmentContainer( class TodoListView extends React.Component { render() { @@ -312,7 +289,6 @@ export default createFragmentContainer( } `, ); - ``` ## Rendering Containers diff --git a/website/versioned_docs/version-v1.6.0/Modern-GraphQLInRelay.md b/website/versioned_docs/version-v1.6.0/Modern-GraphQLInRelay.md index 45ed05dc9670e..7cb555b6ce502 100644 --- a/website/versioned_docs/version-v1.6.0/Modern-GraphQLInRelay.md +++ b/website/versioned_docs/version-v1.6.0/Modern-GraphQLInRelay.md @@ -14,7 +14,6 @@ Table of Contents: The `graphql` template tag provided by Relay serves as the mechanism to write queries, fragments, mutations or subscriptions in the [GraphQL](http://graphql.org/learn/) language. For example: ```javascript - import {graphql} from 'react-relay'; graphql` @@ -24,7 +23,6 @@ graphql` } } `; - ``` The result of using the `graphql` template tag are `GraphQLTaggedNode`s, which are used to define [Query Renderers](./query-renderer), [Fragment Containers](./fragment-container), [Refetch Containers](./refetch-container), [Pagination Containers](./pagination-container), etc. @@ -42,11 +40,9 @@ Relay uses directives to add additional information to GraphQL documents, which `@arguments` is a directive used to pass arguments to a fragment that was defined using [`@argumentDefinitions`](#argumentdefinitions). For example: ```graphql - query TodoListQuery($userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` See [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -56,7 +52,6 @@ See [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragme `@argumentDefinitions` is a directive used to specify arguments taken by a fragment. For example: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -66,7 +61,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` See [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -82,13 +76,11 @@ When using the [Pagination Container](./pagination-container), Relay expects con When defining a fragment, you can use the `@relay(plural: true)` directive to indicate that the fragment is backed by a [GraphQL list](http://graphql.org/learn/schema/#lists-and-non-null), meaning that it will inform Relay that this particular field is an array. For example: ```javascript - graphql` fragment TodoItems_items on TodoItem @relay(plural: true) { id text }`; - ``` ### `@relay(mask: Boolean)` @@ -104,7 +96,6 @@ Keep in mind that it is typically considered an **anti-pattern** to create a sin In the example below, the `user` prop will include the data for `id` and `name` fields wherever `...Component_internUser` is included, instead of Relay's normal behavior to mask those fields: ```javascript - graphql` fragment Component_internUser on InternUser { id @@ -132,7 +123,6 @@ export default createFragmentContainer( } `, ); - ``` ## Relay Compiler @@ -142,7 +132,6 @@ Relay uses the Relay Compiler to convert [`graphql`](#graphql) literals into gen A query like the following: ```javascript - graphql` fragment MyComponent on Type { field @@ -166,7 +155,6 @@ See our relay-compiler section in our [Installation and Setup guide](./installat To use the Relay Compiler, you need either a .graphql or .json GraphQL schema file, describing your GraphQL server's API. Typically these files are local representations of a server source of truth and are not edited directly. For example, we might have a `schema.graphql` like: ```graphql - schema { query: Root } @@ -184,7 +172,6 @@ type WordDefinition { text: String image: String } - ``` ### Source files @@ -200,7 +187,6 @@ For example, given the two files: - `src/Components/DictionaryComponent.js` ```javascript - const DictionaryWordFragment = graphql` fragment DictionaryComponent_word on Word { id @@ -222,7 +208,6 @@ For example, given the two files: - `src/Queries/DictionaryQuery.js` ```javascript - const DictionaryQuery = graphql` query DictionaryQuery { dictionary { @@ -246,9 +231,7 @@ Typically you will not need to import your generated definitions. The [Relay Bab However the Relay Compiler also automatically generates [Flow](https://flow.org) types as [type comments](https://flow.org/en/docs/types/comments/). For example, you can import the generated flow types like so: ```javascript - import type {DictionaryComponent_word} from './__generated__/DictionaryComponent_word.graphql'; - ``` ### Advanced usage diff --git a/website/versioned_docs/version-v1.6.0/Modern-LocalStateManagement.md b/website/versioned_docs/version-v1.6.0/Modern-LocalStateManagement.md index f3427f392a611..dc50079ca5fbe 100644 --- a/website/versioned_docs/version-v1.6.0/Modern-LocalStateManagement.md +++ b/website/versioned_docs/version-v1.6.0/Modern-LocalStateManagement.md @@ -23,23 +23,19 @@ It can even be used to extend an existing server schema. For example, we can create a new type called `Note`: ```graphql - type Note { id: ID! title: String body: String } - ``` And then extend the server schema type `User`, with a list of `Note`, called `notes`. ```graphql - extend type User { notes: [Note] } - ``` ## Querying local state @@ -50,7 +46,6 @@ The field can be from the server schema, or it can be schema agnostic, like an i Here, we use a [QueryRenderer](./query-renderer) to get the current `User` via the `viewer` field, along with their id, name and the local list of notes. ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -96,7 +91,6 @@ const Example = (props) => { /> ); } - ``` ## Mutating local state @@ -110,7 +104,6 @@ To build upon the previous example, let's try creating, updating and deleting a ### Create ```javascript - import {commitLocalUpdate} from 'react-relay'; let tempID = 0; @@ -130,7 +123,6 @@ function createUserNote() { user.setLinkedRecords([...userNoteRecords, newNoteRecord], 'notes'); }); } - ``` Note that since this record will be rendered by the `ExampleQuery` in our `QueryRenderer`, the QueryRenderer will automatically retain this data so it isn't garbage collected. @@ -138,7 +130,6 @@ Note that since this record will be rendered by the `ExampleQuery` in our `Query If no component is rendering the local data and you want to manually retain it, you can do so by calling `environment.retain()`: ```javascript - import {createOperationDescriptor, getRequest} from 'relay-runtime'; // Create a query that references that record @@ -165,13 +156,11 @@ const disposable = environment.retain(operation); // Whenever you don't need that data anymore and it's okay for Relay to garbage collect it, // you can dispose of the retain disposable.dispose(); - ``` ### Update ```javascript - import {commitLocalUpdate} from 'react-relay'; function updateUserNote(dataID, body, title) { @@ -182,13 +171,11 @@ function updateUserNote(dataID, body, title) { note.setValue(title, 'title') }); } - ``` ### Delete ```javascript - import {commitLocalUpdate} from 'react-relay'; function deleteUserNote(dataID) { @@ -206,7 +193,6 @@ function deleteUserNote(dataID) { user.setLinkedRecords(newUserNoteRecords, 'notes'); }); } - ``` ## Initial local state @@ -215,7 +201,6 @@ All new client-side schema fields default to `undefined` value. Often however, y You can use an updater function via `commitLocalUpdate` to prime local state. ```javascript - import {commitLocalUpdate} from 'react-relay'; commitLocalUpdate(environment, store => { @@ -224,5 +209,4 @@ commitLocalUpdate(environment, store => { // initialize user notes to an empty array. user.setLinkedRecords([], 'notes'); }); - ``` diff --git a/website/versioned_docs/version-v1.6.0/Modern-MigrationSetup.md b/website/versioned_docs/version-v1.6.0/Modern-MigrationSetup.md index 66f1145357e25..a89c0e178e0e5 100644 --- a/website/versioned_docs/version-v1.6.0/Modern-MigrationSetup.md +++ b/website/versioned_docs/version-v1.6.0/Modern-MigrationSetup.md @@ -13,13 +13,11 @@ With some additional configuration, the `"relay"` babel plugin can also translat Relay Classic `Relay.QL` literals. Most importantly, include a reference to your GraphQL Schema as either a json file or graphql schema file. ```javascript - { "plugins": [ ["relay", {"schema": "path/schema.graphql"}] ] } - ``` ## Set up babel-plugin-relay for "[compatibility mode](./relay-compat)" @@ -29,13 +27,11 @@ literals can be translated to be usable by _both_ runtimes if configured to use compatibility mode: ```javascript - { "plugins": [ ["relay", {"compat": true, "schema": "path/schema.graphql"}] ] } - ``` ## Additional Options @@ -47,7 +43,6 @@ thrown at runtime. When compiling code for production deployment, the plugin can be configured to immediately throw upon encountering a validation problem. The plugin can be further customized for different environments with the following options: ```javascript - { "plugins": [ ["relay", { @@ -56,5 +51,4 @@ When compiling code for production deployment, the plugin can be configured to i }] ] } - ``` diff --git a/website/versioned_docs/version-v1.6.0/Modern-Mutations.md b/website/versioned_docs/version-v1.6.0/Modern-Mutations.md index d879216bdd5e3..ebb1797237203 100644 --- a/website/versioned_docs/version-v1.6.0/Modern-Mutations.md +++ b/website/versioned_docs/version-v1.6.0/Modern-Mutations.md @@ -16,7 +16,6 @@ Table of Contents: Use `commitMutation` to create and execute mutations. `commitMutation` has the following signature: ```javascript - commitMutation( environment: Environment, config: { @@ -30,7 +29,6 @@ commitMutation( configs?: Array, }, ); - ``` ### Arguments @@ -57,7 +55,6 @@ commitMutation( Example of a simple mutation: ```javascript - import {commitMutation, graphql} from 'react-relay'; const mutation = graphql` @@ -92,7 +89,6 @@ function markNotificationAsRead(environment, source, storyID) { }, ); } - ``` ## Optimistic Updates @@ -100,7 +96,6 @@ function markNotificationAsRead(environment, source, storyID) { To improve perceived responsiveness, you may wish to perform an "optimistic update", in which the client immediately updates to reflect the anticipated new value even before the response from the server has come back. The simplest way to do this is by providing an `optimisticResponse` and adding it to the `config` that we pass into `commitMutation`: ```javascript - const mutation = graphql` mutation MarkReadNotificationMutation( $input: MarkReadNotificationData! @@ -129,7 +124,6 @@ commitMutation( variables, }, ); - ``` Another way to enable optimistic updates is via the `optimisticUpdater`, which can be used for more complicated update scenarios. Using `optimisticUpdater` is covered in the section [below](#using-updater-and-optimisticupdater). @@ -149,7 +143,6 @@ Given a deletedIDFieldName, Relay will remove the node(s) from the connection. #### Example ```javascript - const mutation = graphql` mutation DestroyShipMutation($input: DestroyShipData!) { destroyShip(input: $input) { @@ -167,7 +160,6 @@ const configs = [{ type: 'NODE_DELETE', deletedIDFieldName: 'destroyedShipId', }]; - ``` ### RANGE_ADD @@ -187,7 +179,6 @@ Given a parent, information about the connection, and the name of the newly crea #### Example ```javascript - const mutation = graphql` mutation AddShipMutation($input: AddShipData!) { addShip(input: $input) { @@ -210,7 +201,6 @@ const configs = [{ }], edgeName: 'newShipEdge', }]; - ``` ### RANGE_DELETE @@ -232,7 +222,6 @@ from the connection but leave the associated record(s) in the store. #### Example ```javascript - const mutation = graphql` mutation RemoveTagsMutation($input: RemoveTagsData!) { removeTags(input: $input) { @@ -255,7 +244,6 @@ const configs = [{ pathToConnection: ['todo', 'tags'], deletedIDFieldName: removedTagId }]; - ``` ## Using updater and optimisticUpdater @@ -273,7 +261,6 @@ When you provide these functions, this is roughly what happens during the mutati Here are a quick example of adding a todo item to a Todo list using this [example schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L36): ```javascript - // AddTodoMutation.js import {commitMutation, graphql} from 'react-relay'; import {ConnectionHandler} from 'relay-runtime'; @@ -365,7 +352,6 @@ function commit( } ); } - ``` For details on how to interact with the Relay Store, please refer to our Relay Store [docs](./relay-store). diff --git a/website/versioned_docs/version-v1.6.0/Modern-NetworkLayer.md b/website/versioned_docs/version-v1.6.0/Modern-NetworkLayer.md index c5813a18609e8..e0d5a012a0ecf 100644 --- a/website/versioned_docs/version-v1.6.0/Modern-NetworkLayer.md +++ b/website/versioned_docs/version-v1.6.0/Modern-NetworkLayer.md @@ -8,7 +8,6 @@ In order to know how to access your GraphQL server, Relay Modern requires develo Currently the easiest way to create a network layer is via a helper from the `relay-runtime` package: ```javascript - const {Environment, Network} = require('relay-runtime'); // Define a function that fetches the results of an operation (query/mutation/etc) @@ -42,7 +41,6 @@ const environment = new Environment({ ..., // other options network, }); - ``` Note that this is a basic example to help you get started. This example could be extended with additional features such as request/response caching (enabled e.g. when `cacheConfig.force` is false) and uploading form data for mutations (the `uploadables` parameter). diff --git a/website/versioned_docs/version-v1.6.0/Modern-PaginationContainer.md b/website/versioned_docs/version-v1.6.0/Modern-PaginationContainer.md index 8a9ee1c315691..7cd45d706b42d 100644 --- a/website/versioned_docs/version-v1.6.0/Modern-PaginationContainer.md +++ b/website/versioned_docs/version-v1.6.0/Modern-PaginationContainer.md @@ -24,7 +24,6 @@ However, when [specifying connection fragments](#createpaginationcontainer) for The purpose of the `@connection` directive is to allow Relay to uniquely identify different connections under a parent type. The `@connection` directive takes 2 arguments that help identify the connection: ```graphql - @connection(key: String!, filters: [String]) ``` @@ -37,7 +36,6 @@ The purpose of the `@connection` directive is to allow Relay to uniquely identif Specifying just the `key`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and the value of `$orderBy` (given that no `filters` were provided) @@ -53,13 +51,11 @@ fragment Feed_user on User { } } } - ``` Specifying `key` and `filters`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and /only/ the value of `$searchTerm`, i.e. @@ -77,7 +73,6 @@ fragment Feed_user on User { } } } - ``` ## `createPaginationContainer` @@ -85,7 +80,6 @@ fragment Feed_user on User { `createPaginationContainer` has the following signature: ```javascript - createPaginationContainer( component: ReactComponentClass, fragmentSpec: GraphQLTaggedNode | {[string]: GraphQLTaggedNode}, @@ -113,7 +107,6 @@ type ConnectionData = { startCursor: ?string, }, }; - ``` ### Arguments @@ -137,7 +130,6 @@ type ConnectionData = { The Component resulting from `createPaginationContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -148,7 +140,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -163,7 +154,6 @@ type Props = { `hasMore` is a function available on the `relay` [prop](#available-props). This function indicates wether there are more pages to fetch from the server or not. ```javascript - hasMore: () => boolean, ``` @@ -173,7 +163,6 @@ hasMore: () => boolean, `isLoading` is a function available on the `relay` [prop](#available-props). This function indicates if a previous call to [`loadMore()`](#loadmore) is still pending. This is convenient for avoiding duplicate load calls. ```javascript - isLoading: () => boolean, ``` @@ -183,7 +172,6 @@ isLoading: () => boolean, `loadMore` is a function available on the `relay` [prop](#available-props). You can call `loadMore()` to fetch more items from the server based on the `connectionConfig` provided to the container. This will return null if there are no more items to fetch, otherwise it will fetch more items and return a Disposable that can be used to cancel the fetch. ```javascript - loadMore(pageSize: number, callback: ?(error: ?Error) => void): ?Disposable ``` @@ -198,7 +186,6 @@ loadMore(pageSize: number, callback: ?(error: ?Error) => void): ?Disposable `refetchConnection` is a function available on the `relay` [prop](#available-props). You can call `refetchConnection` to restart pagination on a connection from scratch, with optionally a completely new set of variables to pass to the pagination `query`. This is useful for example if you are paginating over a collection based on a userID and the userID changes, you'd want to start paginating over the new collection for the new user. ```javascript - refetchConnection:( count: number, callback: (error: ?Error) => void, @@ -216,7 +203,6 @@ refetchConnection:( ## Pagination Example ```javascript - // Feed.js import {createPaginationContainer, graphql} from 'react-relay'; @@ -311,5 +297,4 @@ module.exports = createPaginationContainer( ` } ); - ``` diff --git a/website/versioned_docs/version-v1.6.0/Modern-PersistedQueries.md b/website/versioned_docs/version-v1.6.0/Modern-PersistedQueries.md index 74b5c3c5d13c6..aadc6710f63bb 100644 --- a/website/versioned_docs/version-v1.6.0/Modern-PersistedQueries.md +++ b/website/versioned_docs/version-v1.6.0/Modern-PersistedQueries.md @@ -16,12 +16,10 @@ The relay compiler supports persisted queries which is useful because: In your `npm` script in `package.json`, run the relay compiler using the `--persist-output` flag: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` The `--persist-ouput` flag does 2 things: @@ -30,8 +28,7 @@ The `--persist-ouput` flag does 2 things: For example without `--persist-output`, a generated `ConcreteRequest` might look like below: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -48,8 +45,7 @@ The `--persist-ouput` flag does 2 things: With `--persist-output ` this becomes: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -67,12 +63,10 @@ The `--persist-ouput` flag does 2 things: 2. It generates a JSON file at the `` you specify containing a mapping from query ids to the corresponding operation texts. -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./src/queryMaps/queryMap.json" } - ``` The example above writes the complete query map file to `./src/queryMaps/queryMap.json`. You need to ensure all the directories @@ -82,8 +76,7 @@ leading to the `queryMap.json` file exist. You'll need to modify your network layer fetch implementation to pass a documentId parameter in the POST body instead of a query parameter: -```js - +```javascript function fetchQuery(operation, variables,) { return fetch('/graphql', { method: 'POST', @@ -99,7 +92,6 @@ function fetchQuery(operation, variables,) { return response.json(); }); } - ``` ## Executing Persisted Queries on the Server @@ -115,13 +107,11 @@ the query map file in a common location accessible to both the client and the se For applications where the client and server projects are separate, one option is to have an additional npm run script to push the query map at compile time to a location accessible by your server: -```js - +```javascript "scripts": { "push-queries": "node ./pushQueries.js", "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-ouput && npm run push-queries" } - ``` Some possibilities of what you can do in `./pushQueries.js`: @@ -145,8 +135,7 @@ database technologies you use, so we'll just cover the most common and basic exa If you use `express-graphql` and have access to the query map file, you can import the `--persist-output` JSON file directly and perform the matching using the `matchQueryMiddleware` from [relay-compiler-plus](https://github.com/yusinto/relay-compiler-plus). -```js - +```javascript import Express from 'express'; import expressGraphql from 'express-graphql'; import {matchQueryMiddleware} from 'relay-compiler-plus'; @@ -157,7 +146,6 @@ const app = Express(); app.use('/graphql', matchQueryMiddleware(queryMapJson), expressGraphql({schema})); - ``` ## Using `--persist-output` and `--watch` diff --git a/website/versioned_docs/version-v1.6.0/Modern-QueryRenderer.md b/website/versioned_docs/version-v1.6.0/Modern-QueryRenderer.md index 5b5fc9c90a237..6914b030ccd25 100644 --- a/website/versioned_docs/version-v1.6.0/Modern-QueryRenderer.md +++ b/website/versioned_docs/version-v1.6.0/Modern-QueryRenderer.md @@ -21,7 +21,6 @@ However, a `QueryRenderer` will not start loading its data until it is mounted, ## Example ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -53,5 +52,4 @@ class Example extends React.Component { ); } } - ``` diff --git a/website/versioned_docs/version-v1.6.0/Modern-RefetchContainer.md b/website/versioned_docs/version-v1.6.0/Modern-RefetchContainer.md index 25839f6aed901..416e049a71403 100644 --- a/website/versioned_docs/version-v1.6.0/Modern-RefetchContainer.md +++ b/website/versioned_docs/version-v1.6.0/Modern-RefetchContainer.md @@ -16,13 +16,11 @@ Table of Contents: `createRefetchContainer` has the following signature: ```javascript - createRefetchContainer( component: ReactComponentClass, fragmentSpec: GraphQLTaggedNode | {[string]: GraphQLTaggedNode}, refetchQuery: GraphQLTaggedNode, ): ReactComponentClass; - ``` ### Arguments @@ -40,7 +38,6 @@ createRefetchContainer( The Component resulting from `createRefetchContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -48,7 +45,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -64,7 +60,6 @@ type Props = { `refetch` has the following signature: ```javascript - type RefetchOptions = { force?: boolean, }; @@ -104,7 +99,6 @@ Returns a `Disposable` on which you could call `dispose()` to cancel the refetch In this simple example, let's assume we want to fetch the latest data for a `TodoItem` from the server: ```javascript - // TodoItem.js import {createRefetchContainer, graphql} from 'react-relay'; @@ -148,7 +142,6 @@ export default createRefetchContainer( } ` ); - ``` ### Loading more data @@ -156,7 +149,6 @@ export default createRefetchContainer( In this example we are using a Refetch Container to fetch more stories in a story feed component. ```javascript - import {createRefetchContainer, graphql} from 'react-relay'; class FeedStories extends React.Component { @@ -212,5 +204,4 @@ export default createRefetchContainer( } `, ); - ``` diff --git a/website/versioned_docs/version-v1.6.0/Modern-RelayCompat.md b/website/versioned_docs/version-v1.6.0/Modern-RelayCompat.md index 36632d3a8f1a1..f47dbd845ba3e 100644 --- a/website/versioned_docs/version-v1.6.0/Modern-RelayCompat.md +++ b/website/versioned_docs/version-v1.6.0/Modern-RelayCompat.md @@ -31,7 +31,6 @@ Relay Modern. The components using Relay Compat can be referred to by both other Relay Modern and Relay Classic components. ```javascript - const {createFragmentContainer, graphql} = require('react-relay/compat'); class TodoItem extends React.Component { @@ -47,5 +46,4 @@ module.exports = createFragmentContainer(TodoItem, graphql` isComplete } `); - ``` diff --git a/website/versioned_docs/version-v1.6.0/Modern-RelayEnvironment.md b/website/versioned_docs/version-v1.6.0/Modern-RelayEnvironment.md index b356b5deecdc5..ed75bc69d1f86 100644 --- a/website/versioned_docs/version-v1.6.0/Modern-RelayEnvironment.md +++ b/website/versioned_docs/version-v1.6.0/Modern-RelayEnvironment.md @@ -12,7 +12,6 @@ Most applications will create a single Environment instance and use it throughou To create an environment instance in Relay Modern, use the `RelayModernEnvironment` class: ```javascript - const { Environment, Network, @@ -30,7 +29,6 @@ const environment = new Environment({ network, store, }); - ``` For more details on creating a Network, see the [NetworkLayer guide](./network-layer). @@ -44,7 +42,6 @@ The example above did not configure a `handlerProvider`, which means that a defa If you wish to provide your own `handlerProvider`, you can do so: ```javascript - const { ConnectionHandler, ViewerHandler, @@ -60,5 +57,4 @@ function handlerProvider(handle) { `handlerProvider: No handler provided for ${handle}` ); } - ``` diff --git a/website/versioned_docs/version-v1.6.0/Modern-RelayStore.md b/website/versioned_docs/version-v1.6.0/Modern-RelayStore.md index 91845846694f4..e8e2df3d9efcf 100644 --- a/website/versioned_docs/version-v1.6.0/Modern-RelayStore.md +++ b/website/versioned_docs/version-v1.6.0/Modern-RelayStore.md @@ -16,7 +16,6 @@ Table of Contents: The `RecordSourceSelectorProxy` is the type of the `store` that [`updater` functions](./mutations#using-updater-and-optimisticupdater) receive as an argument. The following is the `RecordSourceSelectorProxy` interface: ```javascript - interface RecordSourceSelectorProxy { create(dataID: string, typeName: string): RecordProxy; delete(dataID: string): void; @@ -25,7 +24,6 @@ interface RecordSourceSelectorProxy { getRootField(fieldName: string): ?RecordProxy; getPluralRootField(fieldName: string): ?Array; } - ``` ### `create(dataID: string, typeName: string): RecordProxy` @@ -35,9 +33,7 @@ Creates a new record in the store given a `dataID` and the `typeName` as defined #### Example ```javascript - const record = store.create(dataID, 'Todo'); - ``` ### `delete(dataID: string): void` @@ -47,9 +43,7 @@ Deletes a record from the store given its `dataID`. #### Example ```javascript - store.delete(dataID); - ``` ### `get(dataID: string): ?RecordProxy` @@ -59,9 +53,7 @@ Retrieves a record from the store given its `dataID`. Returns a [`RecordProxy`]( #### Example ```javascript - const record = store.get(dataID); - ``` ### `getRoot(): RecordProxy` @@ -73,20 +65,16 @@ Returns the [`RecordProxy`](#recordproxy) representing the root of the GraphQL d Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - // Represents root query const root = store.getRoot(); - ``` ### `getRootField(fieldName: string): ?RecordProxy` @@ -98,19 +86,15 @@ Retrieves a root field from the store given the `fieldName`, as defined by the G Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - const viewer = store.getRootField('viewer'); - ``` ### `getPluralRootField(fieldName: string): ?Array` @@ -122,19 +106,15 @@ Retrieves a root field that represents a collection from the store given the `fi Given the GraphQL document: ```graphql - nodes(first: 10) { # ... } - ``` Usage: ```javascript - const nodes = store.getPluralRootField('nodes'); - ``` ## RecordProxy @@ -142,7 +122,6 @@ const nodes = store.getPluralRootField('nodes'); The `RecordProxy` serves as an interface to mutate records: ```javascript - interface RecordProxy { copyFieldsFrom(sourceRecord: RecordProxy): void; getDataID(): string; @@ -167,7 +146,6 @@ interface RecordProxy { ): RecordProxy; setValue(value: mixed, name: string, arguments?: ?Object): RecordProxy; } - ``` ### `getDataID(): string` @@ -177,9 +155,7 @@ Returns the dataID of the current record. #### Example ```javascript - const id = record.getDataID(); - ``` ### `getType(): string` @@ -189,7 +165,6 @@ Gets the type of the current record, as defined by the GraphQL schema. #### Example ```javascript - const type = user.getType(); // User ``` @@ -203,20 +178,16 @@ Gets the value of a field in the current record given the field name. Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - const name = viewer.getValue('name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. @@ -226,20 +197,16 @@ Optionally, if the field takes arguments, you can pass a bag of `variables`. Given the GraphQL document: ```graphql - viewer { id name(arg: $arg) } - ``` Usage: ```javascript - const name = viewer.getValue('name', {arg: 'value'}); - ``` ### `getLinkedRecord(name: string, arguments?: ?Object): ?RecordProxy` @@ -251,23 +218,19 @@ Retrieves the a record associated with the current record given the field name, Given the GraphQL document: ```graphql - rootField { viewer { id name } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -277,22 +240,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { viewer(arg: $arg) { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {arg: 'value'}); - ``` ### `getLinkedRecords(name: string, arguments?: ?Object): ?Array` @@ -304,22 +263,18 @@ Retrieves the set of records associated with the current record given the field Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const nodes = rootField.getLinkedRecord('nodes'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -329,22 +284,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { nodes(first: $count) { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {count: 10}); - ``` ### `getOrCreateLinkedRecord(name: string, typeName: string, arguments?: ?Object)` @@ -356,19 +307,16 @@ Retrieves the a record associated with the current record given the field name, Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = rootField.getOrCreateLinkedRecord('viewer', 'User'); // Will create if it doesn't exist @@ -383,28 +331,22 @@ Mutates the current record by setting a new value on the specified field. Return Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - viewer.setValue('New Name', 'name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. ```javascript - viewer.setValue('New Name', 'name', {arg: 'value'}); - ``` ### `copyFieldsFrom(sourceRecord: RecordProxy): void` @@ -414,7 +356,6 @@ Mutates the current record by copying the fields over from the passed in record #### Example ```javascript - const record = store.get(id1); const otherRecord = store.get(id2); record.copyFieldsFrom(otherRecord); // Mutates `record` @@ -430,19 +371,16 @@ Mutates the current record by setting a new linked record on the given the field Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = store.create(/* ... */)'' rootField.setLinkedRecord(newViewer, 'viewer'); // @@ -460,19 +398,16 @@ Mutates the current record by setting a new set of linked records on the given t Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newNode = store.create(/* ... */); const newNodes = [...rootField.getLinkedRecords('nodes'), newNode]; @@ -487,7 +422,6 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl `ConnectionHandler` is a utility module exposed by `relay-runtime` that aids in the manipulation of connections. `ConnectionHandler` exposes the following interface: ```javascript - interface ConnectionHandler { getConnection( record: RecordProxy, @@ -512,7 +446,6 @@ interface ConnectionHandler { ): void, deleteNode(connection: RecordProxy, nodeID: string): void } - ``` ### `getConnection(record: RecordProxy, key: string, filters?: ?Object)` @@ -522,7 +455,6 @@ Given a record and a connection key, and optionally a set of filters, `getConnec First, let's take a look at a plain connection: ```graphql - fragment FriendsFragment on User { friends(first: 10) { edges { @@ -532,26 +464,22 @@ fragment FriendsFragment on User { } } } - ``` Accessing a plain connection field like this is the same as other regular field: ```javascript - // The `friends` connection record can be accessed with: const user = store.get(userID); const friends = user && user.getLinkedRecord(user, 'friends'); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` In a [pagination container](./pagination-container), we usually annotate the actual connection field with `@connection` to tell Relay which part needs to be paginated: ```graphql - fragment FriendsFragment on User { friends(first: 10, orderby: "firstname") @connection( key: "FriendsFragment_friends", @@ -563,7 +491,6 @@ fragment FriendsFragment on User { } } } - ``` For connections like the above, `ConnectionHandler` helps us find the record: @@ -581,7 +508,6 @@ const friends = ConnectionHandler.getConnection( ); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` ### Edge creation and insertion @@ -611,7 +537,6 @@ ConnectionHandler.insertEdgeAfter(friends, edge); // No cursor provided, Insert the edge at the front: ConnectionHandler.insertEdgeBefore(friends, edge); - ``` ### `deleteNode(connection: RecordProxy, nodeID: string): void` @@ -625,5 +550,4 @@ Given a connection, deletes any edges whose id matches the given id. const user = store.get(userID); const friends = ConnectionHandler.getConnection(user, 'friends'); ConnectionHandler.deleteNode(friends, idToDelete); - ``` diff --git a/website/versioned_docs/version-v1.6.0/Modern-Subscriptions.md b/website/versioned_docs/version-v1.6.0/Modern-Subscriptions.md index a02a27933c40a..c4e9b324730f0 100644 --- a/website/versioned_docs/version-v1.6.0/Modern-Subscriptions.md +++ b/website/versioned_docs/version-v1.6.0/Modern-Subscriptions.md @@ -6,7 +6,6 @@ original_id: subscriptions Relay exposes the following APIs to create subscriptions. ```javascript - const {requestSubscription} = require('react-relay'); type Variables = {[name: string]: any}; @@ -23,7 +22,6 @@ requestSubscription( configs?: Array, }, ); - ``` Now let's take a closer look at the `config`: @@ -47,7 +45,6 @@ appropriate when you are only changing the properties of existing records that can be identified by their `id`: ```javascript - const { requestSubscription, graphql, @@ -81,7 +78,6 @@ requestSubscription( onError: error => console.error(error), } ); - ``` # Updating the client on each response @@ -91,7 +87,6 @@ Relay's in-memory cache when each subscription response is received. To do so, pass an `updater` function: ```javascript - const {ConnectionHandler} = require('relay-runtime'); requestSubscription( @@ -117,5 +112,4 @@ requestSubscription( }, }, ); - ``` diff --git a/website/versioned_docs/version-v1.6.0/Modern-TestingRelayComponents.md b/website/versioned_docs/version-v1.6.0/Modern-TestingRelayComponents.md index f30317b146e96..eaa443bd20147 100644 --- a/website/versioned_docs/version-v1.6.0/Modern-TestingRelayComponents.md +++ b/website/versioned_docs/version-v1.6.0/Modern-TestingRelayComponents.md @@ -64,7 +64,6 @@ With the `MockPayloadGenerator` and `@relay_test_operation`, we want to get rid Example of a simple Mock Resolver: ```javascript - { ID() { // Return mock value for a scalar filed with type ID @@ -75,13 +74,11 @@ Example of a simple Mock Resolver: return "Lorem Ipsum" } } - ``` It is possible to define more resolvers for Object types: ```javascript - { // This will be the default values for User object in the query response User() { @@ -94,7 +91,6 @@ It is possible to define more resolvers for Object types: }; }, } - ``` ### Mock Resolver Context @@ -102,7 +98,6 @@ It is possible to define more resolvers for Object types: The first argument of the MockResolver is the object that contains Mock Resolver Context. It is possible to return dynamic values from mock resolvers based on the context - for instance, name or alias of the field, a path in the selection, arguments, or parent type. ```javascript - { String(context) { if (context.name === 'zip') { @@ -116,7 +111,6 @@ The first argument of the MockResolver is the object that contains Mock Resolver } } } - ``` ### ID Generation @@ -124,14 +118,12 @@ The first argument of the MockResolver is the object that contains Mock Resolver The second argument of the Mock Resolver its a function that will generate a sequence of integers, useful to generate unique IDs in the tests: ```javascript - { // will generate strings "my-id-1", "my-id-2", etc. ID(_, generateId) { return `my-id-${generateId()}`; }, } - ``` ### `@relay_test_operation` @@ -141,7 +133,6 @@ Most of GraphQL type information for a specific field in the selection is not av Operations with the `@relay_test_operation` directive will have additional metadata that will contain GraphQL type info for fields in the operation's selection. And it will improve the quality of the generated data. You also will be able to define Mock resolvers for Scalar (not only ID and String) and Abstract types: ```javascript - { Float() { return 123.456; @@ -159,7 +150,6 @@ Operations with the `@relay_test_operation` directive will have additional metad }; } } - ``` ## Examples @@ -169,7 +159,6 @@ Operations with the `@relay_test_operation` directive will have additional metad Using `createMockEnvironment` and `MockPayloadGenerator` allows writing concise tests for components that are using Relay Containers and Renderers. Both those modules can be imported from `relay-test-utils`. ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { @@ -222,7 +211,6 @@ test('Error State', () => { renderer.root.find(item => (item.props.testID = 'errorMessage')), ).toBeDefined(); }); - ``` ### Fragment Container Tests @@ -230,7 +218,6 @@ test('Error State', () => { Essentially, in the example above, `resolveMostRecentOperation` will generate data for all child fragment containers (pagination, refetch). Usually, the Root Components container may have many child fragment components and you may want to exercise a specific Fragment Container. The solution for that would be to wrap your fragment container with the QueryRenderer that renders a Query that's spreads fragments from your fragment container. ```javascript - test('Fragment Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -261,7 +248,6 @@ test('Fragment Container', () => { expect(renderer).toMatchSnapshot(); }); - ``` ### Pagination Container Test @@ -269,7 +255,6 @@ test('Fragment Container', () => { Essentially, tests for Pagination container are not different from Fragment Container tests. We can also do more here. We can actually see how the pagination works by asserting the behavior of our components when performing pagination (load more, refetch). ```javascript - // Pagination Example test('Pagination Container', () => { const environment = createMockEnvironment(); @@ -343,7 +328,6 @@ test('Pagination Container', () => { We can use similar approach here with wrapping container with Query Renderer. And for the sake of completeness, we will add example here: ```javascript - test('Refetch Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -385,7 +369,6 @@ test('Refetch Container', () => { ); // expect(renderer).toMatchSnapshot(); }); - ``` ### Mutations @@ -393,7 +376,6 @@ test('Refetch Container', () => { Mutations itself are operations so we can test them independently (unit-test) for specific mutation, or in combination with the view from which this mutation is called. ```javascript - // Say, you have a mutation function function sendMutation(environment, onCompleted, onError, variables) commitMutation(environment, { @@ -416,7 +398,6 @@ test('it should send mutation', () => { ); expect(onCompleted).toBeCalled(); }); - ``` ### Subscription @@ -424,7 +405,6 @@ test('it should send mutation', () => { We can test subscription in a similar way we test mutations ```javascript - // Example subscribe function function subscribe(environment, onNext, onError, variables) requestSubscription(environment, { @@ -447,7 +427,6 @@ test('it should subscribe', () => { ); expect(onNext).toBeCalled(); }); - ``` ### Example with `queueOperationResolver` @@ -455,7 +434,6 @@ test('it should subscribe', () => { With `queueOpeararionResolver`, it possible to define responses for operations that will be executed on the environment ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { diff --git a/website/versioned_docs/version-v1.6.0/Modern-TypeEmission.md b/website/versioned_docs/version-v1.6.0/Modern-TypeEmission.md index c25bc737d5684..9f41810a3618b 100644 --- a/website/versioned_docs/version-v1.6.0/Modern-TypeEmission.md +++ b/website/versioned_docs/version-v1.6.0/Modern-TypeEmission.md @@ -15,7 +15,6 @@ In this example the emitted type-information would require the variables object #### Flow ```javascript - /** * export type ExampleQueryVariables = {| * +artistID: string @@ -43,7 +42,6 @@ const variables: ExampleQueryVariables = { #### TypeScript ```javascript - /** * export type ExampleQueryVariables = { * readonly artistID: string @@ -78,7 +76,6 @@ In this example the emitted type-information describes the response data availab #### Flow ```javascript - /** * export type ExampleQueryResponse = {| * +artist: ?{| @@ -109,7 +106,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * export type ExampleQueryResponse = { * readonly artist?: { @@ -145,7 +141,6 @@ Similarly, in this example the emitted type-information describes the prop data #### Flow ```javascript - /** * export type ExampleFragment_artist = {| * +name: string @@ -171,7 +166,6 @@ export const ExampleFragment = createFragmentContainer( #### TypeScript ```javascript - /** * export type ExampleFragment_artist = { * readonly name: string @@ -205,7 +199,6 @@ Consider a component that composes the above fragment container example. In this #### Flow ```javascript - /** * import type { FragmentReference } from "relay-runtime"; * declare export opaque type ExampleFragment_artist$ref: FragmentReference; @@ -249,7 +242,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * declare const _ExampleFragment_artist$ref: unique symbol; * export type ExampleFragment_artist$ref = typeof _ExampleFragment_artist$ref; @@ -314,7 +306,6 @@ $ relay-compiler --artifactDirectory ./src/__generated__ […] ["relay", { "artifactDirectory": "./src/__generated__" }] ] } - ``` It is recommended to alias this directory in your module resolution configuration such that you don’t need to specify relative paths in your source files. This is what is also done in the above examples, where artifacts are imported from a `__generated__` alias, rather than relative paths like `../../../../__generated__`. diff --git a/website/versioned_docs/version-v1.6.0/Modern-UpgradingSetVariables.md b/website/versioned_docs/version-v1.6.0/Modern-UpgradingSetVariables.md index d5b086fafce20..ff73feec04f8b 100644 --- a/website/versioned_docs/version-v1.6.0/Modern-UpgradingSetVariables.md +++ b/website/versioned_docs/version-v1.6.0/Modern-UpgradingSetVariables.md @@ -36,7 +36,6 @@ fragment on User { # ... } } - ``` This should be upgraded to use a [`PaginationContainer`](./pagination-container). @@ -61,7 +60,6 @@ fragment on User { # ... } } - ``` This can be upgraded by using a [`RefetchContainer`](./refetch-container) which allows you to specify the exact query to use to fetch the new data. @@ -86,7 +84,6 @@ fragment on FeedbackTarget { # ... } } - ``` This can be upgraded by conditionally rendering a [`QueryRenderer`](./query-renderer) which will load the data once it is rendered. The code overhead of doing this is dramatically reduced with the new API. diff --git a/website/versioned_docs/version-v1.6.0/Modern-fetchQuery.md b/website/versioned_docs/version-v1.6.0/Modern-fetchQuery.md index 19e9b57c4219a..223c01ccc75c2 100644 --- a/website/versioned_docs/version-v1.6.0/Modern-fetchQuery.md +++ b/website/versioned_docs/version-v1.6.0/Modern-fetchQuery.md @@ -5,7 +5,6 @@ title: fetchQuery You can use the `fetchQuery` function to imperatively make GraphQL Requests. This is useful for cases where you want to make requests outside of React but still utilize the Relay store and network layer. ```javascript - import {fetchQuery, graphql} from 'relay-runtime'; const query = graphql` @@ -24,7 +23,6 @@ fetchQuery(environment, query, variables) .then(data => { // access the graphql response }); - ``` ## Arguments diff --git a/website/versioned_docs/version-v1.6.0/PrinciplesAndArchitecture-Compiler.md b/website/versioned_docs/version-v1.6.0/PrinciplesAndArchitecture-Compiler.md index c195491682b1f..fcd0490cb724f 100644 --- a/website/versioned_docs/version-v1.6.0/PrinciplesAndArchitecture-Compiler.md +++ b/website/versioned_docs/version-v1.6.0/PrinciplesAndArchitecture-Compiler.md @@ -74,7 +74,6 @@ foo { # type FooType foo { id } - ``` - `SkipRedundantNodeTransform`: A more advanced version of flattening, this eliminates more complex cases of field duplication such as when a field is fetched both unconditionally and conditionally, or is fetched by two different sub-fragments. For example: @@ -97,7 +96,6 @@ foo { id } } - ``` - `GenerateRequisiteFieldTransform`: This optional, Relay-specific transform inserts `id` fields for globally identifiable objects and `__typename` fields wherever the type cannot be statically determined (e.g. for unions). diff --git a/website/versioned_docs/version-v1.6.0/PrinciplesAndArchitecture-Runtime.md b/website/versioned_docs/version-v1.6.0/PrinciplesAndArchitecture-Runtime.md index f012908d090c5..e9c88a4b2ae0c 100644 --- a/website/versioned_docs/version-v1.6.0/PrinciplesAndArchitecture-Runtime.md +++ b/website/versioned_docs/version-v1.6.0/PrinciplesAndArchitecture-Runtime.md @@ -77,7 +77,6 @@ RecordSource { city: 'Seattle', } } - ``` [1] Note that GraphQL itself does not impose this constraint, and Relay Runtime may also be used for schemas that do not conform to it. For example, both systems can be used to query a single denormalized table. However, many of the features that Relay Runtime provides, such as caching and normalization, work best when the data is represented as a normalized graph with stable identities for discrete pieces of information. diff --git a/website/versioned_docs/version-v1.6.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md b/website/versioned_docs/version-v1.6.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md index 14b1119288f23..9527e65e8950e 100644 --- a/website/versioned_docs/version-v1.6.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md +++ b/website/versioned_docs/version-v1.6.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md @@ -12,7 +12,6 @@ In this article we'll explore what it means to build a GraphQL client framework Imagine we have a simple application that fetches a list of stories, and some details about each one. Here's how that might look in resource-oriented REST: ```javascript - // Fetch the list of story IDs but not their details: rest.get('/stories').then(stories => // This resolves to a list of items with linked resources: @@ -25,13 +24,11 @@ rest.get('/stories').then(stories => // `[ { id: "...", text: "..." } ]` console.log(stories); }); - ``` Note that this approach requires _n+1_ requests to the server: 1 to fetch the list, and _n_ to fetch each item. With GraphQL we can fetch the same data in a single network request to the server (without creating a custom endpoint that we'd then have to maintain): ```javascript - graphql.get(`query { stories { id, text } }`).then( stories => { // A list of story items: @@ -39,7 +36,6 @@ graphql.get(`query { stories { id, text } }`).then( console.log(stories); } ); - ``` So far we're just using GraphQL as a more efficient version of typical REST approaches. Note two important benefits in the GraphQL version: @@ -56,7 +52,6 @@ Repeatedly refetching information from the server can get quite slow. For exampl In a resource-oriented REST system, we can maintain a **response cache** based on URIs: ```javascript - var _cache = new Map(); rest.get = uri => { if (!_cache.has(uri)) { @@ -64,13 +59,11 @@ rest.get = uri => { } return _cache.get(uri); }; - ``` Response-caching can also be applied to GraphQL. A basic approach would work similarly to the REST version. The text of the query itself can be used as a cache key: ```javascript - var _cache = new Map(); graphql.get = queryText => { if (!_cache.has(queryText)) { @@ -78,7 +71,6 @@ graphql.get = queryText => { } return _cache.get(queryText); }; - ``` Now, requests for previously cached data can be answered immediately without making a network request. This is a practical approach to improving the perceived performance of an application. However, this method of caching can cause problems with data consistency. @@ -90,7 +82,6 @@ With GraphQL it is very common for the results of multiple queries to overlap. H ``` query { stories { id, text, likeCount } } - ``` and then later refetch one of the stories whose `likeCount` has since been incremented: @@ -98,7 +89,6 @@ and then later refetch one of the stories whose `likeCount` has since been incre ``` query { story(id: "123") { id, text, likeCount } } - ``` We'll now see different `likeCount`s depending on how the story is accessed. A view that uses the first query will see an outdated count, while a view using the second query will see the updated count. @@ -119,7 +109,6 @@ query { } } } - ``` And here's a possible response: @@ -134,13 +123,11 @@ query: { } } } - ``` Although the response is hierarchical, we'll cache it by flattening all the records. Here is an example of how Relay would cache this query response: ```javascript - Map { // `story(id: "1")` 1: Map { @@ -152,7 +139,6 @@ Map { name: 'Jan', }, }; - ``` This is only a simple example: in reality the cache must handle one-to-many associations and pagination (among other things). @@ -182,7 +168,6 @@ The first query was for a list of stories: ``` query { stories { id, text, likeCount } } - ``` With a normalized response cache, a record would be created for each story in the list. The `stories` field would store links to each of these records. @@ -192,7 +177,6 @@ The second query refetched the information for one of those stories: ``` query { story(id: "123") { id, text, likeCount } } - ``` When this response is normalized, Relay can detect that this result overlaps with existing data based on its `id`. Rather than create a new record, Relay will update the existing `123` record. The new `likeCount` is therefore available to _both_ queries, as well as any other query that might reference this story. @@ -215,7 +199,6 @@ query { } } } - ``` After initially fetching this story our cache might be as follows. Note that the story and comment both link to the same record as `author`: @@ -242,7 +225,6 @@ Map { author: Link(2), }, } - ``` The author of this story also commented on it — quite common. Now imagine that some other view fetches new information about the author, and her profile photo has changed to a new URI. Here's the _only_ part of our cached data that changes: @@ -256,7 +238,6 @@ Map { photo: 'http://.../photo2.jpg', }, } - ``` The value of the `photo` field has changed; and therefore the record `2` has also changed. And that's it. Nothing else in the _cache_ is affected. But clearly our _view_ needs to reflect the update: both instances of the author in the UI (as story author and comment author) need to show the new photo. @@ -273,7 +254,6 @@ ImmutableMap { }, 3: ImmutableMap // same as before } - ``` If we replace `2` with a new immutable record, we'll also get a new immutable instance of the cache object. However, records `1` and `3` are untouched. Because the data is normalized, we can't tell that `story`'s contents have changed just by looking at the `story` record alone. @@ -299,7 +279,6 @@ mutation StoryLike($storyID: String) { likeCount } } - ``` Notice that we're querying for data that _may_ have changed as a result of the mutation. An obvious question is: why can't the server just tell us what changed? The answer is: it's complicated. GraphQL abstracts over _any_ data storage layer (or an aggregation of multiple sources), and works with any programming language. Furthermore, the goal of GraphQL is to provide data in a form that is useful to product developers building a view. diff --git a/website/versioned_docs/version-v1.6.0/PrinciplesAndArchitecture-ThinkingInRelay.md b/website/versioned_docs/version-v1.6.0/PrinciplesAndArchitecture-ThinkingInRelay.md index 47c27f92ab909..1ffea144589ad 100644 --- a/website/versioned_docs/version-v1.6.0/PrinciplesAndArchitecture-ThinkingInRelay.md +++ b/website/versioned_docs/version-v1.6.0/PrinciplesAndArchitecture-ThinkingInRelay.md @@ -30,13 +30,11 @@ fragment Story_story on Story { photo } } - ``` And this fragment can then be used to define the Story container: ```javascript - const {createFragmentContainer, graphql} = require('react-relay'); // Plain React component. @@ -64,7 +62,6 @@ const StoryContainer = createFragmentContainer(Story, { In React, rendering a view requires two inputs: the _component_ to render, and a _root_ DOM (UI) node to render into. Rendering Relay containers is similar: we need a _container_ to render, and a _root_ in the graph from which to start our query. We also must ensure that the queries for the container are executed and may want to show a loading indicator while data is being fetched. Similar to `ReactDOM.render(component, domNode)`, Relay provides `` for this purpose. The `query` and `variables` define what data to fetch and `render` defines what to render. Here's how we might render ``: ```javascript - ReactDOM.render( { ); } } - ``` The above code is doing something very similar to our [previous example](#rendering-graphql-queries), however, we are now passing a `$userID` variable to the GraphQL query, via the `variables` prop. This has a couple of important implications: @@ -229,7 +217,6 @@ Now that we know how to define and fetch queries, let's actually start building First, let's start at the bottom; let's say that we want to render a component that given a todo item, simply displays the item's text and completed state: ```javascript - // Todo.js import React from 'react'; @@ -259,7 +246,6 @@ export default class Todo extends React.Component { ); } } - ``` From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L107), we know that we can query this data on the `Todo` type. However, we don't want to have to send a separate query for each todo item; that would defeat the purpose of using GraphQL over a traditional REST API. We could manually query for these fields directly in our `QueryRenderer` query, but that would hurt re-usability: what if we want to query the same set of fields as part of a different query? Additionally, we wouldn't know which component needs the data we're querying, a problem Relay directly tries to address. @@ -267,18 +253,15 @@ From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/dat Instead, we can define a reusable [Fragment](http://graphql.org/learn/queries/#fragments), which allows us to define a set of fields on a type and reuse them within our queries wherever we need to: ```graphql - fragment TodoItemFragment on Todo { complete text } - ``` Our component can then use this fragment to declare its data dependency on the `Todo` GraphQL type: ```javascript - // Todo.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -338,7 +321,6 @@ Before proceeding, don't forget to run the Relay Compiler with `yarn relay`. Given that [Fragment Containers](./fragment-container) are just React components, we can compose them as such, and even re-use fragment containers within other fragment containers. As an example, let's see how we would define a `TodoList` component that just renders a list of todo items, and whether all have been completed or not: ```javascript - // TodoList.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -397,7 +379,6 @@ export default createFragmentContainer( } `, ); - ``` As with the first fragment container we defined, `TodoList` declares it's data dependencies via a fragment. However, this component additionally re-uses the fragment previously defined by the `Todo` component, and passes the appropriate data to when rendering the child `Todo` components (a.k.a. fragment containers). @@ -412,7 +393,6 @@ fragment containers do not directly fetch data. Instead, containers declare a sp A `QueryRenderer` rendering these fragment containers could look like the following: ```javascript - // ViewerTodoList.js import React from 'react'; import PropTypes from 'prop-types'; @@ -454,7 +434,6 @@ export default ViewerTodoList extends React.Component { ); } } - ``` Check out or docs for [Fragment Containers](./fragment-container) for more details, and our guides on [Refetch](./refetch-container) and [Pagination](./pagination-container) for more advanced usage of containers. @@ -466,7 +445,6 @@ Now that we know how to query for and render data, let's move on to changing our From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L35), we know that we have some mutations available to us, so let's start by writing a mutation to change the `complete` status of a given todo item (i.e. mark or unmark it as done): ```graphql - mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { changeTodoStatus(input: $input) { todo { @@ -475,7 +453,6 @@ mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { } } } - ``` This mutation allows us to query back some data as a [result of the mutation](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L18), so we're going to query for the updated `complete` status on the todo item. @@ -483,7 +460,6 @@ This mutation allows us to query back some data as a [result of the mutation](ht In order to execute this mutation in Relay, we're going to write a new mutation using Relay's `commitMutation` api: ```javascript - // ChangeTodoStatusMutation.js import {graphql, commitMutation} from 'react-relay'; @@ -517,7 +493,6 @@ function commit( } export default {commit}; - ``` Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mutation to the server, and in our case, upon receiving a response it will automatically update the local data store with the latest data from the server. This also means that upon receiving the response, Relay will ensure that any components (i.e. containers) that depend on the updated data are re-rendered. @@ -525,7 +500,6 @@ Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mut In order to actually use this mutation in our component, we could update our `Todo` component in the following way: ```javascript - // Todo.js // ... @@ -559,7 +533,6 @@ In order to make the experience better, we can configure our mutation to do an o In Relay, there's a couple of options we can pass to `commitMutation` to enable optimistic updates. Let's see what that would look like in our `ChangeTodoStatusMutation`: ```javascript - // ChangeTodoStatusMutation.js // ... @@ -594,7 +567,6 @@ function commit( } export default {commit}; - ``` In the simplest case above, we just need to pass an `optimisticResponse` option, which should refer to an object having the same shape as the mutation response payload. When we pass this option, Relay will know to immediately update our local data with the optimistic response, and then update it with the actual server response, or roll it back if an error occurs. diff --git a/website/versioned_docs/version-v1.6.1/Modern-ConvertingMutations.md b/website/versioned_docs/version-v1.6.1/Modern-ConvertingMutations.md index 288ac18ab0872..96410a4589cef 100644 --- a/website/versioned_docs/version-v1.6.1/Modern-ConvertingMutations.md +++ b/website/versioned_docs/version-v1.6.1/Modern-ConvertingMutations.md @@ -12,19 +12,16 @@ FatQueries in Relay Classic mutations was a concept that was confusing for a num Example of existing fat query: ```javascript - RelayClassic.QL` fragment on MarkReadNotificationResponsePayload @relay(pattern: true) { notification } `; - ``` Example of converted mutation query: ```javascript - graphql` mutation MarkReadNotificationMutation( $input: MarkReadNotificationData! @@ -37,7 +34,6 @@ graphql` } } `; - ``` ## Migrating Configs @@ -63,7 +59,6 @@ This is no longer needed in Compatibility Mode for neither environments. Relay w Take this example of a simple mutation in Relay Classic: ```javascript - class LikeStoryMutation extends RelayClassic.Mutation { getMutation() { return RelayClassic.QL`mutation {likeStory}`; @@ -102,7 +97,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { `, }; } - ``` ### Converting `getMutation()` and `getFatQuery()` @@ -110,7 +104,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { We combine these two into a regular GraphQL mutation, which list out specific fields that needs to be updated. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story(data: $input) { @@ -122,7 +115,6 @@ const mutation = graphql` } } `; - ``` ### Converting `getConfigs()` @@ -134,13 +126,11 @@ As specified above, `FIELDS_CHANGE` configs can be omitted. To convert `getVariables()`, we take the return value from the original function and wrap it in an object that contains a property that matches the variable name for the mutation. In this case, the mutation has a `input` variable that is of type `LikeStoryData`. ```javascript - const variables = { input: { storyID: args.storyID } } - ``` ### Final Result @@ -148,7 +138,6 @@ const variables = { As you can see, our resulting mutation is a lot simpler and more like regular GraphQL than the Relay Classic version we started out with. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story { @@ -174,7 +163,6 @@ function commit(environment: CompatEnvironment, args) { variables, }); } - ``` See [Mutation](./mutations) for additional options on `commitMutation` for more complex mutations. diff --git a/website/versioned_docs/version-v1.6.1/Modern-FragmentContainer.md b/website/versioned_docs/version-v1.6.1/Modern-FragmentContainer.md index e86b79995c1c7..7bbd0a9f22899 100644 --- a/website/versioned_docs/version-v1.6.1/Modern-FragmentContainer.md +++ b/website/versioned_docs/version-v1.6.1/Modern-FragmentContainer.md @@ -17,12 +17,10 @@ Table of Contents: `createFragmentContainer` has the following signature: ```javascript - createFragmentContainer( component: ReactComponentClass, fragmentSpec: GraphQLTaggedNode | {[string]: GraphQLTaggedNode}, ): ReactComponentClass; - ``` ### Arguments @@ -46,7 +44,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -61,7 +58,6 @@ To start, let's build the plain React version of a hypothetical `` c Here's a basic implementation of `` that ignores styling in order to highlight the functionality: ```javascript - // TodoItem.js class TodoItem extends React.Component { render() { @@ -81,7 +77,6 @@ class TodoItem extends React.Component { ); } } - ``` ### Data Dependencies With GraphQL @@ -89,7 +84,6 @@ class TodoItem extends React.Component { In Relay, data dependencies are described using [GraphQL](https://github.com/facebook/graphql). For ``, the dependency can be expressed as follows. Note that this exactly matches the shape that the component expected for the `item` prop. ```javascript - graphql` # This fragment only applies to objects of type 'Todo'. fragment TodoItem_item on Todo { @@ -105,7 +99,6 @@ graphql` Given the plain React component and a GraphQL fragment, we can now define a Fragment Container to specify this component's data requirements. Let's look at the code first and then see what's happening: ```javascript - // TodoItem.js import {createFragmentContainer, graphql} from 'react-relay'; @@ -123,13 +116,11 @@ export default createFragmentContainer(TodoItem, { } `, }); - ``` Relay will infer the prop name from the fragment name according to the fragment naming convention `<...>_`. The example below is equivalent to the one above: ```javascript - export default createFragmentContainer( TodoItem, graphql` @@ -139,13 +130,11 @@ export default createFragmentContainer( } `, ); - ``` If there is no `_` suffix, the `data` prop name will be used: ```javascript - class TodoItem extends React.Component { render() { const item = this.props.data; @@ -162,7 +151,6 @@ export default createFragmentContainer( } `, ); - ``` ## Container Composition @@ -176,7 +164,6 @@ Let's explore how this works via a `` component that composes the `< View composition is _exactly_ what you're used to — Relay containers are just standard React components. Here's the `` component: ```javascript - class TodoList extends React.Component { render() { // Expects a `list` with a string `title`, as well as the information @@ -191,7 +178,6 @@ class TodoList extends React.Component { ); } } - ``` ### Composing Fragments @@ -199,7 +185,6 @@ class TodoList extends React.Component { Fragment composition works similarly — a parent container's fragment composes the fragment for each of its children. In this case, `` needs to fetch information about the `Todo`s that are required by ``. ```javascript - class TodoList extends React.Component // as above export default createFragmentContainer( @@ -217,7 +202,6 @@ export default createFragmentContainer( } `, ); - ``` Note that when composing fragments, the type of the composed fragment must match the field on the parent in which it is embedded. For example, it wouldn't make sense to embed a fragment of type `Story` into a parent's field of type `User`. Relay and GraphQL will provide helpful error messages if you get this wrong (and if they aren't helpful, let us know!). @@ -231,7 +215,6 @@ When defining a fragment, you can use the [`@argumentDefinitions`](./graphql-in- For example, let's redefine our `TodoList_list` fragment to take some arguments using `@argumentDefinitions`: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -241,7 +224,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` Any arguments defined inside `@argumentDefinitions` will be local variables available inside the fragment's scope. However, a fragment can also reference global variables that were defined in the root query. @@ -253,11 +235,9 @@ In order to pass arguments to a fragment that has `@argumentDefinitions`, you ne Following our `TodoList_list` example, we would pass arguments to the fragment like so: ```graphql - query TodoListQuery($count: Int, $userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` ### Calling Component Instance Methods @@ -268,7 +248,6 @@ Since Relay composes these component instances in a container, you need to use t Consider an input with a server-defined placeholder text and an imperative method to focus the input node: ```javascript - export default createFragmentContainer( class TodoInput extends React.Component { focus() { @@ -288,13 +267,11 @@ export default createFragmentContainer( } `, ); - ``` To call this method on the underlying component, first provide a `componentRef` function to the Relay container. This differs from providing a [`ref`](https://facebook.github.io/react/docs/refs-and-the-dom.html) function which would provide a reference to the Relay container itself, not the underlying React Component. ```javascript - export default createFragmentContainer( class TodoListView extends React.Component { render() { @@ -312,7 +289,6 @@ export default createFragmentContainer( } `, ); - ``` ## Rendering Containers diff --git a/website/versioned_docs/version-v1.6.1/Modern-GraphQLInRelay.md b/website/versioned_docs/version-v1.6.1/Modern-GraphQLInRelay.md index 45ed05dc9670e..7cb555b6ce502 100644 --- a/website/versioned_docs/version-v1.6.1/Modern-GraphQLInRelay.md +++ b/website/versioned_docs/version-v1.6.1/Modern-GraphQLInRelay.md @@ -14,7 +14,6 @@ Table of Contents: The `graphql` template tag provided by Relay serves as the mechanism to write queries, fragments, mutations or subscriptions in the [GraphQL](http://graphql.org/learn/) language. For example: ```javascript - import {graphql} from 'react-relay'; graphql` @@ -24,7 +23,6 @@ graphql` } } `; - ``` The result of using the `graphql` template tag are `GraphQLTaggedNode`s, which are used to define [Query Renderers](./query-renderer), [Fragment Containers](./fragment-container), [Refetch Containers](./refetch-container), [Pagination Containers](./pagination-container), etc. @@ -42,11 +40,9 @@ Relay uses directives to add additional information to GraphQL documents, which `@arguments` is a directive used to pass arguments to a fragment that was defined using [`@argumentDefinitions`](#argumentdefinitions). For example: ```graphql - query TodoListQuery($userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` See [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -56,7 +52,6 @@ See [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragme `@argumentDefinitions` is a directive used to specify arguments taken by a fragment. For example: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -66,7 +61,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` See [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -82,13 +76,11 @@ When using the [Pagination Container](./pagination-container), Relay expects con When defining a fragment, you can use the `@relay(plural: true)` directive to indicate that the fragment is backed by a [GraphQL list](http://graphql.org/learn/schema/#lists-and-non-null), meaning that it will inform Relay that this particular field is an array. For example: ```javascript - graphql` fragment TodoItems_items on TodoItem @relay(plural: true) { id text }`; - ``` ### `@relay(mask: Boolean)` @@ -104,7 +96,6 @@ Keep in mind that it is typically considered an **anti-pattern** to create a sin In the example below, the `user` prop will include the data for `id` and `name` fields wherever `...Component_internUser` is included, instead of Relay's normal behavior to mask those fields: ```javascript - graphql` fragment Component_internUser on InternUser { id @@ -132,7 +123,6 @@ export default createFragmentContainer( } `, ); - ``` ## Relay Compiler @@ -142,7 +132,6 @@ Relay uses the Relay Compiler to convert [`graphql`](#graphql) literals into gen A query like the following: ```javascript - graphql` fragment MyComponent on Type { field @@ -166,7 +155,6 @@ See our relay-compiler section in our [Installation and Setup guide](./installat To use the Relay Compiler, you need either a .graphql or .json GraphQL schema file, describing your GraphQL server's API. Typically these files are local representations of a server source of truth and are not edited directly. For example, we might have a `schema.graphql` like: ```graphql - schema { query: Root } @@ -184,7 +172,6 @@ type WordDefinition { text: String image: String } - ``` ### Source files @@ -200,7 +187,6 @@ For example, given the two files: - `src/Components/DictionaryComponent.js` ```javascript - const DictionaryWordFragment = graphql` fragment DictionaryComponent_word on Word { id @@ -222,7 +208,6 @@ For example, given the two files: - `src/Queries/DictionaryQuery.js` ```javascript - const DictionaryQuery = graphql` query DictionaryQuery { dictionary { @@ -246,9 +231,7 @@ Typically you will not need to import your generated definitions. The [Relay Bab However the Relay Compiler also automatically generates [Flow](https://flow.org) types as [type comments](https://flow.org/en/docs/types/comments/). For example, you can import the generated flow types like so: ```javascript - import type {DictionaryComponent_word} from './__generated__/DictionaryComponent_word.graphql'; - ``` ### Advanced usage diff --git a/website/versioned_docs/version-v1.6.1/Modern-LocalStateManagement.md b/website/versioned_docs/version-v1.6.1/Modern-LocalStateManagement.md index f3427f392a611..dc50079ca5fbe 100644 --- a/website/versioned_docs/version-v1.6.1/Modern-LocalStateManagement.md +++ b/website/versioned_docs/version-v1.6.1/Modern-LocalStateManagement.md @@ -23,23 +23,19 @@ It can even be used to extend an existing server schema. For example, we can create a new type called `Note`: ```graphql - type Note { id: ID! title: String body: String } - ``` And then extend the server schema type `User`, with a list of `Note`, called `notes`. ```graphql - extend type User { notes: [Note] } - ``` ## Querying local state @@ -50,7 +46,6 @@ The field can be from the server schema, or it can be schema agnostic, like an i Here, we use a [QueryRenderer](./query-renderer) to get the current `User` via the `viewer` field, along with their id, name and the local list of notes. ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -96,7 +91,6 @@ const Example = (props) => { /> ); } - ``` ## Mutating local state @@ -110,7 +104,6 @@ To build upon the previous example, let's try creating, updating and deleting a ### Create ```javascript - import {commitLocalUpdate} from 'react-relay'; let tempID = 0; @@ -130,7 +123,6 @@ function createUserNote() { user.setLinkedRecords([...userNoteRecords, newNoteRecord], 'notes'); }); } - ``` Note that since this record will be rendered by the `ExampleQuery` in our `QueryRenderer`, the QueryRenderer will automatically retain this data so it isn't garbage collected. @@ -138,7 +130,6 @@ Note that since this record will be rendered by the `ExampleQuery` in our `Query If no component is rendering the local data and you want to manually retain it, you can do so by calling `environment.retain()`: ```javascript - import {createOperationDescriptor, getRequest} from 'relay-runtime'; // Create a query that references that record @@ -165,13 +156,11 @@ const disposable = environment.retain(operation); // Whenever you don't need that data anymore and it's okay for Relay to garbage collect it, // you can dispose of the retain disposable.dispose(); - ``` ### Update ```javascript - import {commitLocalUpdate} from 'react-relay'; function updateUserNote(dataID, body, title) { @@ -182,13 +171,11 @@ function updateUserNote(dataID, body, title) { note.setValue(title, 'title') }); } - ``` ### Delete ```javascript - import {commitLocalUpdate} from 'react-relay'; function deleteUserNote(dataID) { @@ -206,7 +193,6 @@ function deleteUserNote(dataID) { user.setLinkedRecords(newUserNoteRecords, 'notes'); }); } - ``` ## Initial local state @@ -215,7 +201,6 @@ All new client-side schema fields default to `undefined` value. Often however, y You can use an updater function via `commitLocalUpdate` to prime local state. ```javascript - import {commitLocalUpdate} from 'react-relay'; commitLocalUpdate(environment, store => { @@ -224,5 +209,4 @@ commitLocalUpdate(environment, store => { // initialize user notes to an empty array. user.setLinkedRecords([], 'notes'); }); - ``` diff --git a/website/versioned_docs/version-v1.6.1/Modern-MigrationSetup.md b/website/versioned_docs/version-v1.6.1/Modern-MigrationSetup.md index 66f1145357e25..a89c0e178e0e5 100644 --- a/website/versioned_docs/version-v1.6.1/Modern-MigrationSetup.md +++ b/website/versioned_docs/version-v1.6.1/Modern-MigrationSetup.md @@ -13,13 +13,11 @@ With some additional configuration, the `"relay"` babel plugin can also translat Relay Classic `Relay.QL` literals. Most importantly, include a reference to your GraphQL Schema as either a json file or graphql schema file. ```javascript - { "plugins": [ ["relay", {"schema": "path/schema.graphql"}] ] } - ``` ## Set up babel-plugin-relay for "[compatibility mode](./relay-compat)" @@ -29,13 +27,11 @@ literals can be translated to be usable by _both_ runtimes if configured to use compatibility mode: ```javascript - { "plugins": [ ["relay", {"compat": true, "schema": "path/schema.graphql"}] ] } - ``` ## Additional Options @@ -47,7 +43,6 @@ thrown at runtime. When compiling code for production deployment, the plugin can be configured to immediately throw upon encountering a validation problem. The plugin can be further customized for different environments with the following options: ```javascript - { "plugins": [ ["relay", { @@ -56,5 +51,4 @@ When compiling code for production deployment, the plugin can be configured to i }] ] } - ``` diff --git a/website/versioned_docs/version-v1.6.1/Modern-Mutations.md b/website/versioned_docs/version-v1.6.1/Modern-Mutations.md index d879216bdd5e3..ebb1797237203 100644 --- a/website/versioned_docs/version-v1.6.1/Modern-Mutations.md +++ b/website/versioned_docs/version-v1.6.1/Modern-Mutations.md @@ -16,7 +16,6 @@ Table of Contents: Use `commitMutation` to create and execute mutations. `commitMutation` has the following signature: ```javascript - commitMutation( environment: Environment, config: { @@ -30,7 +29,6 @@ commitMutation( configs?: Array, }, ); - ``` ### Arguments @@ -57,7 +55,6 @@ commitMutation( Example of a simple mutation: ```javascript - import {commitMutation, graphql} from 'react-relay'; const mutation = graphql` @@ -92,7 +89,6 @@ function markNotificationAsRead(environment, source, storyID) { }, ); } - ``` ## Optimistic Updates @@ -100,7 +96,6 @@ function markNotificationAsRead(environment, source, storyID) { To improve perceived responsiveness, you may wish to perform an "optimistic update", in which the client immediately updates to reflect the anticipated new value even before the response from the server has come back. The simplest way to do this is by providing an `optimisticResponse` and adding it to the `config` that we pass into `commitMutation`: ```javascript - const mutation = graphql` mutation MarkReadNotificationMutation( $input: MarkReadNotificationData! @@ -129,7 +124,6 @@ commitMutation( variables, }, ); - ``` Another way to enable optimistic updates is via the `optimisticUpdater`, which can be used for more complicated update scenarios. Using `optimisticUpdater` is covered in the section [below](#using-updater-and-optimisticupdater). @@ -149,7 +143,6 @@ Given a deletedIDFieldName, Relay will remove the node(s) from the connection. #### Example ```javascript - const mutation = graphql` mutation DestroyShipMutation($input: DestroyShipData!) { destroyShip(input: $input) { @@ -167,7 +160,6 @@ const configs = [{ type: 'NODE_DELETE', deletedIDFieldName: 'destroyedShipId', }]; - ``` ### RANGE_ADD @@ -187,7 +179,6 @@ Given a parent, information about the connection, and the name of the newly crea #### Example ```javascript - const mutation = graphql` mutation AddShipMutation($input: AddShipData!) { addShip(input: $input) { @@ -210,7 +201,6 @@ const configs = [{ }], edgeName: 'newShipEdge', }]; - ``` ### RANGE_DELETE @@ -232,7 +222,6 @@ from the connection but leave the associated record(s) in the store. #### Example ```javascript - const mutation = graphql` mutation RemoveTagsMutation($input: RemoveTagsData!) { removeTags(input: $input) { @@ -255,7 +244,6 @@ const configs = [{ pathToConnection: ['todo', 'tags'], deletedIDFieldName: removedTagId }]; - ``` ## Using updater and optimisticUpdater @@ -273,7 +261,6 @@ When you provide these functions, this is roughly what happens during the mutati Here are a quick example of adding a todo item to a Todo list using this [example schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L36): ```javascript - // AddTodoMutation.js import {commitMutation, graphql} from 'react-relay'; import {ConnectionHandler} from 'relay-runtime'; @@ -365,7 +352,6 @@ function commit( } ); } - ``` For details on how to interact with the Relay Store, please refer to our Relay Store [docs](./relay-store). diff --git a/website/versioned_docs/version-v1.6.1/Modern-NetworkLayer.md b/website/versioned_docs/version-v1.6.1/Modern-NetworkLayer.md index c5813a18609e8..e0d5a012a0ecf 100644 --- a/website/versioned_docs/version-v1.6.1/Modern-NetworkLayer.md +++ b/website/versioned_docs/version-v1.6.1/Modern-NetworkLayer.md @@ -8,7 +8,6 @@ In order to know how to access your GraphQL server, Relay Modern requires develo Currently the easiest way to create a network layer is via a helper from the `relay-runtime` package: ```javascript - const {Environment, Network} = require('relay-runtime'); // Define a function that fetches the results of an operation (query/mutation/etc) @@ -42,7 +41,6 @@ const environment = new Environment({ ..., // other options network, }); - ``` Note that this is a basic example to help you get started. This example could be extended with additional features such as request/response caching (enabled e.g. when `cacheConfig.force` is false) and uploading form data for mutations (the `uploadables` parameter). diff --git a/website/versioned_docs/version-v1.6.1/Modern-PaginationContainer.md b/website/versioned_docs/version-v1.6.1/Modern-PaginationContainer.md index 8a9ee1c315691..7cd45d706b42d 100644 --- a/website/versioned_docs/version-v1.6.1/Modern-PaginationContainer.md +++ b/website/versioned_docs/version-v1.6.1/Modern-PaginationContainer.md @@ -24,7 +24,6 @@ However, when [specifying connection fragments](#createpaginationcontainer) for The purpose of the `@connection` directive is to allow Relay to uniquely identify different connections under a parent type. The `@connection` directive takes 2 arguments that help identify the connection: ```graphql - @connection(key: String!, filters: [String]) ``` @@ -37,7 +36,6 @@ The purpose of the `@connection` directive is to allow Relay to uniquely identif Specifying just the `key`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and the value of `$orderBy` (given that no `filters` were provided) @@ -53,13 +51,11 @@ fragment Feed_user on User { } } } - ``` Specifying `key` and `filters`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and /only/ the value of `$searchTerm`, i.e. @@ -77,7 +73,6 @@ fragment Feed_user on User { } } } - ``` ## `createPaginationContainer` @@ -85,7 +80,6 @@ fragment Feed_user on User { `createPaginationContainer` has the following signature: ```javascript - createPaginationContainer( component: ReactComponentClass, fragmentSpec: GraphQLTaggedNode | {[string]: GraphQLTaggedNode}, @@ -113,7 +107,6 @@ type ConnectionData = { startCursor: ?string, }, }; - ``` ### Arguments @@ -137,7 +130,6 @@ type ConnectionData = { The Component resulting from `createPaginationContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -148,7 +140,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -163,7 +154,6 @@ type Props = { `hasMore` is a function available on the `relay` [prop](#available-props). This function indicates wether there are more pages to fetch from the server or not. ```javascript - hasMore: () => boolean, ``` @@ -173,7 +163,6 @@ hasMore: () => boolean, `isLoading` is a function available on the `relay` [prop](#available-props). This function indicates if a previous call to [`loadMore()`](#loadmore) is still pending. This is convenient for avoiding duplicate load calls. ```javascript - isLoading: () => boolean, ``` @@ -183,7 +172,6 @@ isLoading: () => boolean, `loadMore` is a function available on the `relay` [prop](#available-props). You can call `loadMore()` to fetch more items from the server based on the `connectionConfig` provided to the container. This will return null if there are no more items to fetch, otherwise it will fetch more items and return a Disposable that can be used to cancel the fetch. ```javascript - loadMore(pageSize: number, callback: ?(error: ?Error) => void): ?Disposable ``` @@ -198,7 +186,6 @@ loadMore(pageSize: number, callback: ?(error: ?Error) => void): ?Disposable `refetchConnection` is a function available on the `relay` [prop](#available-props). You can call `refetchConnection` to restart pagination on a connection from scratch, with optionally a completely new set of variables to pass to the pagination `query`. This is useful for example if you are paginating over a collection based on a userID and the userID changes, you'd want to start paginating over the new collection for the new user. ```javascript - refetchConnection:( count: number, callback: (error: ?Error) => void, @@ -216,7 +203,6 @@ refetchConnection:( ## Pagination Example ```javascript - // Feed.js import {createPaginationContainer, graphql} from 'react-relay'; @@ -311,5 +297,4 @@ module.exports = createPaginationContainer( ` } ); - ``` diff --git a/website/versioned_docs/version-v1.6.1/Modern-PersistedQueries.md b/website/versioned_docs/version-v1.6.1/Modern-PersistedQueries.md index 74b5c3c5d13c6..aadc6710f63bb 100644 --- a/website/versioned_docs/version-v1.6.1/Modern-PersistedQueries.md +++ b/website/versioned_docs/version-v1.6.1/Modern-PersistedQueries.md @@ -16,12 +16,10 @@ The relay compiler supports persisted queries which is useful because: In your `npm` script in `package.json`, run the relay compiler using the `--persist-output` flag: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` The `--persist-ouput` flag does 2 things: @@ -30,8 +28,7 @@ The `--persist-ouput` flag does 2 things: For example without `--persist-output`, a generated `ConcreteRequest` might look like below: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -48,8 +45,7 @@ The `--persist-ouput` flag does 2 things: With `--persist-output ` this becomes: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -67,12 +63,10 @@ The `--persist-ouput` flag does 2 things: 2. It generates a JSON file at the `` you specify containing a mapping from query ids to the corresponding operation texts. -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./src/queryMaps/queryMap.json" } - ``` The example above writes the complete query map file to `./src/queryMaps/queryMap.json`. You need to ensure all the directories @@ -82,8 +76,7 @@ leading to the `queryMap.json` file exist. You'll need to modify your network layer fetch implementation to pass a documentId parameter in the POST body instead of a query parameter: -```js - +```javascript function fetchQuery(operation, variables,) { return fetch('/graphql', { method: 'POST', @@ -99,7 +92,6 @@ function fetchQuery(operation, variables,) { return response.json(); }); } - ``` ## Executing Persisted Queries on the Server @@ -115,13 +107,11 @@ the query map file in a common location accessible to both the client and the se For applications where the client and server projects are separate, one option is to have an additional npm run script to push the query map at compile time to a location accessible by your server: -```js - +```javascript "scripts": { "push-queries": "node ./pushQueries.js", "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-ouput && npm run push-queries" } - ``` Some possibilities of what you can do in `./pushQueries.js`: @@ -145,8 +135,7 @@ database technologies you use, so we'll just cover the most common and basic exa If you use `express-graphql` and have access to the query map file, you can import the `--persist-output` JSON file directly and perform the matching using the `matchQueryMiddleware` from [relay-compiler-plus](https://github.com/yusinto/relay-compiler-plus). -```js - +```javascript import Express from 'express'; import expressGraphql from 'express-graphql'; import {matchQueryMiddleware} from 'relay-compiler-plus'; @@ -157,7 +146,6 @@ const app = Express(); app.use('/graphql', matchQueryMiddleware(queryMapJson), expressGraphql({schema})); - ``` ## Using `--persist-output` and `--watch` diff --git a/website/versioned_docs/version-v1.6.1/Modern-QueryRenderer.md b/website/versioned_docs/version-v1.6.1/Modern-QueryRenderer.md index 5b5fc9c90a237..6914b030ccd25 100644 --- a/website/versioned_docs/version-v1.6.1/Modern-QueryRenderer.md +++ b/website/versioned_docs/version-v1.6.1/Modern-QueryRenderer.md @@ -21,7 +21,6 @@ However, a `QueryRenderer` will not start loading its data until it is mounted, ## Example ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -53,5 +52,4 @@ class Example extends React.Component { ); } } - ``` diff --git a/website/versioned_docs/version-v1.6.1/Modern-RefetchContainer.md b/website/versioned_docs/version-v1.6.1/Modern-RefetchContainer.md index 25839f6aed901..416e049a71403 100644 --- a/website/versioned_docs/version-v1.6.1/Modern-RefetchContainer.md +++ b/website/versioned_docs/version-v1.6.1/Modern-RefetchContainer.md @@ -16,13 +16,11 @@ Table of Contents: `createRefetchContainer` has the following signature: ```javascript - createRefetchContainer( component: ReactComponentClass, fragmentSpec: GraphQLTaggedNode | {[string]: GraphQLTaggedNode}, refetchQuery: GraphQLTaggedNode, ): ReactComponentClass; - ``` ### Arguments @@ -40,7 +38,6 @@ createRefetchContainer( The Component resulting from `createRefetchContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -48,7 +45,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -64,7 +60,6 @@ type Props = { `refetch` has the following signature: ```javascript - type RefetchOptions = { force?: boolean, }; @@ -104,7 +99,6 @@ Returns a `Disposable` on which you could call `dispose()` to cancel the refetch In this simple example, let's assume we want to fetch the latest data for a `TodoItem` from the server: ```javascript - // TodoItem.js import {createRefetchContainer, graphql} from 'react-relay'; @@ -148,7 +142,6 @@ export default createRefetchContainer( } ` ); - ``` ### Loading more data @@ -156,7 +149,6 @@ export default createRefetchContainer( In this example we are using a Refetch Container to fetch more stories in a story feed component. ```javascript - import {createRefetchContainer, graphql} from 'react-relay'; class FeedStories extends React.Component { @@ -212,5 +204,4 @@ export default createRefetchContainer( } `, ); - ``` diff --git a/website/versioned_docs/version-v1.6.1/Modern-RelayCompat.md b/website/versioned_docs/version-v1.6.1/Modern-RelayCompat.md index 36632d3a8f1a1..f47dbd845ba3e 100644 --- a/website/versioned_docs/version-v1.6.1/Modern-RelayCompat.md +++ b/website/versioned_docs/version-v1.6.1/Modern-RelayCompat.md @@ -31,7 +31,6 @@ Relay Modern. The components using Relay Compat can be referred to by both other Relay Modern and Relay Classic components. ```javascript - const {createFragmentContainer, graphql} = require('react-relay/compat'); class TodoItem extends React.Component { @@ -47,5 +46,4 @@ module.exports = createFragmentContainer(TodoItem, graphql` isComplete } `); - ``` diff --git a/website/versioned_docs/version-v1.6.1/Modern-RelayEnvironment.md b/website/versioned_docs/version-v1.6.1/Modern-RelayEnvironment.md index b356b5deecdc5..ed75bc69d1f86 100644 --- a/website/versioned_docs/version-v1.6.1/Modern-RelayEnvironment.md +++ b/website/versioned_docs/version-v1.6.1/Modern-RelayEnvironment.md @@ -12,7 +12,6 @@ Most applications will create a single Environment instance and use it throughou To create an environment instance in Relay Modern, use the `RelayModernEnvironment` class: ```javascript - const { Environment, Network, @@ -30,7 +29,6 @@ const environment = new Environment({ network, store, }); - ``` For more details on creating a Network, see the [NetworkLayer guide](./network-layer). @@ -44,7 +42,6 @@ The example above did not configure a `handlerProvider`, which means that a defa If you wish to provide your own `handlerProvider`, you can do so: ```javascript - const { ConnectionHandler, ViewerHandler, @@ -60,5 +57,4 @@ function handlerProvider(handle) { `handlerProvider: No handler provided for ${handle}` ); } - ``` diff --git a/website/versioned_docs/version-v1.6.1/Modern-RelayStore.md b/website/versioned_docs/version-v1.6.1/Modern-RelayStore.md index 91845846694f4..e8e2df3d9efcf 100644 --- a/website/versioned_docs/version-v1.6.1/Modern-RelayStore.md +++ b/website/versioned_docs/version-v1.6.1/Modern-RelayStore.md @@ -16,7 +16,6 @@ Table of Contents: The `RecordSourceSelectorProxy` is the type of the `store` that [`updater` functions](./mutations#using-updater-and-optimisticupdater) receive as an argument. The following is the `RecordSourceSelectorProxy` interface: ```javascript - interface RecordSourceSelectorProxy { create(dataID: string, typeName: string): RecordProxy; delete(dataID: string): void; @@ -25,7 +24,6 @@ interface RecordSourceSelectorProxy { getRootField(fieldName: string): ?RecordProxy; getPluralRootField(fieldName: string): ?Array; } - ``` ### `create(dataID: string, typeName: string): RecordProxy` @@ -35,9 +33,7 @@ Creates a new record in the store given a `dataID` and the `typeName` as defined #### Example ```javascript - const record = store.create(dataID, 'Todo'); - ``` ### `delete(dataID: string): void` @@ -47,9 +43,7 @@ Deletes a record from the store given its `dataID`. #### Example ```javascript - store.delete(dataID); - ``` ### `get(dataID: string): ?RecordProxy` @@ -59,9 +53,7 @@ Retrieves a record from the store given its `dataID`. Returns a [`RecordProxy`]( #### Example ```javascript - const record = store.get(dataID); - ``` ### `getRoot(): RecordProxy` @@ -73,20 +65,16 @@ Returns the [`RecordProxy`](#recordproxy) representing the root of the GraphQL d Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - // Represents root query const root = store.getRoot(); - ``` ### `getRootField(fieldName: string): ?RecordProxy` @@ -98,19 +86,15 @@ Retrieves a root field from the store given the `fieldName`, as defined by the G Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - const viewer = store.getRootField('viewer'); - ``` ### `getPluralRootField(fieldName: string): ?Array` @@ -122,19 +106,15 @@ Retrieves a root field that represents a collection from the store given the `fi Given the GraphQL document: ```graphql - nodes(first: 10) { # ... } - ``` Usage: ```javascript - const nodes = store.getPluralRootField('nodes'); - ``` ## RecordProxy @@ -142,7 +122,6 @@ const nodes = store.getPluralRootField('nodes'); The `RecordProxy` serves as an interface to mutate records: ```javascript - interface RecordProxy { copyFieldsFrom(sourceRecord: RecordProxy): void; getDataID(): string; @@ -167,7 +146,6 @@ interface RecordProxy { ): RecordProxy; setValue(value: mixed, name: string, arguments?: ?Object): RecordProxy; } - ``` ### `getDataID(): string` @@ -177,9 +155,7 @@ Returns the dataID of the current record. #### Example ```javascript - const id = record.getDataID(); - ``` ### `getType(): string` @@ -189,7 +165,6 @@ Gets the type of the current record, as defined by the GraphQL schema. #### Example ```javascript - const type = user.getType(); // User ``` @@ -203,20 +178,16 @@ Gets the value of a field in the current record given the field name. Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - const name = viewer.getValue('name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. @@ -226,20 +197,16 @@ Optionally, if the field takes arguments, you can pass a bag of `variables`. Given the GraphQL document: ```graphql - viewer { id name(arg: $arg) } - ``` Usage: ```javascript - const name = viewer.getValue('name', {arg: 'value'}); - ``` ### `getLinkedRecord(name: string, arguments?: ?Object): ?RecordProxy` @@ -251,23 +218,19 @@ Retrieves the a record associated with the current record given the field name, Given the GraphQL document: ```graphql - rootField { viewer { id name } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -277,22 +240,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { viewer(arg: $arg) { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {arg: 'value'}); - ``` ### `getLinkedRecords(name: string, arguments?: ?Object): ?Array` @@ -304,22 +263,18 @@ Retrieves the set of records associated with the current record given the field Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const nodes = rootField.getLinkedRecord('nodes'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -329,22 +284,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { nodes(first: $count) { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {count: 10}); - ``` ### `getOrCreateLinkedRecord(name: string, typeName: string, arguments?: ?Object)` @@ -356,19 +307,16 @@ Retrieves the a record associated with the current record given the field name, Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = rootField.getOrCreateLinkedRecord('viewer', 'User'); // Will create if it doesn't exist @@ -383,28 +331,22 @@ Mutates the current record by setting a new value on the specified field. Return Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - viewer.setValue('New Name', 'name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. ```javascript - viewer.setValue('New Name', 'name', {arg: 'value'}); - ``` ### `copyFieldsFrom(sourceRecord: RecordProxy): void` @@ -414,7 +356,6 @@ Mutates the current record by copying the fields over from the passed in record #### Example ```javascript - const record = store.get(id1); const otherRecord = store.get(id2); record.copyFieldsFrom(otherRecord); // Mutates `record` @@ -430,19 +371,16 @@ Mutates the current record by setting a new linked record on the given the field Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = store.create(/* ... */)'' rootField.setLinkedRecord(newViewer, 'viewer'); // @@ -460,19 +398,16 @@ Mutates the current record by setting a new set of linked records on the given t Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newNode = store.create(/* ... */); const newNodes = [...rootField.getLinkedRecords('nodes'), newNode]; @@ -487,7 +422,6 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl `ConnectionHandler` is a utility module exposed by `relay-runtime` that aids in the manipulation of connections. `ConnectionHandler` exposes the following interface: ```javascript - interface ConnectionHandler { getConnection( record: RecordProxy, @@ -512,7 +446,6 @@ interface ConnectionHandler { ): void, deleteNode(connection: RecordProxy, nodeID: string): void } - ``` ### `getConnection(record: RecordProxy, key: string, filters?: ?Object)` @@ -522,7 +455,6 @@ Given a record and a connection key, and optionally a set of filters, `getConnec First, let's take a look at a plain connection: ```graphql - fragment FriendsFragment on User { friends(first: 10) { edges { @@ -532,26 +464,22 @@ fragment FriendsFragment on User { } } } - ``` Accessing a plain connection field like this is the same as other regular field: ```javascript - // The `friends` connection record can be accessed with: const user = store.get(userID); const friends = user && user.getLinkedRecord(user, 'friends'); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` In a [pagination container](./pagination-container), we usually annotate the actual connection field with `@connection` to tell Relay which part needs to be paginated: ```graphql - fragment FriendsFragment on User { friends(first: 10, orderby: "firstname") @connection( key: "FriendsFragment_friends", @@ -563,7 +491,6 @@ fragment FriendsFragment on User { } } } - ``` For connections like the above, `ConnectionHandler` helps us find the record: @@ -581,7 +508,6 @@ const friends = ConnectionHandler.getConnection( ); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` ### Edge creation and insertion @@ -611,7 +537,6 @@ ConnectionHandler.insertEdgeAfter(friends, edge); // No cursor provided, Insert the edge at the front: ConnectionHandler.insertEdgeBefore(friends, edge); - ``` ### `deleteNode(connection: RecordProxy, nodeID: string): void` @@ -625,5 +550,4 @@ Given a connection, deletes any edges whose id matches the given id. const user = store.get(userID); const friends = ConnectionHandler.getConnection(user, 'friends'); ConnectionHandler.deleteNode(friends, idToDelete); - ``` diff --git a/website/versioned_docs/version-v1.6.1/Modern-Subscriptions.md b/website/versioned_docs/version-v1.6.1/Modern-Subscriptions.md index a02a27933c40a..c4e9b324730f0 100644 --- a/website/versioned_docs/version-v1.6.1/Modern-Subscriptions.md +++ b/website/versioned_docs/version-v1.6.1/Modern-Subscriptions.md @@ -6,7 +6,6 @@ original_id: subscriptions Relay exposes the following APIs to create subscriptions. ```javascript - const {requestSubscription} = require('react-relay'); type Variables = {[name: string]: any}; @@ -23,7 +22,6 @@ requestSubscription( configs?: Array, }, ); - ``` Now let's take a closer look at the `config`: @@ -47,7 +45,6 @@ appropriate when you are only changing the properties of existing records that can be identified by their `id`: ```javascript - const { requestSubscription, graphql, @@ -81,7 +78,6 @@ requestSubscription( onError: error => console.error(error), } ); - ``` # Updating the client on each response @@ -91,7 +87,6 @@ Relay's in-memory cache when each subscription response is received. To do so, pass an `updater` function: ```javascript - const {ConnectionHandler} = require('relay-runtime'); requestSubscription( @@ -117,5 +112,4 @@ requestSubscription( }, }, ); - ``` diff --git a/website/versioned_docs/version-v1.6.1/Modern-TestingRelayComponents.md b/website/versioned_docs/version-v1.6.1/Modern-TestingRelayComponents.md index f30317b146e96..eaa443bd20147 100644 --- a/website/versioned_docs/version-v1.6.1/Modern-TestingRelayComponents.md +++ b/website/versioned_docs/version-v1.6.1/Modern-TestingRelayComponents.md @@ -64,7 +64,6 @@ With the `MockPayloadGenerator` and `@relay_test_operation`, we want to get rid Example of a simple Mock Resolver: ```javascript - { ID() { // Return mock value for a scalar filed with type ID @@ -75,13 +74,11 @@ Example of a simple Mock Resolver: return "Lorem Ipsum" } } - ``` It is possible to define more resolvers for Object types: ```javascript - { // This will be the default values for User object in the query response User() { @@ -94,7 +91,6 @@ It is possible to define more resolvers for Object types: }; }, } - ``` ### Mock Resolver Context @@ -102,7 +98,6 @@ It is possible to define more resolvers for Object types: The first argument of the MockResolver is the object that contains Mock Resolver Context. It is possible to return dynamic values from mock resolvers based on the context - for instance, name or alias of the field, a path in the selection, arguments, or parent type. ```javascript - { String(context) { if (context.name === 'zip') { @@ -116,7 +111,6 @@ The first argument of the MockResolver is the object that contains Mock Resolver } } } - ``` ### ID Generation @@ -124,14 +118,12 @@ The first argument of the MockResolver is the object that contains Mock Resolver The second argument of the Mock Resolver its a function that will generate a sequence of integers, useful to generate unique IDs in the tests: ```javascript - { // will generate strings "my-id-1", "my-id-2", etc. ID(_, generateId) { return `my-id-${generateId()}`; }, } - ``` ### `@relay_test_operation` @@ -141,7 +133,6 @@ Most of GraphQL type information for a specific field in the selection is not av Operations with the `@relay_test_operation` directive will have additional metadata that will contain GraphQL type info for fields in the operation's selection. And it will improve the quality of the generated data. You also will be able to define Mock resolvers for Scalar (not only ID and String) and Abstract types: ```javascript - { Float() { return 123.456; @@ -159,7 +150,6 @@ Operations with the `@relay_test_operation` directive will have additional metad }; } } - ``` ## Examples @@ -169,7 +159,6 @@ Operations with the `@relay_test_operation` directive will have additional metad Using `createMockEnvironment` and `MockPayloadGenerator` allows writing concise tests for components that are using Relay Containers and Renderers. Both those modules can be imported from `relay-test-utils`. ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { @@ -222,7 +211,6 @@ test('Error State', () => { renderer.root.find(item => (item.props.testID = 'errorMessage')), ).toBeDefined(); }); - ``` ### Fragment Container Tests @@ -230,7 +218,6 @@ test('Error State', () => { Essentially, in the example above, `resolveMostRecentOperation` will generate data for all child fragment containers (pagination, refetch). Usually, the Root Components container may have many child fragment components and you may want to exercise a specific Fragment Container. The solution for that would be to wrap your fragment container with the QueryRenderer that renders a Query that's spreads fragments from your fragment container. ```javascript - test('Fragment Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -261,7 +248,6 @@ test('Fragment Container', () => { expect(renderer).toMatchSnapshot(); }); - ``` ### Pagination Container Test @@ -269,7 +255,6 @@ test('Fragment Container', () => { Essentially, tests for Pagination container are not different from Fragment Container tests. We can also do more here. We can actually see how the pagination works by asserting the behavior of our components when performing pagination (load more, refetch). ```javascript - // Pagination Example test('Pagination Container', () => { const environment = createMockEnvironment(); @@ -343,7 +328,6 @@ test('Pagination Container', () => { We can use similar approach here with wrapping container with Query Renderer. And for the sake of completeness, we will add example here: ```javascript - test('Refetch Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -385,7 +369,6 @@ test('Refetch Container', () => { ); // expect(renderer).toMatchSnapshot(); }); - ``` ### Mutations @@ -393,7 +376,6 @@ test('Refetch Container', () => { Mutations itself are operations so we can test them independently (unit-test) for specific mutation, or in combination with the view from which this mutation is called. ```javascript - // Say, you have a mutation function function sendMutation(environment, onCompleted, onError, variables) commitMutation(environment, { @@ -416,7 +398,6 @@ test('it should send mutation', () => { ); expect(onCompleted).toBeCalled(); }); - ``` ### Subscription @@ -424,7 +405,6 @@ test('it should send mutation', () => { We can test subscription in a similar way we test mutations ```javascript - // Example subscribe function function subscribe(environment, onNext, onError, variables) requestSubscription(environment, { @@ -447,7 +427,6 @@ test('it should subscribe', () => { ); expect(onNext).toBeCalled(); }); - ``` ### Example with `queueOperationResolver` @@ -455,7 +434,6 @@ test('it should subscribe', () => { With `queueOpeararionResolver`, it possible to define responses for operations that will be executed on the environment ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { diff --git a/website/versioned_docs/version-v1.6.1/Modern-TypeEmission.md b/website/versioned_docs/version-v1.6.1/Modern-TypeEmission.md index c25bc737d5684..9f41810a3618b 100644 --- a/website/versioned_docs/version-v1.6.1/Modern-TypeEmission.md +++ b/website/versioned_docs/version-v1.6.1/Modern-TypeEmission.md @@ -15,7 +15,6 @@ In this example the emitted type-information would require the variables object #### Flow ```javascript - /** * export type ExampleQueryVariables = {| * +artistID: string @@ -43,7 +42,6 @@ const variables: ExampleQueryVariables = { #### TypeScript ```javascript - /** * export type ExampleQueryVariables = { * readonly artistID: string @@ -78,7 +76,6 @@ In this example the emitted type-information describes the response data availab #### Flow ```javascript - /** * export type ExampleQueryResponse = {| * +artist: ?{| @@ -109,7 +106,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * export type ExampleQueryResponse = { * readonly artist?: { @@ -145,7 +141,6 @@ Similarly, in this example the emitted type-information describes the prop data #### Flow ```javascript - /** * export type ExampleFragment_artist = {| * +name: string @@ -171,7 +166,6 @@ export const ExampleFragment = createFragmentContainer( #### TypeScript ```javascript - /** * export type ExampleFragment_artist = { * readonly name: string @@ -205,7 +199,6 @@ Consider a component that composes the above fragment container example. In this #### Flow ```javascript - /** * import type { FragmentReference } from "relay-runtime"; * declare export opaque type ExampleFragment_artist$ref: FragmentReference; @@ -249,7 +242,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * declare const _ExampleFragment_artist$ref: unique symbol; * export type ExampleFragment_artist$ref = typeof _ExampleFragment_artist$ref; @@ -314,7 +306,6 @@ $ relay-compiler --artifactDirectory ./src/__generated__ […] ["relay", { "artifactDirectory": "./src/__generated__" }] ] } - ``` It is recommended to alias this directory in your module resolution configuration such that you don’t need to specify relative paths in your source files. This is what is also done in the above examples, where artifacts are imported from a `__generated__` alias, rather than relative paths like `../../../../__generated__`. diff --git a/website/versioned_docs/version-v1.6.1/Modern-UpgradingSetVariables.md b/website/versioned_docs/version-v1.6.1/Modern-UpgradingSetVariables.md index d5b086fafce20..ff73feec04f8b 100644 --- a/website/versioned_docs/version-v1.6.1/Modern-UpgradingSetVariables.md +++ b/website/versioned_docs/version-v1.6.1/Modern-UpgradingSetVariables.md @@ -36,7 +36,6 @@ fragment on User { # ... } } - ``` This should be upgraded to use a [`PaginationContainer`](./pagination-container). @@ -61,7 +60,6 @@ fragment on User { # ... } } - ``` This can be upgraded by using a [`RefetchContainer`](./refetch-container) which allows you to specify the exact query to use to fetch the new data. @@ -86,7 +84,6 @@ fragment on FeedbackTarget { # ... } } - ``` This can be upgraded by conditionally rendering a [`QueryRenderer`](./query-renderer) which will load the data once it is rendered. The code overhead of doing this is dramatically reduced with the new API. diff --git a/website/versioned_docs/version-v1.6.1/Modern-fetchQuery.md b/website/versioned_docs/version-v1.6.1/Modern-fetchQuery.md index 19e9b57c4219a..223c01ccc75c2 100644 --- a/website/versioned_docs/version-v1.6.1/Modern-fetchQuery.md +++ b/website/versioned_docs/version-v1.6.1/Modern-fetchQuery.md @@ -5,7 +5,6 @@ title: fetchQuery You can use the `fetchQuery` function to imperatively make GraphQL Requests. This is useful for cases where you want to make requests outside of React but still utilize the Relay store and network layer. ```javascript - import {fetchQuery, graphql} from 'relay-runtime'; const query = graphql` @@ -24,7 +23,6 @@ fetchQuery(environment, query, variables) .then(data => { // access the graphql response }); - ``` ## Arguments diff --git a/website/versioned_docs/version-v1.6.1/PrinciplesAndArchitecture-Compiler.md b/website/versioned_docs/version-v1.6.1/PrinciplesAndArchitecture-Compiler.md index c195491682b1f..fcd0490cb724f 100644 --- a/website/versioned_docs/version-v1.6.1/PrinciplesAndArchitecture-Compiler.md +++ b/website/versioned_docs/version-v1.6.1/PrinciplesAndArchitecture-Compiler.md @@ -74,7 +74,6 @@ foo { # type FooType foo { id } - ``` - `SkipRedundantNodeTransform`: A more advanced version of flattening, this eliminates more complex cases of field duplication such as when a field is fetched both unconditionally and conditionally, or is fetched by two different sub-fragments. For example: @@ -97,7 +96,6 @@ foo { id } } - ``` - `GenerateRequisiteFieldTransform`: This optional, Relay-specific transform inserts `id` fields for globally identifiable objects and `__typename` fields wherever the type cannot be statically determined (e.g. for unions). diff --git a/website/versioned_docs/version-v1.6.1/PrinciplesAndArchitecture-Runtime.md b/website/versioned_docs/version-v1.6.1/PrinciplesAndArchitecture-Runtime.md index f012908d090c5..e9c88a4b2ae0c 100644 --- a/website/versioned_docs/version-v1.6.1/PrinciplesAndArchitecture-Runtime.md +++ b/website/versioned_docs/version-v1.6.1/PrinciplesAndArchitecture-Runtime.md @@ -77,7 +77,6 @@ RecordSource { city: 'Seattle', } } - ``` [1] Note that GraphQL itself does not impose this constraint, and Relay Runtime may also be used for schemas that do not conform to it. For example, both systems can be used to query a single denormalized table. However, many of the features that Relay Runtime provides, such as caching and normalization, work best when the data is represented as a normalized graph with stable identities for discrete pieces of information. diff --git a/website/versioned_docs/version-v1.6.1/PrinciplesAndArchitecture-ThinkingInGraphQL.md b/website/versioned_docs/version-v1.6.1/PrinciplesAndArchitecture-ThinkingInGraphQL.md index 14b1119288f23..9527e65e8950e 100644 --- a/website/versioned_docs/version-v1.6.1/PrinciplesAndArchitecture-ThinkingInGraphQL.md +++ b/website/versioned_docs/version-v1.6.1/PrinciplesAndArchitecture-ThinkingInGraphQL.md @@ -12,7 +12,6 @@ In this article we'll explore what it means to build a GraphQL client framework Imagine we have a simple application that fetches a list of stories, and some details about each one. Here's how that might look in resource-oriented REST: ```javascript - // Fetch the list of story IDs but not their details: rest.get('/stories').then(stories => // This resolves to a list of items with linked resources: @@ -25,13 +24,11 @@ rest.get('/stories').then(stories => // `[ { id: "...", text: "..." } ]` console.log(stories); }); - ``` Note that this approach requires _n+1_ requests to the server: 1 to fetch the list, and _n_ to fetch each item. With GraphQL we can fetch the same data in a single network request to the server (without creating a custom endpoint that we'd then have to maintain): ```javascript - graphql.get(`query { stories { id, text } }`).then( stories => { // A list of story items: @@ -39,7 +36,6 @@ graphql.get(`query { stories { id, text } }`).then( console.log(stories); } ); - ``` So far we're just using GraphQL as a more efficient version of typical REST approaches. Note two important benefits in the GraphQL version: @@ -56,7 +52,6 @@ Repeatedly refetching information from the server can get quite slow. For exampl In a resource-oriented REST system, we can maintain a **response cache** based on URIs: ```javascript - var _cache = new Map(); rest.get = uri => { if (!_cache.has(uri)) { @@ -64,13 +59,11 @@ rest.get = uri => { } return _cache.get(uri); }; - ``` Response-caching can also be applied to GraphQL. A basic approach would work similarly to the REST version. The text of the query itself can be used as a cache key: ```javascript - var _cache = new Map(); graphql.get = queryText => { if (!_cache.has(queryText)) { @@ -78,7 +71,6 @@ graphql.get = queryText => { } return _cache.get(queryText); }; - ``` Now, requests for previously cached data can be answered immediately without making a network request. This is a practical approach to improving the perceived performance of an application. However, this method of caching can cause problems with data consistency. @@ -90,7 +82,6 @@ With GraphQL it is very common for the results of multiple queries to overlap. H ``` query { stories { id, text, likeCount } } - ``` and then later refetch one of the stories whose `likeCount` has since been incremented: @@ -98,7 +89,6 @@ and then later refetch one of the stories whose `likeCount` has since been incre ``` query { story(id: "123") { id, text, likeCount } } - ``` We'll now see different `likeCount`s depending on how the story is accessed. A view that uses the first query will see an outdated count, while a view using the second query will see the updated count. @@ -119,7 +109,6 @@ query { } } } - ``` And here's a possible response: @@ -134,13 +123,11 @@ query: { } } } - ``` Although the response is hierarchical, we'll cache it by flattening all the records. Here is an example of how Relay would cache this query response: ```javascript - Map { // `story(id: "1")` 1: Map { @@ -152,7 +139,6 @@ Map { name: 'Jan', }, }; - ``` This is only a simple example: in reality the cache must handle one-to-many associations and pagination (among other things). @@ -182,7 +168,6 @@ The first query was for a list of stories: ``` query { stories { id, text, likeCount } } - ``` With a normalized response cache, a record would be created for each story in the list. The `stories` field would store links to each of these records. @@ -192,7 +177,6 @@ The second query refetched the information for one of those stories: ``` query { story(id: "123") { id, text, likeCount } } - ``` When this response is normalized, Relay can detect that this result overlaps with existing data based on its `id`. Rather than create a new record, Relay will update the existing `123` record. The new `likeCount` is therefore available to _both_ queries, as well as any other query that might reference this story. @@ -215,7 +199,6 @@ query { } } } - ``` After initially fetching this story our cache might be as follows. Note that the story and comment both link to the same record as `author`: @@ -242,7 +225,6 @@ Map { author: Link(2), }, } - ``` The author of this story also commented on it — quite common. Now imagine that some other view fetches new information about the author, and her profile photo has changed to a new URI. Here's the _only_ part of our cached data that changes: @@ -256,7 +238,6 @@ Map { photo: 'http://.../photo2.jpg', }, } - ``` The value of the `photo` field has changed; and therefore the record `2` has also changed. And that's it. Nothing else in the _cache_ is affected. But clearly our _view_ needs to reflect the update: both instances of the author in the UI (as story author and comment author) need to show the new photo. @@ -273,7 +254,6 @@ ImmutableMap { }, 3: ImmutableMap // same as before } - ``` If we replace `2` with a new immutable record, we'll also get a new immutable instance of the cache object. However, records `1` and `3` are untouched. Because the data is normalized, we can't tell that `story`'s contents have changed just by looking at the `story` record alone. @@ -299,7 +279,6 @@ mutation StoryLike($storyID: String) { likeCount } } - ``` Notice that we're querying for data that _may_ have changed as a result of the mutation. An obvious question is: why can't the server just tell us what changed? The answer is: it's complicated. GraphQL abstracts over _any_ data storage layer (or an aggregation of multiple sources), and works with any programming language. Furthermore, the goal of GraphQL is to provide data in a form that is useful to product developers building a view. diff --git a/website/versioned_docs/version-v1.6.1/PrinciplesAndArchitecture-ThinkingInRelay.md b/website/versioned_docs/version-v1.6.1/PrinciplesAndArchitecture-ThinkingInRelay.md index 47c27f92ab909..1ffea144589ad 100644 --- a/website/versioned_docs/version-v1.6.1/PrinciplesAndArchitecture-ThinkingInRelay.md +++ b/website/versioned_docs/version-v1.6.1/PrinciplesAndArchitecture-ThinkingInRelay.md @@ -30,13 +30,11 @@ fragment Story_story on Story { photo } } - ``` And this fragment can then be used to define the Story container: ```javascript - const {createFragmentContainer, graphql} = require('react-relay'); // Plain React component. @@ -64,7 +62,6 @@ const StoryContainer = createFragmentContainer(Story, { In React, rendering a view requires two inputs: the _component_ to render, and a _root_ DOM (UI) node to render into. Rendering Relay containers is similar: we need a _container_ to render, and a _root_ in the graph from which to start our query. We also must ensure that the queries for the container are executed and may want to show a loading indicator while data is being fetched. Similar to `ReactDOM.render(component, domNode)`, Relay provides `` for this purpose. The `query` and `variables` define what data to fetch and `render` defines what to render. Here's how we might render ``: ```javascript - ReactDOM.render( { ); } } - ``` The above code is doing something very similar to our [previous example](#rendering-graphql-queries), however, we are now passing a `$userID` variable to the GraphQL query, via the `variables` prop. This has a couple of important implications: @@ -229,7 +217,6 @@ Now that we know how to define and fetch queries, let's actually start building First, let's start at the bottom; let's say that we want to render a component that given a todo item, simply displays the item's text and completed state: ```javascript - // Todo.js import React from 'react'; @@ -259,7 +246,6 @@ export default class Todo extends React.Component { ); } } - ``` From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L107), we know that we can query this data on the `Todo` type. However, we don't want to have to send a separate query for each todo item; that would defeat the purpose of using GraphQL over a traditional REST API. We could manually query for these fields directly in our `QueryRenderer` query, but that would hurt re-usability: what if we want to query the same set of fields as part of a different query? Additionally, we wouldn't know which component needs the data we're querying, a problem Relay directly tries to address. @@ -267,18 +253,15 @@ From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/dat Instead, we can define a reusable [Fragment](http://graphql.org/learn/queries/#fragments), which allows us to define a set of fields on a type and reuse them within our queries wherever we need to: ```graphql - fragment TodoItemFragment on Todo { complete text } - ``` Our component can then use this fragment to declare its data dependency on the `Todo` GraphQL type: ```javascript - // Todo.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -338,7 +321,6 @@ Before proceeding, don't forget to run the Relay Compiler with `yarn relay`. Given that [Fragment Containers](./fragment-container) are just React components, we can compose them as such, and even re-use fragment containers within other fragment containers. As an example, let's see how we would define a `TodoList` component that just renders a list of todo items, and whether all have been completed or not: ```javascript - // TodoList.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -397,7 +379,6 @@ export default createFragmentContainer( } `, ); - ``` As with the first fragment container we defined, `TodoList` declares it's data dependencies via a fragment. However, this component additionally re-uses the fragment previously defined by the `Todo` component, and passes the appropriate data to when rendering the child `Todo` components (a.k.a. fragment containers). @@ -412,7 +393,6 @@ fragment containers do not directly fetch data. Instead, containers declare a sp A `QueryRenderer` rendering these fragment containers could look like the following: ```javascript - // ViewerTodoList.js import React from 'react'; import PropTypes from 'prop-types'; @@ -454,7 +434,6 @@ export default ViewerTodoList extends React.Component { ); } } - ``` Check out or docs for [Fragment Containers](./fragment-container) for more details, and our guides on [Refetch](./refetch-container) and [Pagination](./pagination-container) for more advanced usage of containers. @@ -466,7 +445,6 @@ Now that we know how to query for and render data, let's move on to changing our From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L35), we know that we have some mutations available to us, so let's start by writing a mutation to change the `complete` status of a given todo item (i.e. mark or unmark it as done): ```graphql - mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { changeTodoStatus(input: $input) { todo { @@ -475,7 +453,6 @@ mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { } } } - ``` This mutation allows us to query back some data as a [result of the mutation](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L18), so we're going to query for the updated `complete` status on the todo item. @@ -483,7 +460,6 @@ This mutation allows us to query back some data as a [result of the mutation](ht In order to execute this mutation in Relay, we're going to write a new mutation using Relay's `commitMutation` api: ```javascript - // ChangeTodoStatusMutation.js import {graphql, commitMutation} from 'react-relay'; @@ -517,7 +493,6 @@ function commit( } export default {commit}; - ``` Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mutation to the server, and in our case, upon receiving a response it will automatically update the local data store with the latest data from the server. This also means that upon receiving the response, Relay will ensure that any components (i.e. containers) that depend on the updated data are re-rendered. @@ -525,7 +500,6 @@ Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mut In order to actually use this mutation in our component, we could update our `Todo` component in the following way: ```javascript - // Todo.js // ... @@ -559,7 +533,6 @@ In order to make the experience better, we can configure our mutation to do an o In Relay, there's a couple of options we can pass to `commitMutation` to enable optimistic updates. Let's see what that would look like in our `ChangeTodoStatusMutation`: ```javascript - // ChangeTodoStatusMutation.js // ... @@ -594,7 +567,6 @@ function commit( } export default {commit}; - ``` In the simplest case above, we just need to pass an `optimisticResponse` option, which should refer to an object having the same shape as the mutation response payload. When we pass this option, Relay will know to immediately update our local data with the optimistic response, and then update it with the actual server response, or roll it back if an error occurs. diff --git a/website/versioned_docs/version-v1.6.2/Modern-ConvertingMutations.md b/website/versioned_docs/version-v1.6.2/Modern-ConvertingMutations.md index 288ac18ab0872..96410a4589cef 100644 --- a/website/versioned_docs/version-v1.6.2/Modern-ConvertingMutations.md +++ b/website/versioned_docs/version-v1.6.2/Modern-ConvertingMutations.md @@ -12,19 +12,16 @@ FatQueries in Relay Classic mutations was a concept that was confusing for a num Example of existing fat query: ```javascript - RelayClassic.QL` fragment on MarkReadNotificationResponsePayload @relay(pattern: true) { notification } `; - ``` Example of converted mutation query: ```javascript - graphql` mutation MarkReadNotificationMutation( $input: MarkReadNotificationData! @@ -37,7 +34,6 @@ graphql` } } `; - ``` ## Migrating Configs @@ -63,7 +59,6 @@ This is no longer needed in Compatibility Mode for neither environments. Relay w Take this example of a simple mutation in Relay Classic: ```javascript - class LikeStoryMutation extends RelayClassic.Mutation { getMutation() { return RelayClassic.QL`mutation {likeStory}`; @@ -102,7 +97,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { `, }; } - ``` ### Converting `getMutation()` and `getFatQuery()` @@ -110,7 +104,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { We combine these two into a regular GraphQL mutation, which list out specific fields that needs to be updated. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story(data: $input) { @@ -122,7 +115,6 @@ const mutation = graphql` } } `; - ``` ### Converting `getConfigs()` @@ -134,13 +126,11 @@ As specified above, `FIELDS_CHANGE` configs can be omitted. To convert `getVariables()`, we take the return value from the original function and wrap it in an object that contains a property that matches the variable name for the mutation. In this case, the mutation has a `input` variable that is of type `LikeStoryData`. ```javascript - const variables = { input: { storyID: args.storyID } } - ``` ### Final Result @@ -148,7 +138,6 @@ const variables = { As you can see, our resulting mutation is a lot simpler and more like regular GraphQL than the Relay Classic version we started out with. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story { @@ -174,7 +163,6 @@ function commit(environment: CompatEnvironment, args) { variables, }); } - ``` See [Mutation](./mutations) for additional options on `commitMutation` for more complex mutations. diff --git a/website/versioned_docs/version-v1.6.2/Modern-FragmentContainer.md b/website/versioned_docs/version-v1.6.2/Modern-FragmentContainer.md index e86b79995c1c7..7bbd0a9f22899 100644 --- a/website/versioned_docs/version-v1.6.2/Modern-FragmentContainer.md +++ b/website/versioned_docs/version-v1.6.2/Modern-FragmentContainer.md @@ -17,12 +17,10 @@ Table of Contents: `createFragmentContainer` has the following signature: ```javascript - createFragmentContainer( component: ReactComponentClass, fragmentSpec: GraphQLTaggedNode | {[string]: GraphQLTaggedNode}, ): ReactComponentClass; - ``` ### Arguments @@ -46,7 +44,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -61,7 +58,6 @@ To start, let's build the plain React version of a hypothetical `` c Here's a basic implementation of `` that ignores styling in order to highlight the functionality: ```javascript - // TodoItem.js class TodoItem extends React.Component { render() { @@ -81,7 +77,6 @@ class TodoItem extends React.Component { ); } } - ``` ### Data Dependencies With GraphQL @@ -89,7 +84,6 @@ class TodoItem extends React.Component { In Relay, data dependencies are described using [GraphQL](https://github.com/facebook/graphql). For ``, the dependency can be expressed as follows. Note that this exactly matches the shape that the component expected for the `item` prop. ```javascript - graphql` # This fragment only applies to objects of type 'Todo'. fragment TodoItem_item on Todo { @@ -105,7 +99,6 @@ graphql` Given the plain React component and a GraphQL fragment, we can now define a Fragment Container to specify this component's data requirements. Let's look at the code first and then see what's happening: ```javascript - // TodoItem.js import {createFragmentContainer, graphql} from 'react-relay'; @@ -123,13 +116,11 @@ export default createFragmentContainer(TodoItem, { } `, }); - ``` Relay will infer the prop name from the fragment name according to the fragment naming convention `<...>_`. The example below is equivalent to the one above: ```javascript - export default createFragmentContainer( TodoItem, graphql` @@ -139,13 +130,11 @@ export default createFragmentContainer( } `, ); - ``` If there is no `_` suffix, the `data` prop name will be used: ```javascript - class TodoItem extends React.Component { render() { const item = this.props.data; @@ -162,7 +151,6 @@ export default createFragmentContainer( } `, ); - ``` ## Container Composition @@ -176,7 +164,6 @@ Let's explore how this works via a `` component that composes the `< View composition is _exactly_ what you're used to — Relay containers are just standard React components. Here's the `` component: ```javascript - class TodoList extends React.Component { render() { // Expects a `list` with a string `title`, as well as the information @@ -191,7 +178,6 @@ class TodoList extends React.Component { ); } } - ``` ### Composing Fragments @@ -199,7 +185,6 @@ class TodoList extends React.Component { Fragment composition works similarly — a parent container's fragment composes the fragment for each of its children. In this case, `` needs to fetch information about the `Todo`s that are required by ``. ```javascript - class TodoList extends React.Component // as above export default createFragmentContainer( @@ -217,7 +202,6 @@ export default createFragmentContainer( } `, ); - ``` Note that when composing fragments, the type of the composed fragment must match the field on the parent in which it is embedded. For example, it wouldn't make sense to embed a fragment of type `Story` into a parent's field of type `User`. Relay and GraphQL will provide helpful error messages if you get this wrong (and if they aren't helpful, let us know!). @@ -231,7 +215,6 @@ When defining a fragment, you can use the [`@argumentDefinitions`](./graphql-in- For example, let's redefine our `TodoList_list` fragment to take some arguments using `@argumentDefinitions`: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -241,7 +224,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` Any arguments defined inside `@argumentDefinitions` will be local variables available inside the fragment's scope. However, a fragment can also reference global variables that were defined in the root query. @@ -253,11 +235,9 @@ In order to pass arguments to a fragment that has `@argumentDefinitions`, you ne Following our `TodoList_list` example, we would pass arguments to the fragment like so: ```graphql - query TodoListQuery($count: Int, $userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` ### Calling Component Instance Methods @@ -268,7 +248,6 @@ Since Relay composes these component instances in a container, you need to use t Consider an input with a server-defined placeholder text and an imperative method to focus the input node: ```javascript - export default createFragmentContainer( class TodoInput extends React.Component { focus() { @@ -288,13 +267,11 @@ export default createFragmentContainer( } `, ); - ``` To call this method on the underlying component, first provide a `componentRef` function to the Relay container. This differs from providing a [`ref`](https://facebook.github.io/react/docs/refs-and-the-dom.html) function which would provide a reference to the Relay container itself, not the underlying React Component. ```javascript - export default createFragmentContainer( class TodoListView extends React.Component { render() { @@ -312,7 +289,6 @@ export default createFragmentContainer( } `, ); - ``` ## Rendering Containers diff --git a/website/versioned_docs/version-v1.6.2/Modern-GraphQLInRelay.md b/website/versioned_docs/version-v1.6.2/Modern-GraphQLInRelay.md index 45ed05dc9670e..7cb555b6ce502 100644 --- a/website/versioned_docs/version-v1.6.2/Modern-GraphQLInRelay.md +++ b/website/versioned_docs/version-v1.6.2/Modern-GraphQLInRelay.md @@ -14,7 +14,6 @@ Table of Contents: The `graphql` template tag provided by Relay serves as the mechanism to write queries, fragments, mutations or subscriptions in the [GraphQL](http://graphql.org/learn/) language. For example: ```javascript - import {graphql} from 'react-relay'; graphql` @@ -24,7 +23,6 @@ graphql` } } `; - ``` The result of using the `graphql` template tag are `GraphQLTaggedNode`s, which are used to define [Query Renderers](./query-renderer), [Fragment Containers](./fragment-container), [Refetch Containers](./refetch-container), [Pagination Containers](./pagination-container), etc. @@ -42,11 +40,9 @@ Relay uses directives to add additional information to GraphQL documents, which `@arguments` is a directive used to pass arguments to a fragment that was defined using [`@argumentDefinitions`](#argumentdefinitions). For example: ```graphql - query TodoListQuery($userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` See [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -56,7 +52,6 @@ See [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragme `@argumentDefinitions` is a directive used to specify arguments taken by a fragment. For example: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -66,7 +61,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` See [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -82,13 +76,11 @@ When using the [Pagination Container](./pagination-container), Relay expects con When defining a fragment, you can use the `@relay(plural: true)` directive to indicate that the fragment is backed by a [GraphQL list](http://graphql.org/learn/schema/#lists-and-non-null), meaning that it will inform Relay that this particular field is an array. For example: ```javascript - graphql` fragment TodoItems_items on TodoItem @relay(plural: true) { id text }`; - ``` ### `@relay(mask: Boolean)` @@ -104,7 +96,6 @@ Keep in mind that it is typically considered an **anti-pattern** to create a sin In the example below, the `user` prop will include the data for `id` and `name` fields wherever `...Component_internUser` is included, instead of Relay's normal behavior to mask those fields: ```javascript - graphql` fragment Component_internUser on InternUser { id @@ -132,7 +123,6 @@ export default createFragmentContainer( } `, ); - ``` ## Relay Compiler @@ -142,7 +132,6 @@ Relay uses the Relay Compiler to convert [`graphql`](#graphql) literals into gen A query like the following: ```javascript - graphql` fragment MyComponent on Type { field @@ -166,7 +155,6 @@ See our relay-compiler section in our [Installation and Setup guide](./installat To use the Relay Compiler, you need either a .graphql or .json GraphQL schema file, describing your GraphQL server's API. Typically these files are local representations of a server source of truth and are not edited directly. For example, we might have a `schema.graphql` like: ```graphql - schema { query: Root } @@ -184,7 +172,6 @@ type WordDefinition { text: String image: String } - ``` ### Source files @@ -200,7 +187,6 @@ For example, given the two files: - `src/Components/DictionaryComponent.js` ```javascript - const DictionaryWordFragment = graphql` fragment DictionaryComponent_word on Word { id @@ -222,7 +208,6 @@ For example, given the two files: - `src/Queries/DictionaryQuery.js` ```javascript - const DictionaryQuery = graphql` query DictionaryQuery { dictionary { @@ -246,9 +231,7 @@ Typically you will not need to import your generated definitions. The [Relay Bab However the Relay Compiler also automatically generates [Flow](https://flow.org) types as [type comments](https://flow.org/en/docs/types/comments/). For example, you can import the generated flow types like so: ```javascript - import type {DictionaryComponent_word} from './__generated__/DictionaryComponent_word.graphql'; - ``` ### Advanced usage diff --git a/website/versioned_docs/version-v1.6.2/Modern-LocalStateManagement.md b/website/versioned_docs/version-v1.6.2/Modern-LocalStateManagement.md index f3427f392a611..dc50079ca5fbe 100644 --- a/website/versioned_docs/version-v1.6.2/Modern-LocalStateManagement.md +++ b/website/versioned_docs/version-v1.6.2/Modern-LocalStateManagement.md @@ -23,23 +23,19 @@ It can even be used to extend an existing server schema. For example, we can create a new type called `Note`: ```graphql - type Note { id: ID! title: String body: String } - ``` And then extend the server schema type `User`, with a list of `Note`, called `notes`. ```graphql - extend type User { notes: [Note] } - ``` ## Querying local state @@ -50,7 +46,6 @@ The field can be from the server schema, or it can be schema agnostic, like an i Here, we use a [QueryRenderer](./query-renderer) to get the current `User` via the `viewer` field, along with their id, name and the local list of notes. ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -96,7 +91,6 @@ const Example = (props) => { /> ); } - ``` ## Mutating local state @@ -110,7 +104,6 @@ To build upon the previous example, let's try creating, updating and deleting a ### Create ```javascript - import {commitLocalUpdate} from 'react-relay'; let tempID = 0; @@ -130,7 +123,6 @@ function createUserNote() { user.setLinkedRecords([...userNoteRecords, newNoteRecord], 'notes'); }); } - ``` Note that since this record will be rendered by the `ExampleQuery` in our `QueryRenderer`, the QueryRenderer will automatically retain this data so it isn't garbage collected. @@ -138,7 +130,6 @@ Note that since this record will be rendered by the `ExampleQuery` in our `Query If no component is rendering the local data and you want to manually retain it, you can do so by calling `environment.retain()`: ```javascript - import {createOperationDescriptor, getRequest} from 'relay-runtime'; // Create a query that references that record @@ -165,13 +156,11 @@ const disposable = environment.retain(operation); // Whenever you don't need that data anymore and it's okay for Relay to garbage collect it, // you can dispose of the retain disposable.dispose(); - ``` ### Update ```javascript - import {commitLocalUpdate} from 'react-relay'; function updateUserNote(dataID, body, title) { @@ -182,13 +171,11 @@ function updateUserNote(dataID, body, title) { note.setValue(title, 'title') }); } - ``` ### Delete ```javascript - import {commitLocalUpdate} from 'react-relay'; function deleteUserNote(dataID) { @@ -206,7 +193,6 @@ function deleteUserNote(dataID) { user.setLinkedRecords(newUserNoteRecords, 'notes'); }); } - ``` ## Initial local state @@ -215,7 +201,6 @@ All new client-side schema fields default to `undefined` value. Often however, y You can use an updater function via `commitLocalUpdate` to prime local state. ```javascript - import {commitLocalUpdate} from 'react-relay'; commitLocalUpdate(environment, store => { @@ -224,5 +209,4 @@ commitLocalUpdate(environment, store => { // initialize user notes to an empty array. user.setLinkedRecords([], 'notes'); }); - ``` diff --git a/website/versioned_docs/version-v1.6.2/Modern-MigrationSetup.md b/website/versioned_docs/version-v1.6.2/Modern-MigrationSetup.md index 66f1145357e25..a89c0e178e0e5 100644 --- a/website/versioned_docs/version-v1.6.2/Modern-MigrationSetup.md +++ b/website/versioned_docs/version-v1.6.2/Modern-MigrationSetup.md @@ -13,13 +13,11 @@ With some additional configuration, the `"relay"` babel plugin can also translat Relay Classic `Relay.QL` literals. Most importantly, include a reference to your GraphQL Schema as either a json file or graphql schema file. ```javascript - { "plugins": [ ["relay", {"schema": "path/schema.graphql"}] ] } - ``` ## Set up babel-plugin-relay for "[compatibility mode](./relay-compat)" @@ -29,13 +27,11 @@ literals can be translated to be usable by _both_ runtimes if configured to use compatibility mode: ```javascript - { "plugins": [ ["relay", {"compat": true, "schema": "path/schema.graphql"}] ] } - ``` ## Additional Options @@ -47,7 +43,6 @@ thrown at runtime. When compiling code for production deployment, the plugin can be configured to immediately throw upon encountering a validation problem. The plugin can be further customized for different environments with the following options: ```javascript - { "plugins": [ ["relay", { @@ -56,5 +51,4 @@ When compiling code for production deployment, the plugin can be configured to i }] ] } - ``` diff --git a/website/versioned_docs/version-v1.6.2/Modern-Mutations.md b/website/versioned_docs/version-v1.6.2/Modern-Mutations.md index d879216bdd5e3..ebb1797237203 100644 --- a/website/versioned_docs/version-v1.6.2/Modern-Mutations.md +++ b/website/versioned_docs/version-v1.6.2/Modern-Mutations.md @@ -16,7 +16,6 @@ Table of Contents: Use `commitMutation` to create and execute mutations. `commitMutation` has the following signature: ```javascript - commitMutation( environment: Environment, config: { @@ -30,7 +29,6 @@ commitMutation( configs?: Array, }, ); - ``` ### Arguments @@ -57,7 +55,6 @@ commitMutation( Example of a simple mutation: ```javascript - import {commitMutation, graphql} from 'react-relay'; const mutation = graphql` @@ -92,7 +89,6 @@ function markNotificationAsRead(environment, source, storyID) { }, ); } - ``` ## Optimistic Updates @@ -100,7 +96,6 @@ function markNotificationAsRead(environment, source, storyID) { To improve perceived responsiveness, you may wish to perform an "optimistic update", in which the client immediately updates to reflect the anticipated new value even before the response from the server has come back. The simplest way to do this is by providing an `optimisticResponse` and adding it to the `config` that we pass into `commitMutation`: ```javascript - const mutation = graphql` mutation MarkReadNotificationMutation( $input: MarkReadNotificationData! @@ -129,7 +124,6 @@ commitMutation( variables, }, ); - ``` Another way to enable optimistic updates is via the `optimisticUpdater`, which can be used for more complicated update scenarios. Using `optimisticUpdater` is covered in the section [below](#using-updater-and-optimisticupdater). @@ -149,7 +143,6 @@ Given a deletedIDFieldName, Relay will remove the node(s) from the connection. #### Example ```javascript - const mutation = graphql` mutation DestroyShipMutation($input: DestroyShipData!) { destroyShip(input: $input) { @@ -167,7 +160,6 @@ const configs = [{ type: 'NODE_DELETE', deletedIDFieldName: 'destroyedShipId', }]; - ``` ### RANGE_ADD @@ -187,7 +179,6 @@ Given a parent, information about the connection, and the name of the newly crea #### Example ```javascript - const mutation = graphql` mutation AddShipMutation($input: AddShipData!) { addShip(input: $input) { @@ -210,7 +201,6 @@ const configs = [{ }], edgeName: 'newShipEdge', }]; - ``` ### RANGE_DELETE @@ -232,7 +222,6 @@ from the connection but leave the associated record(s) in the store. #### Example ```javascript - const mutation = graphql` mutation RemoveTagsMutation($input: RemoveTagsData!) { removeTags(input: $input) { @@ -255,7 +244,6 @@ const configs = [{ pathToConnection: ['todo', 'tags'], deletedIDFieldName: removedTagId }]; - ``` ## Using updater and optimisticUpdater @@ -273,7 +261,6 @@ When you provide these functions, this is roughly what happens during the mutati Here are a quick example of adding a todo item to a Todo list using this [example schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L36): ```javascript - // AddTodoMutation.js import {commitMutation, graphql} from 'react-relay'; import {ConnectionHandler} from 'relay-runtime'; @@ -365,7 +352,6 @@ function commit( } ); } - ``` For details on how to interact with the Relay Store, please refer to our Relay Store [docs](./relay-store). diff --git a/website/versioned_docs/version-v1.6.2/Modern-NetworkLayer.md b/website/versioned_docs/version-v1.6.2/Modern-NetworkLayer.md index c5813a18609e8..e0d5a012a0ecf 100644 --- a/website/versioned_docs/version-v1.6.2/Modern-NetworkLayer.md +++ b/website/versioned_docs/version-v1.6.2/Modern-NetworkLayer.md @@ -8,7 +8,6 @@ In order to know how to access your GraphQL server, Relay Modern requires develo Currently the easiest way to create a network layer is via a helper from the `relay-runtime` package: ```javascript - const {Environment, Network} = require('relay-runtime'); // Define a function that fetches the results of an operation (query/mutation/etc) @@ -42,7 +41,6 @@ const environment = new Environment({ ..., // other options network, }); - ``` Note that this is a basic example to help you get started. This example could be extended with additional features such as request/response caching (enabled e.g. when `cacheConfig.force` is false) and uploading form data for mutations (the `uploadables` parameter). diff --git a/website/versioned_docs/version-v1.6.2/Modern-PaginationContainer.md b/website/versioned_docs/version-v1.6.2/Modern-PaginationContainer.md index 8a9ee1c315691..7cd45d706b42d 100644 --- a/website/versioned_docs/version-v1.6.2/Modern-PaginationContainer.md +++ b/website/versioned_docs/version-v1.6.2/Modern-PaginationContainer.md @@ -24,7 +24,6 @@ However, when [specifying connection fragments](#createpaginationcontainer) for The purpose of the `@connection` directive is to allow Relay to uniquely identify different connections under a parent type. The `@connection` directive takes 2 arguments that help identify the connection: ```graphql - @connection(key: String!, filters: [String]) ``` @@ -37,7 +36,6 @@ The purpose of the `@connection` directive is to allow Relay to uniquely identif Specifying just the `key`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and the value of `$orderBy` (given that no `filters` were provided) @@ -53,13 +51,11 @@ fragment Feed_user on User { } } } - ``` Specifying `key` and `filters`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and /only/ the value of `$searchTerm`, i.e. @@ -77,7 +73,6 @@ fragment Feed_user on User { } } } - ``` ## `createPaginationContainer` @@ -85,7 +80,6 @@ fragment Feed_user on User { `createPaginationContainer` has the following signature: ```javascript - createPaginationContainer( component: ReactComponentClass, fragmentSpec: GraphQLTaggedNode | {[string]: GraphQLTaggedNode}, @@ -113,7 +107,6 @@ type ConnectionData = { startCursor: ?string, }, }; - ``` ### Arguments @@ -137,7 +130,6 @@ type ConnectionData = { The Component resulting from `createPaginationContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -148,7 +140,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -163,7 +154,6 @@ type Props = { `hasMore` is a function available on the `relay` [prop](#available-props). This function indicates wether there are more pages to fetch from the server or not. ```javascript - hasMore: () => boolean, ``` @@ -173,7 +163,6 @@ hasMore: () => boolean, `isLoading` is a function available on the `relay` [prop](#available-props). This function indicates if a previous call to [`loadMore()`](#loadmore) is still pending. This is convenient for avoiding duplicate load calls. ```javascript - isLoading: () => boolean, ``` @@ -183,7 +172,6 @@ isLoading: () => boolean, `loadMore` is a function available on the `relay` [prop](#available-props). You can call `loadMore()` to fetch more items from the server based on the `connectionConfig` provided to the container. This will return null if there are no more items to fetch, otherwise it will fetch more items and return a Disposable that can be used to cancel the fetch. ```javascript - loadMore(pageSize: number, callback: ?(error: ?Error) => void): ?Disposable ``` @@ -198,7 +186,6 @@ loadMore(pageSize: number, callback: ?(error: ?Error) => void): ?Disposable `refetchConnection` is a function available on the `relay` [prop](#available-props). You can call `refetchConnection` to restart pagination on a connection from scratch, with optionally a completely new set of variables to pass to the pagination `query`. This is useful for example if you are paginating over a collection based on a userID and the userID changes, you'd want to start paginating over the new collection for the new user. ```javascript - refetchConnection:( count: number, callback: (error: ?Error) => void, @@ -216,7 +203,6 @@ refetchConnection:( ## Pagination Example ```javascript - // Feed.js import {createPaginationContainer, graphql} from 'react-relay'; @@ -311,5 +297,4 @@ module.exports = createPaginationContainer( ` } ); - ``` diff --git a/website/versioned_docs/version-v1.6.2/Modern-PersistedQueries.md b/website/versioned_docs/version-v1.6.2/Modern-PersistedQueries.md index 74b5c3c5d13c6..aadc6710f63bb 100644 --- a/website/versioned_docs/version-v1.6.2/Modern-PersistedQueries.md +++ b/website/versioned_docs/version-v1.6.2/Modern-PersistedQueries.md @@ -16,12 +16,10 @@ The relay compiler supports persisted queries which is useful because: In your `npm` script in `package.json`, run the relay compiler using the `--persist-output` flag: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` The `--persist-ouput` flag does 2 things: @@ -30,8 +28,7 @@ The `--persist-ouput` flag does 2 things: For example without `--persist-output`, a generated `ConcreteRequest` might look like below: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -48,8 +45,7 @@ The `--persist-ouput` flag does 2 things: With `--persist-output ` this becomes: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -67,12 +63,10 @@ The `--persist-ouput` flag does 2 things: 2. It generates a JSON file at the `` you specify containing a mapping from query ids to the corresponding operation texts. -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./src/queryMaps/queryMap.json" } - ``` The example above writes the complete query map file to `./src/queryMaps/queryMap.json`. You need to ensure all the directories @@ -82,8 +76,7 @@ leading to the `queryMap.json` file exist. You'll need to modify your network layer fetch implementation to pass a documentId parameter in the POST body instead of a query parameter: -```js - +```javascript function fetchQuery(operation, variables,) { return fetch('/graphql', { method: 'POST', @@ -99,7 +92,6 @@ function fetchQuery(operation, variables,) { return response.json(); }); } - ``` ## Executing Persisted Queries on the Server @@ -115,13 +107,11 @@ the query map file in a common location accessible to both the client and the se For applications where the client and server projects are separate, one option is to have an additional npm run script to push the query map at compile time to a location accessible by your server: -```js - +```javascript "scripts": { "push-queries": "node ./pushQueries.js", "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-ouput && npm run push-queries" } - ``` Some possibilities of what you can do in `./pushQueries.js`: @@ -145,8 +135,7 @@ database technologies you use, so we'll just cover the most common and basic exa If you use `express-graphql` and have access to the query map file, you can import the `--persist-output` JSON file directly and perform the matching using the `matchQueryMiddleware` from [relay-compiler-plus](https://github.com/yusinto/relay-compiler-plus). -```js - +```javascript import Express from 'express'; import expressGraphql from 'express-graphql'; import {matchQueryMiddleware} from 'relay-compiler-plus'; @@ -157,7 +146,6 @@ const app = Express(); app.use('/graphql', matchQueryMiddleware(queryMapJson), expressGraphql({schema})); - ``` ## Using `--persist-output` and `--watch` diff --git a/website/versioned_docs/version-v1.6.2/Modern-QueryRenderer.md b/website/versioned_docs/version-v1.6.2/Modern-QueryRenderer.md index 5b5fc9c90a237..6914b030ccd25 100644 --- a/website/versioned_docs/version-v1.6.2/Modern-QueryRenderer.md +++ b/website/versioned_docs/version-v1.6.2/Modern-QueryRenderer.md @@ -21,7 +21,6 @@ However, a `QueryRenderer` will not start loading its data until it is mounted, ## Example ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -53,5 +52,4 @@ class Example extends React.Component { ); } } - ``` diff --git a/website/versioned_docs/version-v1.6.2/Modern-RefetchContainer.md b/website/versioned_docs/version-v1.6.2/Modern-RefetchContainer.md index 25839f6aed901..416e049a71403 100644 --- a/website/versioned_docs/version-v1.6.2/Modern-RefetchContainer.md +++ b/website/versioned_docs/version-v1.6.2/Modern-RefetchContainer.md @@ -16,13 +16,11 @@ Table of Contents: `createRefetchContainer` has the following signature: ```javascript - createRefetchContainer( component: ReactComponentClass, fragmentSpec: GraphQLTaggedNode | {[string]: GraphQLTaggedNode}, refetchQuery: GraphQLTaggedNode, ): ReactComponentClass; - ``` ### Arguments @@ -40,7 +38,6 @@ createRefetchContainer( The Component resulting from `createRefetchContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -48,7 +45,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -64,7 +60,6 @@ type Props = { `refetch` has the following signature: ```javascript - type RefetchOptions = { force?: boolean, }; @@ -104,7 +99,6 @@ Returns a `Disposable` on which you could call `dispose()` to cancel the refetch In this simple example, let's assume we want to fetch the latest data for a `TodoItem` from the server: ```javascript - // TodoItem.js import {createRefetchContainer, graphql} from 'react-relay'; @@ -148,7 +142,6 @@ export default createRefetchContainer( } ` ); - ``` ### Loading more data @@ -156,7 +149,6 @@ export default createRefetchContainer( In this example we are using a Refetch Container to fetch more stories in a story feed component. ```javascript - import {createRefetchContainer, graphql} from 'react-relay'; class FeedStories extends React.Component { @@ -212,5 +204,4 @@ export default createRefetchContainer( } `, ); - ``` diff --git a/website/versioned_docs/version-v1.6.2/Modern-RelayCompat.md b/website/versioned_docs/version-v1.6.2/Modern-RelayCompat.md index 36632d3a8f1a1..f47dbd845ba3e 100644 --- a/website/versioned_docs/version-v1.6.2/Modern-RelayCompat.md +++ b/website/versioned_docs/version-v1.6.2/Modern-RelayCompat.md @@ -31,7 +31,6 @@ Relay Modern. The components using Relay Compat can be referred to by both other Relay Modern and Relay Classic components. ```javascript - const {createFragmentContainer, graphql} = require('react-relay/compat'); class TodoItem extends React.Component { @@ -47,5 +46,4 @@ module.exports = createFragmentContainer(TodoItem, graphql` isComplete } `); - ``` diff --git a/website/versioned_docs/version-v1.6.2/Modern-RelayEnvironment.md b/website/versioned_docs/version-v1.6.2/Modern-RelayEnvironment.md index b356b5deecdc5..ed75bc69d1f86 100644 --- a/website/versioned_docs/version-v1.6.2/Modern-RelayEnvironment.md +++ b/website/versioned_docs/version-v1.6.2/Modern-RelayEnvironment.md @@ -12,7 +12,6 @@ Most applications will create a single Environment instance and use it throughou To create an environment instance in Relay Modern, use the `RelayModernEnvironment` class: ```javascript - const { Environment, Network, @@ -30,7 +29,6 @@ const environment = new Environment({ network, store, }); - ``` For more details on creating a Network, see the [NetworkLayer guide](./network-layer). @@ -44,7 +42,6 @@ The example above did not configure a `handlerProvider`, which means that a defa If you wish to provide your own `handlerProvider`, you can do so: ```javascript - const { ConnectionHandler, ViewerHandler, @@ -60,5 +57,4 @@ function handlerProvider(handle) { `handlerProvider: No handler provided for ${handle}` ); } - ``` diff --git a/website/versioned_docs/version-v1.6.2/Modern-RelayStore.md b/website/versioned_docs/version-v1.6.2/Modern-RelayStore.md index 91845846694f4..e8e2df3d9efcf 100644 --- a/website/versioned_docs/version-v1.6.2/Modern-RelayStore.md +++ b/website/versioned_docs/version-v1.6.2/Modern-RelayStore.md @@ -16,7 +16,6 @@ Table of Contents: The `RecordSourceSelectorProxy` is the type of the `store` that [`updater` functions](./mutations#using-updater-and-optimisticupdater) receive as an argument. The following is the `RecordSourceSelectorProxy` interface: ```javascript - interface RecordSourceSelectorProxy { create(dataID: string, typeName: string): RecordProxy; delete(dataID: string): void; @@ -25,7 +24,6 @@ interface RecordSourceSelectorProxy { getRootField(fieldName: string): ?RecordProxy; getPluralRootField(fieldName: string): ?Array; } - ``` ### `create(dataID: string, typeName: string): RecordProxy` @@ -35,9 +33,7 @@ Creates a new record in the store given a `dataID` and the `typeName` as defined #### Example ```javascript - const record = store.create(dataID, 'Todo'); - ``` ### `delete(dataID: string): void` @@ -47,9 +43,7 @@ Deletes a record from the store given its `dataID`. #### Example ```javascript - store.delete(dataID); - ``` ### `get(dataID: string): ?RecordProxy` @@ -59,9 +53,7 @@ Retrieves a record from the store given its `dataID`. Returns a [`RecordProxy`]( #### Example ```javascript - const record = store.get(dataID); - ``` ### `getRoot(): RecordProxy` @@ -73,20 +65,16 @@ Returns the [`RecordProxy`](#recordproxy) representing the root of the GraphQL d Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - // Represents root query const root = store.getRoot(); - ``` ### `getRootField(fieldName: string): ?RecordProxy` @@ -98,19 +86,15 @@ Retrieves a root field from the store given the `fieldName`, as defined by the G Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - const viewer = store.getRootField('viewer'); - ``` ### `getPluralRootField(fieldName: string): ?Array` @@ -122,19 +106,15 @@ Retrieves a root field that represents a collection from the store given the `fi Given the GraphQL document: ```graphql - nodes(first: 10) { # ... } - ``` Usage: ```javascript - const nodes = store.getPluralRootField('nodes'); - ``` ## RecordProxy @@ -142,7 +122,6 @@ const nodes = store.getPluralRootField('nodes'); The `RecordProxy` serves as an interface to mutate records: ```javascript - interface RecordProxy { copyFieldsFrom(sourceRecord: RecordProxy): void; getDataID(): string; @@ -167,7 +146,6 @@ interface RecordProxy { ): RecordProxy; setValue(value: mixed, name: string, arguments?: ?Object): RecordProxy; } - ``` ### `getDataID(): string` @@ -177,9 +155,7 @@ Returns the dataID of the current record. #### Example ```javascript - const id = record.getDataID(); - ``` ### `getType(): string` @@ -189,7 +165,6 @@ Gets the type of the current record, as defined by the GraphQL schema. #### Example ```javascript - const type = user.getType(); // User ``` @@ -203,20 +178,16 @@ Gets the value of a field in the current record given the field name. Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - const name = viewer.getValue('name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. @@ -226,20 +197,16 @@ Optionally, if the field takes arguments, you can pass a bag of `variables`. Given the GraphQL document: ```graphql - viewer { id name(arg: $arg) } - ``` Usage: ```javascript - const name = viewer.getValue('name', {arg: 'value'}); - ``` ### `getLinkedRecord(name: string, arguments?: ?Object): ?RecordProxy` @@ -251,23 +218,19 @@ Retrieves the a record associated with the current record given the field name, Given the GraphQL document: ```graphql - rootField { viewer { id name } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -277,22 +240,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { viewer(arg: $arg) { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {arg: 'value'}); - ``` ### `getLinkedRecords(name: string, arguments?: ?Object): ?Array` @@ -304,22 +263,18 @@ Retrieves the set of records associated with the current record given the field Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const nodes = rootField.getLinkedRecord('nodes'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -329,22 +284,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { nodes(first: $count) { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {count: 10}); - ``` ### `getOrCreateLinkedRecord(name: string, typeName: string, arguments?: ?Object)` @@ -356,19 +307,16 @@ Retrieves the a record associated with the current record given the field name, Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = rootField.getOrCreateLinkedRecord('viewer', 'User'); // Will create if it doesn't exist @@ -383,28 +331,22 @@ Mutates the current record by setting a new value on the specified field. Return Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - viewer.setValue('New Name', 'name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. ```javascript - viewer.setValue('New Name', 'name', {arg: 'value'}); - ``` ### `copyFieldsFrom(sourceRecord: RecordProxy): void` @@ -414,7 +356,6 @@ Mutates the current record by copying the fields over from the passed in record #### Example ```javascript - const record = store.get(id1); const otherRecord = store.get(id2); record.copyFieldsFrom(otherRecord); // Mutates `record` @@ -430,19 +371,16 @@ Mutates the current record by setting a new linked record on the given the field Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = store.create(/* ... */)'' rootField.setLinkedRecord(newViewer, 'viewer'); // @@ -460,19 +398,16 @@ Mutates the current record by setting a new set of linked records on the given t Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newNode = store.create(/* ... */); const newNodes = [...rootField.getLinkedRecords('nodes'), newNode]; @@ -487,7 +422,6 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl `ConnectionHandler` is a utility module exposed by `relay-runtime` that aids in the manipulation of connections. `ConnectionHandler` exposes the following interface: ```javascript - interface ConnectionHandler { getConnection( record: RecordProxy, @@ -512,7 +446,6 @@ interface ConnectionHandler { ): void, deleteNode(connection: RecordProxy, nodeID: string): void } - ``` ### `getConnection(record: RecordProxy, key: string, filters?: ?Object)` @@ -522,7 +455,6 @@ Given a record and a connection key, and optionally a set of filters, `getConnec First, let's take a look at a plain connection: ```graphql - fragment FriendsFragment on User { friends(first: 10) { edges { @@ -532,26 +464,22 @@ fragment FriendsFragment on User { } } } - ``` Accessing a plain connection field like this is the same as other regular field: ```javascript - // The `friends` connection record can be accessed with: const user = store.get(userID); const friends = user && user.getLinkedRecord(user, 'friends'); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` In a [pagination container](./pagination-container), we usually annotate the actual connection field with `@connection` to tell Relay which part needs to be paginated: ```graphql - fragment FriendsFragment on User { friends(first: 10, orderby: "firstname") @connection( key: "FriendsFragment_friends", @@ -563,7 +491,6 @@ fragment FriendsFragment on User { } } } - ``` For connections like the above, `ConnectionHandler` helps us find the record: @@ -581,7 +508,6 @@ const friends = ConnectionHandler.getConnection( ); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` ### Edge creation and insertion @@ -611,7 +537,6 @@ ConnectionHandler.insertEdgeAfter(friends, edge); // No cursor provided, Insert the edge at the front: ConnectionHandler.insertEdgeBefore(friends, edge); - ``` ### `deleteNode(connection: RecordProxy, nodeID: string): void` @@ -625,5 +550,4 @@ Given a connection, deletes any edges whose id matches the given id. const user = store.get(userID); const friends = ConnectionHandler.getConnection(user, 'friends'); ConnectionHandler.deleteNode(friends, idToDelete); - ``` diff --git a/website/versioned_docs/version-v1.6.2/Modern-Subscriptions.md b/website/versioned_docs/version-v1.6.2/Modern-Subscriptions.md index a02a27933c40a..c4e9b324730f0 100644 --- a/website/versioned_docs/version-v1.6.2/Modern-Subscriptions.md +++ b/website/versioned_docs/version-v1.6.2/Modern-Subscriptions.md @@ -6,7 +6,6 @@ original_id: subscriptions Relay exposes the following APIs to create subscriptions. ```javascript - const {requestSubscription} = require('react-relay'); type Variables = {[name: string]: any}; @@ -23,7 +22,6 @@ requestSubscription( configs?: Array, }, ); - ``` Now let's take a closer look at the `config`: @@ -47,7 +45,6 @@ appropriate when you are only changing the properties of existing records that can be identified by their `id`: ```javascript - const { requestSubscription, graphql, @@ -81,7 +78,6 @@ requestSubscription( onError: error => console.error(error), } ); - ``` # Updating the client on each response @@ -91,7 +87,6 @@ Relay's in-memory cache when each subscription response is received. To do so, pass an `updater` function: ```javascript - const {ConnectionHandler} = require('relay-runtime'); requestSubscription( @@ -117,5 +112,4 @@ requestSubscription( }, }, ); - ``` diff --git a/website/versioned_docs/version-v1.6.2/Modern-TestingRelayComponents.md b/website/versioned_docs/version-v1.6.2/Modern-TestingRelayComponents.md index f30317b146e96..eaa443bd20147 100644 --- a/website/versioned_docs/version-v1.6.2/Modern-TestingRelayComponents.md +++ b/website/versioned_docs/version-v1.6.2/Modern-TestingRelayComponents.md @@ -64,7 +64,6 @@ With the `MockPayloadGenerator` and `@relay_test_operation`, we want to get rid Example of a simple Mock Resolver: ```javascript - { ID() { // Return mock value for a scalar filed with type ID @@ -75,13 +74,11 @@ Example of a simple Mock Resolver: return "Lorem Ipsum" } } - ``` It is possible to define more resolvers for Object types: ```javascript - { // This will be the default values for User object in the query response User() { @@ -94,7 +91,6 @@ It is possible to define more resolvers for Object types: }; }, } - ``` ### Mock Resolver Context @@ -102,7 +98,6 @@ It is possible to define more resolvers for Object types: The first argument of the MockResolver is the object that contains Mock Resolver Context. It is possible to return dynamic values from mock resolvers based on the context - for instance, name or alias of the field, a path in the selection, arguments, or parent type. ```javascript - { String(context) { if (context.name === 'zip') { @@ -116,7 +111,6 @@ The first argument of the MockResolver is the object that contains Mock Resolver } } } - ``` ### ID Generation @@ -124,14 +118,12 @@ The first argument of the MockResolver is the object that contains Mock Resolver The second argument of the Mock Resolver its a function that will generate a sequence of integers, useful to generate unique IDs in the tests: ```javascript - { // will generate strings "my-id-1", "my-id-2", etc. ID(_, generateId) { return `my-id-${generateId()}`; }, } - ``` ### `@relay_test_operation` @@ -141,7 +133,6 @@ Most of GraphQL type information for a specific field in the selection is not av Operations with the `@relay_test_operation` directive will have additional metadata that will contain GraphQL type info for fields in the operation's selection. And it will improve the quality of the generated data. You also will be able to define Mock resolvers for Scalar (not only ID and String) and Abstract types: ```javascript - { Float() { return 123.456; @@ -159,7 +150,6 @@ Operations with the `@relay_test_operation` directive will have additional metad }; } } - ``` ## Examples @@ -169,7 +159,6 @@ Operations with the `@relay_test_operation` directive will have additional metad Using `createMockEnvironment` and `MockPayloadGenerator` allows writing concise tests for components that are using Relay Containers and Renderers. Both those modules can be imported from `relay-test-utils`. ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { @@ -222,7 +211,6 @@ test('Error State', () => { renderer.root.find(item => (item.props.testID = 'errorMessage')), ).toBeDefined(); }); - ``` ### Fragment Container Tests @@ -230,7 +218,6 @@ test('Error State', () => { Essentially, in the example above, `resolveMostRecentOperation` will generate data for all child fragment containers (pagination, refetch). Usually, the Root Components container may have many child fragment components and you may want to exercise a specific Fragment Container. The solution for that would be to wrap your fragment container with the QueryRenderer that renders a Query that's spreads fragments from your fragment container. ```javascript - test('Fragment Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -261,7 +248,6 @@ test('Fragment Container', () => { expect(renderer).toMatchSnapshot(); }); - ``` ### Pagination Container Test @@ -269,7 +255,6 @@ test('Fragment Container', () => { Essentially, tests for Pagination container are not different from Fragment Container tests. We can also do more here. We can actually see how the pagination works by asserting the behavior of our components when performing pagination (load more, refetch). ```javascript - // Pagination Example test('Pagination Container', () => { const environment = createMockEnvironment(); @@ -343,7 +328,6 @@ test('Pagination Container', () => { We can use similar approach here with wrapping container with Query Renderer. And for the sake of completeness, we will add example here: ```javascript - test('Refetch Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -385,7 +369,6 @@ test('Refetch Container', () => { ); // expect(renderer).toMatchSnapshot(); }); - ``` ### Mutations @@ -393,7 +376,6 @@ test('Refetch Container', () => { Mutations itself are operations so we can test them independently (unit-test) for specific mutation, or in combination with the view from which this mutation is called. ```javascript - // Say, you have a mutation function function sendMutation(environment, onCompleted, onError, variables) commitMutation(environment, { @@ -416,7 +398,6 @@ test('it should send mutation', () => { ); expect(onCompleted).toBeCalled(); }); - ``` ### Subscription @@ -424,7 +405,6 @@ test('it should send mutation', () => { We can test subscription in a similar way we test mutations ```javascript - // Example subscribe function function subscribe(environment, onNext, onError, variables) requestSubscription(environment, { @@ -447,7 +427,6 @@ test('it should subscribe', () => { ); expect(onNext).toBeCalled(); }); - ``` ### Example with `queueOperationResolver` @@ -455,7 +434,6 @@ test('it should subscribe', () => { With `queueOpeararionResolver`, it possible to define responses for operations that will be executed on the environment ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { diff --git a/website/versioned_docs/version-v1.6.2/Modern-TypeEmission.md b/website/versioned_docs/version-v1.6.2/Modern-TypeEmission.md index c25bc737d5684..9f41810a3618b 100644 --- a/website/versioned_docs/version-v1.6.2/Modern-TypeEmission.md +++ b/website/versioned_docs/version-v1.6.2/Modern-TypeEmission.md @@ -15,7 +15,6 @@ In this example the emitted type-information would require the variables object #### Flow ```javascript - /** * export type ExampleQueryVariables = {| * +artistID: string @@ -43,7 +42,6 @@ const variables: ExampleQueryVariables = { #### TypeScript ```javascript - /** * export type ExampleQueryVariables = { * readonly artistID: string @@ -78,7 +76,6 @@ In this example the emitted type-information describes the response data availab #### Flow ```javascript - /** * export type ExampleQueryResponse = {| * +artist: ?{| @@ -109,7 +106,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * export type ExampleQueryResponse = { * readonly artist?: { @@ -145,7 +141,6 @@ Similarly, in this example the emitted type-information describes the prop data #### Flow ```javascript - /** * export type ExampleFragment_artist = {| * +name: string @@ -171,7 +166,6 @@ export const ExampleFragment = createFragmentContainer( #### TypeScript ```javascript - /** * export type ExampleFragment_artist = { * readonly name: string @@ -205,7 +199,6 @@ Consider a component that composes the above fragment container example. In this #### Flow ```javascript - /** * import type { FragmentReference } from "relay-runtime"; * declare export opaque type ExampleFragment_artist$ref: FragmentReference; @@ -249,7 +242,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * declare const _ExampleFragment_artist$ref: unique symbol; * export type ExampleFragment_artist$ref = typeof _ExampleFragment_artist$ref; @@ -314,7 +306,6 @@ $ relay-compiler --artifactDirectory ./src/__generated__ […] ["relay", { "artifactDirectory": "./src/__generated__" }] ] } - ``` It is recommended to alias this directory in your module resolution configuration such that you don’t need to specify relative paths in your source files. This is what is also done in the above examples, where artifacts are imported from a `__generated__` alias, rather than relative paths like `../../../../__generated__`. diff --git a/website/versioned_docs/version-v1.6.2/Modern-UpgradingSetVariables.md b/website/versioned_docs/version-v1.6.2/Modern-UpgradingSetVariables.md index d5b086fafce20..ff73feec04f8b 100644 --- a/website/versioned_docs/version-v1.6.2/Modern-UpgradingSetVariables.md +++ b/website/versioned_docs/version-v1.6.2/Modern-UpgradingSetVariables.md @@ -36,7 +36,6 @@ fragment on User { # ... } } - ``` This should be upgraded to use a [`PaginationContainer`](./pagination-container). @@ -61,7 +60,6 @@ fragment on User { # ... } } - ``` This can be upgraded by using a [`RefetchContainer`](./refetch-container) which allows you to specify the exact query to use to fetch the new data. @@ -86,7 +84,6 @@ fragment on FeedbackTarget { # ... } } - ``` This can be upgraded by conditionally rendering a [`QueryRenderer`](./query-renderer) which will load the data once it is rendered. The code overhead of doing this is dramatically reduced with the new API. diff --git a/website/versioned_docs/version-v1.6.2/Modern-fetchQuery.md b/website/versioned_docs/version-v1.6.2/Modern-fetchQuery.md index 19e9b57c4219a..223c01ccc75c2 100644 --- a/website/versioned_docs/version-v1.6.2/Modern-fetchQuery.md +++ b/website/versioned_docs/version-v1.6.2/Modern-fetchQuery.md @@ -5,7 +5,6 @@ title: fetchQuery You can use the `fetchQuery` function to imperatively make GraphQL Requests. This is useful for cases where you want to make requests outside of React but still utilize the Relay store and network layer. ```javascript - import {fetchQuery, graphql} from 'relay-runtime'; const query = graphql` @@ -24,7 +23,6 @@ fetchQuery(environment, query, variables) .then(data => { // access the graphql response }); - ``` ## Arguments diff --git a/website/versioned_docs/version-v1.6.2/PrinciplesAndArchitecture-Compiler.md b/website/versioned_docs/version-v1.6.2/PrinciplesAndArchitecture-Compiler.md index c195491682b1f..fcd0490cb724f 100644 --- a/website/versioned_docs/version-v1.6.2/PrinciplesAndArchitecture-Compiler.md +++ b/website/versioned_docs/version-v1.6.2/PrinciplesAndArchitecture-Compiler.md @@ -74,7 +74,6 @@ foo { # type FooType foo { id } - ``` - `SkipRedundantNodeTransform`: A more advanced version of flattening, this eliminates more complex cases of field duplication such as when a field is fetched both unconditionally and conditionally, or is fetched by two different sub-fragments. For example: @@ -97,7 +96,6 @@ foo { id } } - ``` - `GenerateRequisiteFieldTransform`: This optional, Relay-specific transform inserts `id` fields for globally identifiable objects and `__typename` fields wherever the type cannot be statically determined (e.g. for unions). diff --git a/website/versioned_docs/version-v1.6.2/PrinciplesAndArchitecture-Runtime.md b/website/versioned_docs/version-v1.6.2/PrinciplesAndArchitecture-Runtime.md index f012908d090c5..e9c88a4b2ae0c 100644 --- a/website/versioned_docs/version-v1.6.2/PrinciplesAndArchitecture-Runtime.md +++ b/website/versioned_docs/version-v1.6.2/PrinciplesAndArchitecture-Runtime.md @@ -77,7 +77,6 @@ RecordSource { city: 'Seattle', } } - ``` [1] Note that GraphQL itself does not impose this constraint, and Relay Runtime may also be used for schemas that do not conform to it. For example, both systems can be used to query a single denormalized table. However, many of the features that Relay Runtime provides, such as caching and normalization, work best when the data is represented as a normalized graph with stable identities for discrete pieces of information. diff --git a/website/versioned_docs/version-v1.6.2/PrinciplesAndArchitecture-ThinkingInGraphQL.md b/website/versioned_docs/version-v1.6.2/PrinciplesAndArchitecture-ThinkingInGraphQL.md index 14b1119288f23..9527e65e8950e 100644 --- a/website/versioned_docs/version-v1.6.2/PrinciplesAndArchitecture-ThinkingInGraphQL.md +++ b/website/versioned_docs/version-v1.6.2/PrinciplesAndArchitecture-ThinkingInGraphQL.md @@ -12,7 +12,6 @@ In this article we'll explore what it means to build a GraphQL client framework Imagine we have a simple application that fetches a list of stories, and some details about each one. Here's how that might look in resource-oriented REST: ```javascript - // Fetch the list of story IDs but not their details: rest.get('/stories').then(stories => // This resolves to a list of items with linked resources: @@ -25,13 +24,11 @@ rest.get('/stories').then(stories => // `[ { id: "...", text: "..." } ]` console.log(stories); }); - ``` Note that this approach requires _n+1_ requests to the server: 1 to fetch the list, and _n_ to fetch each item. With GraphQL we can fetch the same data in a single network request to the server (without creating a custom endpoint that we'd then have to maintain): ```javascript - graphql.get(`query { stories { id, text } }`).then( stories => { // A list of story items: @@ -39,7 +36,6 @@ graphql.get(`query { stories { id, text } }`).then( console.log(stories); } ); - ``` So far we're just using GraphQL as a more efficient version of typical REST approaches. Note two important benefits in the GraphQL version: @@ -56,7 +52,6 @@ Repeatedly refetching information from the server can get quite slow. For exampl In a resource-oriented REST system, we can maintain a **response cache** based on URIs: ```javascript - var _cache = new Map(); rest.get = uri => { if (!_cache.has(uri)) { @@ -64,13 +59,11 @@ rest.get = uri => { } return _cache.get(uri); }; - ``` Response-caching can also be applied to GraphQL. A basic approach would work similarly to the REST version. The text of the query itself can be used as a cache key: ```javascript - var _cache = new Map(); graphql.get = queryText => { if (!_cache.has(queryText)) { @@ -78,7 +71,6 @@ graphql.get = queryText => { } return _cache.get(queryText); }; - ``` Now, requests for previously cached data can be answered immediately without making a network request. This is a practical approach to improving the perceived performance of an application. However, this method of caching can cause problems with data consistency. @@ -90,7 +82,6 @@ With GraphQL it is very common for the results of multiple queries to overlap. H ``` query { stories { id, text, likeCount } } - ``` and then later refetch one of the stories whose `likeCount` has since been incremented: @@ -98,7 +89,6 @@ and then later refetch one of the stories whose `likeCount` has since been incre ``` query { story(id: "123") { id, text, likeCount } } - ``` We'll now see different `likeCount`s depending on how the story is accessed. A view that uses the first query will see an outdated count, while a view using the second query will see the updated count. @@ -119,7 +109,6 @@ query { } } } - ``` And here's a possible response: @@ -134,13 +123,11 @@ query: { } } } - ``` Although the response is hierarchical, we'll cache it by flattening all the records. Here is an example of how Relay would cache this query response: ```javascript - Map { // `story(id: "1")` 1: Map { @@ -152,7 +139,6 @@ Map { name: 'Jan', }, }; - ``` This is only a simple example: in reality the cache must handle one-to-many associations and pagination (among other things). @@ -182,7 +168,6 @@ The first query was for a list of stories: ``` query { stories { id, text, likeCount } } - ``` With a normalized response cache, a record would be created for each story in the list. The `stories` field would store links to each of these records. @@ -192,7 +177,6 @@ The second query refetched the information for one of those stories: ``` query { story(id: "123") { id, text, likeCount } } - ``` When this response is normalized, Relay can detect that this result overlaps with existing data based on its `id`. Rather than create a new record, Relay will update the existing `123` record. The new `likeCount` is therefore available to _both_ queries, as well as any other query that might reference this story. @@ -215,7 +199,6 @@ query { } } } - ``` After initially fetching this story our cache might be as follows. Note that the story and comment both link to the same record as `author`: @@ -242,7 +225,6 @@ Map { author: Link(2), }, } - ``` The author of this story also commented on it — quite common. Now imagine that some other view fetches new information about the author, and her profile photo has changed to a new URI. Here's the _only_ part of our cached data that changes: @@ -256,7 +238,6 @@ Map { photo: 'http://.../photo2.jpg', }, } - ``` The value of the `photo` field has changed; and therefore the record `2` has also changed. And that's it. Nothing else in the _cache_ is affected. But clearly our _view_ needs to reflect the update: both instances of the author in the UI (as story author and comment author) need to show the new photo. @@ -273,7 +254,6 @@ ImmutableMap { }, 3: ImmutableMap // same as before } - ``` If we replace `2` with a new immutable record, we'll also get a new immutable instance of the cache object. However, records `1` and `3` are untouched. Because the data is normalized, we can't tell that `story`'s contents have changed just by looking at the `story` record alone. @@ -299,7 +279,6 @@ mutation StoryLike($storyID: String) { likeCount } } - ``` Notice that we're querying for data that _may_ have changed as a result of the mutation. An obvious question is: why can't the server just tell us what changed? The answer is: it's complicated. GraphQL abstracts over _any_ data storage layer (or an aggregation of multiple sources), and works with any programming language. Furthermore, the goal of GraphQL is to provide data in a form that is useful to product developers building a view. diff --git a/website/versioned_docs/version-v1.6.2/PrinciplesAndArchitecture-ThinkingInRelay.md b/website/versioned_docs/version-v1.6.2/PrinciplesAndArchitecture-ThinkingInRelay.md index 47c27f92ab909..1ffea144589ad 100644 --- a/website/versioned_docs/version-v1.6.2/PrinciplesAndArchitecture-ThinkingInRelay.md +++ b/website/versioned_docs/version-v1.6.2/PrinciplesAndArchitecture-ThinkingInRelay.md @@ -30,13 +30,11 @@ fragment Story_story on Story { photo } } - ``` And this fragment can then be used to define the Story container: ```javascript - const {createFragmentContainer, graphql} = require('react-relay'); // Plain React component. @@ -64,7 +62,6 @@ const StoryContainer = createFragmentContainer(Story, { In React, rendering a view requires two inputs: the _component_ to render, and a _root_ DOM (UI) node to render into. Rendering Relay containers is similar: we need a _container_ to render, and a _root_ in the graph from which to start our query. We also must ensure that the queries for the container are executed and may want to show a loading indicator while data is being fetched. Similar to `ReactDOM.render(component, domNode)`, Relay provides `` for this purpose. The `query` and `variables` define what data to fetch and `render` defines what to render. Here's how we might render ``: ```javascript - ReactDOM.render( { ); } } - ``` The above code is doing something very similar to our [previous example](#rendering-graphql-queries). However, we are now passing a `$userID` variable to the GraphQL query via the `variables` prop. This has a couple of important implications: @@ -229,7 +217,6 @@ Now that we know how to define and fetch queries, let's actually start building First, let's start at the bottom. Suppose that we want to render a component that simply displays a given todo item's text and completed state: ```javascript - // Todo.js import React from 'react'; @@ -259,7 +246,6 @@ export default class Todo extends React.Component { ); } } - ``` From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L107), we know that we can query this data on the `Todo` type. However, we don't want to have to send a separate query for each todo item; that would defeat the purpose of using GraphQL over a traditional REST API. We could manually query for these fields directly in our `QueryRenderer` query, but that would hurt re-usability: what if we want to query the same set of fields as part of a different query? Additionally, we wouldn't know which component needs the data we're querying, which is a problem Relay directly tries to address. @@ -267,18 +253,15 @@ From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/dat Instead, we can define a reusable [Fragment](http://graphql.org/learn/queries/#fragments), which allows us to define a set of fields on a type and reuse them within our queries wherever we need to: ```graphql - fragment TodoItemFragment on Todo { complete text } - ``` Our component can then use this fragment to declare its data dependency on the `Todo` GraphQL type: ```javascript - // Todo.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -338,7 +321,6 @@ Before proceeding, don't forget to run the Relay Compiler with `yarn relay`. Given that [Fragment Containers](./fragment-container) are just React components, we can compose them as such. We can even re-use fragment containers within other fragment containers. As an example, let's see how we would define a `TodoList` component that just renders a list of todo items, and whether all have been completed or not: ```javascript - // TodoList.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -397,7 +379,6 @@ export default createFragmentContainer( } `, ); - ``` As with the first fragment container we defined, `TodoList` declares it's data dependencies via a fragment. However, this component additionally re-uses the fragment previously defined by the `Todo` component, and passes the appropriate data when rendering the child `Todo` components (a.k.a. fragment containers). @@ -412,7 +393,6 @@ fragment containers do not directly fetch data. Instead, containers declare a sp A `QueryRenderer` rendering these fragment containers could look like the following: ```javascript - // ViewerTodoList.js import React from 'react'; import PropTypes from 'prop-types'; @@ -454,7 +434,6 @@ export default class ViewerTodoList extends React.Component { ); } } - ``` Check out our docs for [Fragment Containers](./fragment-container) for more details, and our guides on [Refetch](./refetch-container) and [Pagination](./pagination-container) for more advanced usage of containers. @@ -466,7 +445,6 @@ Now that we know how to query for and render data, let's move on to changing our From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L35), we know that we have some mutations available to us, so let's start by writing a mutation to change the `complete` status of a given todo item (i.e. mark or unmark it as done): ```graphql - mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { changeTodoStatus(input: $input) { todo { @@ -475,7 +453,6 @@ mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { } } } - ``` This mutation allows us to query back some data as a [result of the mutation](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L18), so we're going to query for the updated `complete` status on the todo item. @@ -483,7 +460,6 @@ This mutation allows us to query back some data as a [result of the mutation](ht In order to execute this mutation in Relay, we're going to write a new mutation using Relay's `commitMutation` api: ```javascript - // ChangeTodoStatusMutation.js import {graphql, commitMutation} from 'react-relay'; @@ -517,7 +493,6 @@ function commit( } export default {commit}; - ``` Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mutation to the server and, in our case, upon receiving a response it will automatically update the local data store with the latest data from the server. This also means that upon receiving the response, Relay will ensure that any components (i.e. containers) that depend on the updated data are re-rendered. @@ -525,7 +500,6 @@ Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mut In order to actually use this mutation in our component, we could update our `Todo` component in the following way: ```javascript - // Todo.js // ... @@ -559,7 +533,6 @@ In order to make the experience better, we can configure our mutation to do an o In Relay, there's a couple of options we can pass to `commitMutation` to enable optimistic updates. Let's see what that would look like in our `ChangeTodoStatusMutation`: ```javascript - // ChangeTodoStatusMutation.js // ... @@ -594,7 +567,6 @@ function commit( } export default {commit}; - ``` In the simplest case above, we just need to pass an `optimisticResponse` option, which should refer to an object having the same shape as the mutation response payload. When we pass this option, Relay will know to immediately update our local data with the optimistic response, and then update it with the actual server response or roll it back if an error occurs. diff --git a/website/versioned_docs/version-v1.7.0/Modern-ConvertingMutations.md b/website/versioned_docs/version-v1.7.0/Modern-ConvertingMutations.md index 08ad2e998cb2d..8f4bdc1d8e0d2 100644 --- a/website/versioned_docs/version-v1.7.0/Modern-ConvertingMutations.md +++ b/website/versioned_docs/version-v1.7.0/Modern-ConvertingMutations.md @@ -12,19 +12,16 @@ FatQueries in Relay Classic mutations was a concept that was confusing for a num Example of existing fat query: ```javascript - RelayClassic.QL` fragment on MarkReadNotificationResponsePayload @relay(pattern: true) { notification } `; - ``` Example of converted mutation query: ```javascript - graphql` mutation MarkReadNotificationMutation( $input: MarkReadNotificationData! @@ -37,7 +34,6 @@ graphql` } } `; - ``` ## Migrating Configs @@ -67,7 +63,6 @@ This is no longer needed in Compatibility Mode for neither environments. Simply Take this example of a simple mutation in Relay Classic: ```javascript - class LikeStoryMutation extends RelayClassic.Mutation { getMutation() { return RelayClassic.QL`mutation {likeStory}`; @@ -106,7 +101,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { `, }; } - ``` ### Converting `getMutation()` and `getFatQuery()` @@ -114,7 +108,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { We combine these two into a regular GraphQL mutation, which list out specific fields that needs to be updated. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story(data: $input) { @@ -126,7 +119,6 @@ const mutation = graphql` } } `; - ``` ### Converting `getConfigs()` @@ -138,13 +130,11 @@ As specified above, `FIELDS_CHANGE` configs can be omitted. To convert `getVariables()`, we take the return value from the original function and wrap it in an object that contains a property that matches the variable name for the mutation. In this case, the mutation has a `input` variable that is of type `LikeStoryData`. ```javascript - const variables = { input: { storyID: args.storyID } } - ``` ### Final Result @@ -152,7 +142,6 @@ const variables = { As you can see, our resulting mutation is a lot simpler and more like regular GraphQL than the Relay Classic version we started out with. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story { @@ -178,7 +167,6 @@ function commit(environment: CompatEnvironment, args) { variables, }); } - ``` See [Mutation](./mutations) for additional options on `commitMutation` for more complex mutations. diff --git a/website/versioned_docs/version-v1.7.0/Modern-FragmentContainer.md b/website/versioned_docs/version-v1.7.0/Modern-FragmentContainer.md index e86b79995c1c7..7bbd0a9f22899 100644 --- a/website/versioned_docs/version-v1.7.0/Modern-FragmentContainer.md +++ b/website/versioned_docs/version-v1.7.0/Modern-FragmentContainer.md @@ -17,12 +17,10 @@ Table of Contents: `createFragmentContainer` has the following signature: ```javascript - createFragmentContainer( component: ReactComponentClass, fragmentSpec: GraphQLTaggedNode | {[string]: GraphQLTaggedNode}, ): ReactComponentClass; - ``` ### Arguments @@ -46,7 +44,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -61,7 +58,6 @@ To start, let's build the plain React version of a hypothetical `` c Here's a basic implementation of `` that ignores styling in order to highlight the functionality: ```javascript - // TodoItem.js class TodoItem extends React.Component { render() { @@ -81,7 +77,6 @@ class TodoItem extends React.Component { ); } } - ``` ### Data Dependencies With GraphQL @@ -89,7 +84,6 @@ class TodoItem extends React.Component { In Relay, data dependencies are described using [GraphQL](https://github.com/facebook/graphql). For ``, the dependency can be expressed as follows. Note that this exactly matches the shape that the component expected for the `item` prop. ```javascript - graphql` # This fragment only applies to objects of type 'Todo'. fragment TodoItem_item on Todo { @@ -105,7 +99,6 @@ graphql` Given the plain React component and a GraphQL fragment, we can now define a Fragment Container to specify this component's data requirements. Let's look at the code first and then see what's happening: ```javascript - // TodoItem.js import {createFragmentContainer, graphql} from 'react-relay'; @@ -123,13 +116,11 @@ export default createFragmentContainer(TodoItem, { } `, }); - ``` Relay will infer the prop name from the fragment name according to the fragment naming convention `<...>_`. The example below is equivalent to the one above: ```javascript - export default createFragmentContainer( TodoItem, graphql` @@ -139,13 +130,11 @@ export default createFragmentContainer( } `, ); - ``` If there is no `_` suffix, the `data` prop name will be used: ```javascript - class TodoItem extends React.Component { render() { const item = this.props.data; @@ -162,7 +151,6 @@ export default createFragmentContainer( } `, ); - ``` ## Container Composition @@ -176,7 +164,6 @@ Let's explore how this works via a `` component that composes the `< View composition is _exactly_ what you're used to — Relay containers are just standard React components. Here's the `` component: ```javascript - class TodoList extends React.Component { render() { // Expects a `list` with a string `title`, as well as the information @@ -191,7 +178,6 @@ class TodoList extends React.Component { ); } } - ``` ### Composing Fragments @@ -199,7 +185,6 @@ class TodoList extends React.Component { Fragment composition works similarly — a parent container's fragment composes the fragment for each of its children. In this case, `` needs to fetch information about the `Todo`s that are required by ``. ```javascript - class TodoList extends React.Component // as above export default createFragmentContainer( @@ -217,7 +202,6 @@ export default createFragmentContainer( } `, ); - ``` Note that when composing fragments, the type of the composed fragment must match the field on the parent in which it is embedded. For example, it wouldn't make sense to embed a fragment of type `Story` into a parent's field of type `User`. Relay and GraphQL will provide helpful error messages if you get this wrong (and if they aren't helpful, let us know!). @@ -231,7 +215,6 @@ When defining a fragment, you can use the [`@argumentDefinitions`](./graphql-in- For example, let's redefine our `TodoList_list` fragment to take some arguments using `@argumentDefinitions`: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -241,7 +224,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` Any arguments defined inside `@argumentDefinitions` will be local variables available inside the fragment's scope. However, a fragment can also reference global variables that were defined in the root query. @@ -253,11 +235,9 @@ In order to pass arguments to a fragment that has `@argumentDefinitions`, you ne Following our `TodoList_list` example, we would pass arguments to the fragment like so: ```graphql - query TodoListQuery($count: Int, $userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` ### Calling Component Instance Methods @@ -268,7 +248,6 @@ Since Relay composes these component instances in a container, you need to use t Consider an input with a server-defined placeholder text and an imperative method to focus the input node: ```javascript - export default createFragmentContainer( class TodoInput extends React.Component { focus() { @@ -288,13 +267,11 @@ export default createFragmentContainer( } `, ); - ``` To call this method on the underlying component, first provide a `componentRef` function to the Relay container. This differs from providing a [`ref`](https://facebook.github.io/react/docs/refs-and-the-dom.html) function which would provide a reference to the Relay container itself, not the underlying React Component. ```javascript - export default createFragmentContainer( class TodoListView extends React.Component { render() { @@ -312,7 +289,6 @@ export default createFragmentContainer( } `, ); - ``` ## Rendering Containers diff --git a/website/versioned_docs/version-v1.7.0/Modern-GraphQLInRelay.md b/website/versioned_docs/version-v1.7.0/Modern-GraphQLInRelay.md index d39a31c6ad4ba..bd4133d7e74b9 100644 --- a/website/versioned_docs/version-v1.7.0/Modern-GraphQLInRelay.md +++ b/website/versioned_docs/version-v1.7.0/Modern-GraphQLInRelay.md @@ -14,7 +14,6 @@ Table of Contents: The `graphql` template tag provided by Relay serves as the mechanism to write queries, fragments, mutations or subscriptions in the [GraphQL](http://graphql.org/learn/) language. For example: ```javascript - import {graphql} from 'react-relay'; graphql` @@ -24,7 +23,6 @@ graphql` } } `; - ``` The result of using the `graphql` template tag are `GraphQLTaggedNode`s, which are used to define [Query Renderers](./query-renderer), [Fragment Containers](./fragment-container), [Refetch Containers](./refetch-container), [Pagination Containers](./pagination-container), etc. @@ -42,11 +40,9 @@ Relay uses directives to add additional information to GraphQL documents, which `@arguments` is a directive used to pass arguments to a fragment that was defined using [`@argumentDefinitions`](#argumentdefinitions). For example: ```graphql - query TodoListQuery($userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` See [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -56,7 +52,6 @@ See [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragme `@argumentDefinitions` is a directive used to specify arguments taken by a fragment. For example: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -66,7 +61,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` See [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -82,13 +76,11 @@ When using the [Pagination Container](./pagination-container), Relay expects con When defining a fragment, you can use the `@relay(plural: true)` directive to indicate that the fragment is backed by a [GraphQL list](http://graphql.org/learn/schema/#lists-and-non-null), meaning that it will inform Relay that this particular field is an array. For example: ```javascript - graphql` fragment TodoItems_items on TodoItem @relay(plural: true) { id text }`; - ``` ### `@relay(mask: Boolean)` @@ -106,7 +98,6 @@ Keep in mind that it is typically considered an **anti-pattern** to create a sin In the example below, the `user` prop will include the data for `id` and `name` fields wherever `...Component_internUser` is included, instead of Relay's normal behavior to mask those fields: ```javascript - graphql` fragment Component_internUser on InternUser @relay(mask: false) { id @@ -134,7 +125,6 @@ export default createFragmentContainer( } `, ); - ``` ## Relay Compiler @@ -144,7 +134,6 @@ Relay uses the Relay Compiler to convert [`graphql`](#graphql) literals into gen A query like the following: ```javascript - graphql` fragment MyComponent on Type { field @@ -168,7 +157,6 @@ See our relay-compiler section in our [Installation and Setup guide](./installat To use the Relay Compiler, you need either a .graphql or .json GraphQL schema file, describing your GraphQL server's API. Typically these files are local representations of a server source of truth and are not edited directly. For example, we might have a `schema.graphql` like: ```graphql - schema { query: Root } @@ -186,7 +174,6 @@ type WordDefinition { text: String image: String } - ``` ### Source files @@ -202,7 +189,6 @@ For example, given the two files: - `src/Components/DictionaryComponent.js` ```javascript - const DictionaryWordFragment = graphql` fragment DictionaryComponent_word on Word { id @@ -224,7 +210,6 @@ For example, given the two files: - `src/Queries/DictionaryQuery.js` ```javascript - const DictionaryQuery = graphql` query DictionaryQuery { dictionary { @@ -248,9 +233,7 @@ Typically you will not need to import your generated definitions. The [Relay Bab However the Relay Compiler also automatically generates [Flow](https://flow.org) types as [type comments](https://flow.org/en/docs/types/comments/). For example, you can import the generated Flow types like so: ```javascript - import type {DictionaryComponent_word} from './__generated__/DictionaryComponent_word.graphql'; - ``` ### Advanced usage diff --git a/website/versioned_docs/version-v1.7.0/Modern-LocalStateManagement.md b/website/versioned_docs/version-v1.7.0/Modern-LocalStateManagement.md index f3427f392a611..dc50079ca5fbe 100644 --- a/website/versioned_docs/version-v1.7.0/Modern-LocalStateManagement.md +++ b/website/versioned_docs/version-v1.7.0/Modern-LocalStateManagement.md @@ -23,23 +23,19 @@ It can even be used to extend an existing server schema. For example, we can create a new type called `Note`: ```graphql - type Note { id: ID! title: String body: String } - ``` And then extend the server schema type `User`, with a list of `Note`, called `notes`. ```graphql - extend type User { notes: [Note] } - ``` ## Querying local state @@ -50,7 +46,6 @@ The field can be from the server schema, or it can be schema agnostic, like an i Here, we use a [QueryRenderer](./query-renderer) to get the current `User` via the `viewer` field, along with their id, name and the local list of notes. ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -96,7 +91,6 @@ const Example = (props) => { /> ); } - ``` ## Mutating local state @@ -110,7 +104,6 @@ To build upon the previous example, let's try creating, updating and deleting a ### Create ```javascript - import {commitLocalUpdate} from 'react-relay'; let tempID = 0; @@ -130,7 +123,6 @@ function createUserNote() { user.setLinkedRecords([...userNoteRecords, newNoteRecord], 'notes'); }); } - ``` Note that since this record will be rendered by the `ExampleQuery` in our `QueryRenderer`, the QueryRenderer will automatically retain this data so it isn't garbage collected. @@ -138,7 +130,6 @@ Note that since this record will be rendered by the `ExampleQuery` in our `Query If no component is rendering the local data and you want to manually retain it, you can do so by calling `environment.retain()`: ```javascript - import {createOperationDescriptor, getRequest} from 'relay-runtime'; // Create a query that references that record @@ -165,13 +156,11 @@ const disposable = environment.retain(operation); // Whenever you don't need that data anymore and it's okay for Relay to garbage collect it, // you can dispose of the retain disposable.dispose(); - ``` ### Update ```javascript - import {commitLocalUpdate} from 'react-relay'; function updateUserNote(dataID, body, title) { @@ -182,13 +171,11 @@ function updateUserNote(dataID, body, title) { note.setValue(title, 'title') }); } - ``` ### Delete ```javascript - import {commitLocalUpdate} from 'react-relay'; function deleteUserNote(dataID) { @@ -206,7 +193,6 @@ function deleteUserNote(dataID) { user.setLinkedRecords(newUserNoteRecords, 'notes'); }); } - ``` ## Initial local state @@ -215,7 +201,6 @@ All new client-side schema fields default to `undefined` value. Often however, y You can use an updater function via `commitLocalUpdate` to prime local state. ```javascript - import {commitLocalUpdate} from 'react-relay'; commitLocalUpdate(environment, store => { @@ -224,5 +209,4 @@ commitLocalUpdate(environment, store => { // initialize user notes to an empty array. user.setLinkedRecords([], 'notes'); }); - ``` diff --git a/website/versioned_docs/version-v1.7.0/Modern-MigrationSetup.md b/website/versioned_docs/version-v1.7.0/Modern-MigrationSetup.md index 66f1145357e25..a89c0e178e0e5 100644 --- a/website/versioned_docs/version-v1.7.0/Modern-MigrationSetup.md +++ b/website/versioned_docs/version-v1.7.0/Modern-MigrationSetup.md @@ -13,13 +13,11 @@ With some additional configuration, the `"relay"` babel plugin can also translat Relay Classic `Relay.QL` literals. Most importantly, include a reference to your GraphQL Schema as either a json file or graphql schema file. ```javascript - { "plugins": [ ["relay", {"schema": "path/schema.graphql"}] ] } - ``` ## Set up babel-plugin-relay for "[compatibility mode](./relay-compat)" @@ -29,13 +27,11 @@ literals can be translated to be usable by _both_ runtimes if configured to use compatibility mode: ```javascript - { "plugins": [ ["relay", {"compat": true, "schema": "path/schema.graphql"}] ] } - ``` ## Additional Options @@ -47,7 +43,6 @@ thrown at runtime. When compiling code for production deployment, the plugin can be configured to immediately throw upon encountering a validation problem. The plugin can be further customized for different environments with the following options: ```javascript - { "plugins": [ ["relay", { @@ -56,5 +51,4 @@ When compiling code for production deployment, the plugin can be configured to i }] ] } - ``` diff --git a/website/versioned_docs/version-v1.7.0/Modern-Mutations.md b/website/versioned_docs/version-v1.7.0/Modern-Mutations.md index f872eaf88b3cb..22e7defebb85b 100644 --- a/website/versioned_docs/version-v1.7.0/Modern-Mutations.md +++ b/website/versioned_docs/version-v1.7.0/Modern-Mutations.md @@ -17,7 +17,6 @@ Table of Contents: Use `commitMutation` to create and execute mutations. `commitMutation` has the following signature: ```javascript - commitMutation( environment: Environment, config: { @@ -31,7 +30,6 @@ commitMutation( configs?: Array, }, ); - ``` ### Arguments @@ -58,7 +56,6 @@ commitMutation( Example of a simple mutation: ```javascript - import {commitMutation, graphql} from 'react-relay'; const mutation = graphql` @@ -93,7 +90,6 @@ function markNotificationAsRead(environment, source, storyID) { }, ); } - ``` ## Optimistic Updates @@ -101,7 +97,6 @@ function markNotificationAsRead(environment, source, storyID) { To improve perceived responsiveness, you may wish to perform an "optimistic update", in which the client immediately updates to reflect the anticipated new value even before the response from the server has come back. The simplest way to do this is by providing an `optimisticResponse` and adding it to the `config` that we pass into `commitMutation`: ```javascript - const mutation = graphql` mutation MarkReadNotificationMutation( $input: MarkReadNotificationInput! @@ -130,7 +125,6 @@ commitMutation( variables, }, ); - ``` Another way to enable optimistic updates is via the `optimisticUpdater`, which can be used for more complicated update scenarios. Using `optimisticUpdater` is covered in the section [below](#using-updater-and-optimisticupdater). @@ -150,7 +144,6 @@ Given a deletedIDFieldName, Relay will remove the node(s) from the connection. #### Example ```javascript - const mutation = graphql` mutation DestroyShipMutation($input: DestroyShipInput!) { destroyShip(input: $input) { @@ -168,7 +161,6 @@ const configs = [{ type: 'NODE_DELETE', deletedIDFieldName: 'destroyedShipId', }]; - ``` ### RANGE_ADD @@ -188,7 +180,6 @@ Given a parent, information about the connection, and the name of the newly crea #### Example ```javascript - const mutation = graphql` mutation AddShipMutation($input: AddShipInput!) { addShip(input: $input) { @@ -218,7 +209,6 @@ function commit(environment, factionId, name) { }], }); } - ``` ### RANGE_DELETE @@ -240,7 +230,6 @@ from the connection but leave the associated record(s) in the store. #### Example ```javascript - const mutation = graphql` mutation RemoveTagMutation($input: RemoveTagInput!) { removeTag(input: $input) { @@ -266,7 +255,6 @@ function commit(environment, todoId, tagId) { }], }); } - ``` ## Using updater and optimisticUpdater @@ -284,7 +272,6 @@ When you provide these functions, this is roughly what happens during the mutati Here are a quick example of adding a todo item to a Todo list using this [example schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L36): ```javascript - // AddTodoMutation.js import {commitMutation, graphql} from 'react-relay'; import {ConnectionHandler} from 'relay-runtime'; @@ -371,7 +358,6 @@ function commit(environment, text, user) { }, }); } - ``` For details on how to interact with the Relay Store, please refer to our Relay Store [docs](./relay-store). diff --git a/website/versioned_docs/version-v1.7.0/Modern-NetworkLayer.md b/website/versioned_docs/version-v1.7.0/Modern-NetworkLayer.md index fcd9fd4dd5e03..daa8c71294c59 100644 --- a/website/versioned_docs/version-v1.7.0/Modern-NetworkLayer.md +++ b/website/versioned_docs/version-v1.7.0/Modern-NetworkLayer.md @@ -8,7 +8,6 @@ In order to know how to access your GraphQL server, Relay Modern requires develo Currently the easiest way to create a network layer is via a helper from the `relay-runtime` package: ```javascript - import { Environment, Network, @@ -50,7 +49,6 @@ const environment = new Environment({ }); export default environment; - ``` Note that this is a basic example to help you get started. This example could be extended with additional features such as request/response caching (enabled e.g. when `cacheConfig.force` is false) and uploading form data for mutations (the `uploadables` parameter). @@ -62,7 +60,6 @@ Relay modern makes no assumptions about what to cache and will garbage collect a You have to implement your own cache strategy. A simple solution is to use `RelayQueryResponseCache`(an in-memory cache): ```javascript - import { Environment, Network, @@ -126,7 +123,6 @@ const environment = new Environment({ }); export default environment; - ``` ## Custom open-source implementations diff --git a/website/versioned_docs/version-v1.7.0/Modern-PaginationContainer.md b/website/versioned_docs/version-v1.7.0/Modern-PaginationContainer.md index e17127d79bb52..818a870d5fe63 100644 --- a/website/versioned_docs/version-v1.7.0/Modern-PaginationContainer.md +++ b/website/versioned_docs/version-v1.7.0/Modern-PaginationContainer.md @@ -24,7 +24,6 @@ However, when [specifying connection fragments](#createpaginationcontainer) for The purpose of the `@connection` directive is to allow Relay to uniquely identify different connections under a parent type. The `@connection` directive takes 2 arguments that help identify the connection: ```graphql - @connection(key: String!, filters: [String]) ``` @@ -37,7 +36,6 @@ The purpose of the `@connection` directive is to allow Relay to uniquely identif Specifying just the `key`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and the value of `$orderBy` (given that no `filters` were provided) @@ -53,13 +51,11 @@ fragment Feed_user on User { } } } - ``` Specifying `key` and `filters`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and /only/ the value of `$searchTerm`, i.e. @@ -77,7 +73,6 @@ fragment Feed_user on User { } } } - ``` ## `createPaginationContainer` @@ -85,7 +80,6 @@ fragment Feed_user on User { `createPaginationContainer` has the following signature: ```javascript - createPaginationContainer( component: ReactComponentClass, fragmentSpec: GraphQLTaggedNode | {[string]: GraphQLTaggedNode}, @@ -113,7 +107,6 @@ type ConnectionData = { startCursor: ?string, }, }; - ``` ### Arguments @@ -137,7 +130,6 @@ type ConnectionData = { The Component resulting from `createPaginationContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -148,7 +140,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -163,7 +154,6 @@ type Props = { `hasMore` is a function available on the `relay` [prop](#available-props). This function indicates whether there are more pages to fetch from the server or not. ```javascript - hasMore: () => boolean, ``` @@ -173,7 +163,6 @@ hasMore: () => boolean, `isLoading` is a function available on the `relay` [prop](#available-props). This function indicates if a previous call to [`loadMore()`](#loadmore) is still pending. This is convenient for avoiding duplicate load calls. ```javascript - isLoading: () => boolean, ``` @@ -183,7 +172,6 @@ isLoading: () => boolean, `loadMore` is a function available on the `relay` [prop](#available-props). You can call `loadMore()` to fetch more items from the server based on the `connectionConfig` provided to the container. This will return null if there are no more items to fetch, otherwise it will fetch more items and return a Disposable that can be used to cancel the fetch. ```javascript - loadMore(pageSize: number, callback: ?(error: ?Error) => void): ?Disposable ``` @@ -198,7 +186,6 @@ loadMore(pageSize: number, callback: ?(error: ?Error) => void): ?Disposable `refetchConnection` is a function available on the `relay` [prop](#available-props). You can call `refetchConnection` to restart pagination on a connection from scratch, with optionally a completely new set of variables to pass to the pagination `query`. This is useful for example if you are paginating over a collection based on a userID and the userID changes, you'd want to start paginating over the new collection for the new user. ```javascript - refetchConnection:( totalCount: number, callback: (error: ?Error) => void, @@ -216,7 +203,6 @@ refetchConnection:( ## Pagination Example ```javascript - // Feed.js import {createPaginationContainer, graphql} from 'react-relay'; @@ -311,5 +297,4 @@ module.exports = createPaginationContainer( ` } ); - ``` diff --git a/website/versioned_docs/version-v1.7.0/Modern-PersistedQueries.md b/website/versioned_docs/version-v1.7.0/Modern-PersistedQueries.md index 74b5c3c5d13c6..aadc6710f63bb 100644 --- a/website/versioned_docs/version-v1.7.0/Modern-PersistedQueries.md +++ b/website/versioned_docs/version-v1.7.0/Modern-PersistedQueries.md @@ -16,12 +16,10 @@ The relay compiler supports persisted queries which is useful because: In your `npm` script in `package.json`, run the relay compiler using the `--persist-output` flag: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` The `--persist-ouput` flag does 2 things: @@ -30,8 +28,7 @@ The `--persist-ouput` flag does 2 things: For example without `--persist-output`, a generated `ConcreteRequest` might look like below: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -48,8 +45,7 @@ The `--persist-ouput` flag does 2 things: With `--persist-output ` this becomes: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -67,12 +63,10 @@ The `--persist-ouput` flag does 2 things: 2. It generates a JSON file at the `` you specify containing a mapping from query ids to the corresponding operation texts. -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./src/queryMaps/queryMap.json" } - ``` The example above writes the complete query map file to `./src/queryMaps/queryMap.json`. You need to ensure all the directories @@ -82,8 +76,7 @@ leading to the `queryMap.json` file exist. You'll need to modify your network layer fetch implementation to pass a documentId parameter in the POST body instead of a query parameter: -```js - +```javascript function fetchQuery(operation, variables,) { return fetch('/graphql', { method: 'POST', @@ -99,7 +92,6 @@ function fetchQuery(operation, variables,) { return response.json(); }); } - ``` ## Executing Persisted Queries on the Server @@ -115,13 +107,11 @@ the query map file in a common location accessible to both the client and the se For applications where the client and server projects are separate, one option is to have an additional npm run script to push the query map at compile time to a location accessible by your server: -```js - +```javascript "scripts": { "push-queries": "node ./pushQueries.js", "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-ouput && npm run push-queries" } - ``` Some possibilities of what you can do in `./pushQueries.js`: @@ -145,8 +135,7 @@ database technologies you use, so we'll just cover the most common and basic exa If you use `express-graphql` and have access to the query map file, you can import the `--persist-output` JSON file directly and perform the matching using the `matchQueryMiddleware` from [relay-compiler-plus](https://github.com/yusinto/relay-compiler-plus). -```js - +```javascript import Express from 'express'; import expressGraphql from 'express-graphql'; import {matchQueryMiddleware} from 'relay-compiler-plus'; @@ -157,7 +146,6 @@ const app = Express(); app.use('/graphql', matchQueryMiddleware(queryMapJson), expressGraphql({schema})); - ``` ## Using `--persist-output` and `--watch` diff --git a/website/versioned_docs/version-v1.7.0/Modern-QueryRenderer.md b/website/versioned_docs/version-v1.7.0/Modern-QueryRenderer.md index 8787283987b82..4259a7a543545 100644 --- a/website/versioned_docs/version-v1.7.0/Modern-QueryRenderer.md +++ b/website/versioned_docs/version-v1.7.0/Modern-QueryRenderer.md @@ -23,7 +23,6 @@ However, a `QueryRenderer` will not start loading its data until it is mounted, ## Example ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -55,5 +54,4 @@ class Example extends React.Component { ); } } - ``` diff --git a/website/versioned_docs/version-v1.7.0/Modern-RefetchContainer.md b/website/versioned_docs/version-v1.7.0/Modern-RefetchContainer.md index 930b460e80f54..d33fc948d775c 100644 --- a/website/versioned_docs/version-v1.7.0/Modern-RefetchContainer.md +++ b/website/versioned_docs/version-v1.7.0/Modern-RefetchContainer.md @@ -16,13 +16,11 @@ Table of Contents: `createRefetchContainer` has the following signature: ```javascript - createRefetchContainer( component: ReactComponentClass, fragmentSpec: GraphQLTaggedNode | {[string]: GraphQLTaggedNode}, refetchQuery: GraphQLTaggedNode, ): ReactComponentClass; - ``` ### Arguments @@ -40,7 +38,6 @@ createRefetchContainer( The Component resulting from `createRefetchContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -48,7 +45,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -64,7 +60,6 @@ type Props = { `refetch` has the following signature: ```javascript - type RefetchOptions = { force?: boolean, }; @@ -104,7 +99,6 @@ Returns a `Disposable` on which you could call `dispose()` to cancel the refetch In this simple example, let's assume we want to fetch the latest data for a `TodoItem` from the server: ```javascript - // TodoItem.js import {createRefetchContainer, graphql} from 'react-relay'; @@ -148,7 +142,6 @@ export default createRefetchContainer( } ` ); - ``` ### Loading more data @@ -156,7 +149,6 @@ export default createRefetchContainer( In this example we are using a Refetch Container to fetch more stories in a story feed component. ```javascript - import {createRefetchContainer, graphql} from 'react-relay'; class FeedStories extends React.Component { @@ -212,5 +204,4 @@ export default createRefetchContainer( } `, ); - ``` diff --git a/website/versioned_docs/version-v1.7.0/Modern-RelayCompat.md b/website/versioned_docs/version-v1.7.0/Modern-RelayCompat.md index 36632d3a8f1a1..f47dbd845ba3e 100644 --- a/website/versioned_docs/version-v1.7.0/Modern-RelayCompat.md +++ b/website/versioned_docs/version-v1.7.0/Modern-RelayCompat.md @@ -31,7 +31,6 @@ Relay Modern. The components using Relay Compat can be referred to by both other Relay Modern and Relay Classic components. ```javascript - const {createFragmentContainer, graphql} = require('react-relay/compat'); class TodoItem extends React.Component { @@ -47,5 +46,4 @@ module.exports = createFragmentContainer(TodoItem, graphql` isComplete } `); - ``` diff --git a/website/versioned_docs/version-v1.7.0/Modern-RelayEnvironment.md b/website/versioned_docs/version-v1.7.0/Modern-RelayEnvironment.md index b356b5deecdc5..ed75bc69d1f86 100644 --- a/website/versioned_docs/version-v1.7.0/Modern-RelayEnvironment.md +++ b/website/versioned_docs/version-v1.7.0/Modern-RelayEnvironment.md @@ -12,7 +12,6 @@ Most applications will create a single Environment instance and use it throughou To create an environment instance in Relay Modern, use the `RelayModernEnvironment` class: ```javascript - const { Environment, Network, @@ -30,7 +29,6 @@ const environment = new Environment({ network, store, }); - ``` For more details on creating a Network, see the [NetworkLayer guide](./network-layer). @@ -44,7 +42,6 @@ The example above did not configure a `handlerProvider`, which means that a defa If you wish to provide your own `handlerProvider`, you can do so: ```javascript - const { ConnectionHandler, ViewerHandler, @@ -60,5 +57,4 @@ function handlerProvider(handle) { `handlerProvider: No handler provided for ${handle}` ); } - ``` diff --git a/website/versioned_docs/version-v1.7.0/Modern-RelayStore.md b/website/versioned_docs/version-v1.7.0/Modern-RelayStore.md index 6bdeeb471b64f..4de7abfbecf1d 100644 --- a/website/versioned_docs/version-v1.7.0/Modern-RelayStore.md +++ b/website/versioned_docs/version-v1.7.0/Modern-RelayStore.md @@ -16,7 +16,6 @@ Table of Contents: The `RecordSourceSelectorProxy` is the type of the `store` that [`updater` functions](./mutations#using-updater-and-optimisticupdater) receive as an argument. The following is the `RecordSourceSelectorProxy` interface: ```javascript - interface RecordSourceSelectorProxy { create(dataID: string, typeName: string): RecordProxy; delete(dataID: string): void; @@ -25,7 +24,6 @@ interface RecordSourceSelectorProxy { getRootField(fieldName: string): ?RecordProxy; getPluralRootField(fieldName: string): ?Array; } - ``` ### `create(dataID: string, typeName: string): RecordProxy` @@ -35,9 +33,7 @@ Creates a new record in the store given a `dataID` and the `typeName` as defined #### Example ```javascript - const record = store.create(dataID, 'Todo'); - ``` ### `delete(dataID: string): void` @@ -47,9 +43,7 @@ Deletes a record from the store given its `dataID`. #### Example ```javascript - store.delete(dataID); - ``` ### `get(dataID: string): ?RecordProxy` @@ -59,9 +53,7 @@ Retrieves a record from the store given its `dataID`. Returns a [`RecordProxy`]( #### Example ```javascript - const record = store.get(dataID); - ``` ### `getRoot(): RecordProxy` @@ -73,20 +65,16 @@ Returns the [`RecordProxy`](#recordproxy) representing the root of the GraphQL d Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - // Represents root query const root = store.getRoot(); - ``` ### `getRootField(fieldName: string): ?RecordProxy` @@ -98,19 +86,15 @@ Retrieves a root field from the store given the `fieldName`, as defined by the G Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - const viewer = store.getRootField('viewer'); - ``` ### `getPluralRootField(fieldName: string): ?Array` @@ -122,19 +106,15 @@ Retrieves a root field that represents a collection from the store given the `fi Given the GraphQL document: ```graphql - nodes(first: 10) { # ... } - ``` Usage: ```javascript - const nodes = store.getPluralRootField('nodes'); - ``` ## RecordProxy @@ -142,7 +122,6 @@ const nodes = store.getPluralRootField('nodes'); The `RecordProxy` serves as an interface to mutate records: ```javascript - interface RecordProxy { copyFieldsFrom(sourceRecord: RecordProxy): void; getDataID(): string; @@ -167,7 +146,6 @@ interface RecordProxy { ): RecordProxy; setValue(value: mixed, name: string, arguments?: ?Object): RecordProxy; } - ``` ### `getDataID(): string` @@ -177,9 +155,7 @@ Returns the dataID of the current record. #### Example ```javascript - const id = record.getDataID(); - ``` ### `getType(): string` @@ -189,7 +165,6 @@ Gets the type of the current record, as defined by the GraphQL schema. #### Example ```javascript - const type = user.getType(); // User ``` @@ -203,20 +178,16 @@ Gets the value of a field in the current record given the field name. Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - const name = viewer.getValue('name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. @@ -226,20 +197,16 @@ Optionally, if the field takes arguments, you can pass a bag of `variables`. Given the GraphQL document: ```graphql - viewer { id name(arg: $arg) } - ``` Usage: ```javascript - const name = viewer.getValue('name', {arg: 'value'}); - ``` ### `getLinkedRecord(name: string, arguments?: ?Object): ?RecordProxy` @@ -251,23 +218,19 @@ Retrieves a record associated with the current record given the field name, as d Given the GraphQL document: ```graphql - rootField { viewer { id name } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -277,22 +240,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { viewer(arg: $arg) { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {arg: 'value'}); - ``` ### `getLinkedRecords(name: string, arguments?: ?Object): ?Array` @@ -304,22 +263,18 @@ Retrieves the set of records associated with the current record given the field Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const nodes = rootField.getLinkedRecords('nodes'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -329,22 +284,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { nodes(first: $count) { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {count: 10}); - ``` ### `getOrCreateLinkedRecord(name: string, typeName: string, arguments?: ?Object)` @@ -356,19 +307,16 @@ Retrieves the a record associated with the current record given the field name, Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = rootField.getOrCreateLinkedRecord('viewer', 'User'); // Will create if it doesn't exist @@ -383,28 +331,22 @@ Mutates the current record by setting a new value on the specified field. Return Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - viewer.setValue('New Name', 'name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. ```javascript - viewer.setValue('New Name', 'name', {arg: 'value'}); - ``` ### `copyFieldsFrom(sourceRecord: RecordProxy): void` @@ -414,7 +356,6 @@ Mutates the current record by copying the fields over from the passed in record #### Example ```javascript - const record = store.get(id1); const otherRecord = store.get(id2); record.copyFieldsFrom(otherRecord); // Mutates `record` @@ -430,19 +371,16 @@ Mutates the current record by setting a new linked record on the given the field Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = store.create(/* ... */)'' rootField.setLinkedRecord(newViewer, 'viewer'); // @@ -460,19 +398,16 @@ Mutates the current record by setting a new set of linked records on the given t Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newNode = store.create(/* ... */); const newNodes = [...rootField.getLinkedRecords('nodes'), newNode]; @@ -487,7 +422,6 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl `ConnectionHandler` is a utility module exposed by `relay-runtime` that aids in the manipulation of connections. `ConnectionHandler` exposes the following interface: ```javascript - interface ConnectionHandler { getConnection( record: RecordProxy, @@ -512,7 +446,6 @@ interface ConnectionHandler { ): void, deleteNode(connection: RecordProxy, nodeID: string): void } - ``` ### `getConnection(record: RecordProxy, key: string, filters?: ?Object)` @@ -522,7 +455,6 @@ Given a record and a connection key, and optionally a set of filters, `getConnec First, let's take a look at a plain connection: ```graphql - fragment FriendsFragment on User { friends(first: 10) { edges { @@ -532,26 +464,22 @@ fragment FriendsFragment on User { } } } - ``` Accessing a plain connection field like this is the same as other regular field: ```javascript - // The `friends` connection record can be accessed with: const user = store.get(userID); const friends = user && user.getLinkedRecord(user, 'friends'); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` In a [pagination container](./pagination-container), we usually annotate the actual connection field with `@connection` to tell Relay which part needs to be paginated: ```graphql - fragment FriendsFragment on User { friends(first: 10, orderby: "firstname") @connection( key: "FriendsFragment_friends", @@ -563,7 +491,6 @@ fragment FriendsFragment on User { } } } - ``` For connections like the above, `ConnectionHandler` helps us find the record: @@ -581,7 +508,6 @@ const friends = ConnectionHandler.getConnection( ); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` ### Edge creation and insertion @@ -611,7 +537,6 @@ ConnectionHandler.insertEdgeAfter(friends, edge); // No cursor provided, Insert the edge at the front: ConnectionHandler.insertEdgeBefore(friends, edge); - ``` ### `deleteNode(connection: RecordProxy, nodeID: string): void` @@ -625,5 +550,4 @@ Given a connection, deletes any edges whose id matches the given id. const user = store.get(userID); const friends = ConnectionHandler.getConnection(user, 'friends'); ConnectionHandler.deleteNode(friends, idToDelete); - ``` diff --git a/website/versioned_docs/version-v1.7.0/Modern-Subscriptions.md b/website/versioned_docs/version-v1.7.0/Modern-Subscriptions.md index 3521d610d6bc6..a104adde23e89 100644 --- a/website/versioned_docs/version-v1.7.0/Modern-Subscriptions.md +++ b/website/versioned_docs/version-v1.7.0/Modern-Subscriptions.md @@ -6,7 +6,6 @@ original_id: subscriptions Relay exposes the following APIs to create subscriptions. ```javascript - const {requestSubscription} = require('react-relay'); type Variables = {[name: string]: any}; @@ -27,7 +26,6 @@ requestSubscription( configs?: Array, }, ) => Disposable; - ``` The function returns a `Disposable` on which you could call `dispose()` to cancel the refetch. @@ -53,7 +51,6 @@ appropriate when you are only changing the properties of existing records that can be identified by their `id`: ```javascript - const { requestSubscription, graphql, @@ -87,7 +84,6 @@ requestSubscription( onError: error => console.error(error), } ); - ``` # Updating the client on each response @@ -97,7 +93,6 @@ Relay's in-memory cache when each subscription response is received. To do so, pass an `updater` function: ```javascript - const {ConnectionHandler} = require('relay-runtime'); requestSubscription( @@ -123,5 +118,4 @@ requestSubscription( }, }, ); - ``` diff --git a/website/versioned_docs/version-v1.7.0/Modern-TestingRelayComponents.md b/website/versioned_docs/version-v1.7.0/Modern-TestingRelayComponents.md index f30317b146e96..eaa443bd20147 100644 --- a/website/versioned_docs/version-v1.7.0/Modern-TestingRelayComponents.md +++ b/website/versioned_docs/version-v1.7.0/Modern-TestingRelayComponents.md @@ -64,7 +64,6 @@ With the `MockPayloadGenerator` and `@relay_test_operation`, we want to get rid Example of a simple Mock Resolver: ```javascript - { ID() { // Return mock value for a scalar filed with type ID @@ -75,13 +74,11 @@ Example of a simple Mock Resolver: return "Lorem Ipsum" } } - ``` It is possible to define more resolvers for Object types: ```javascript - { // This will be the default values for User object in the query response User() { @@ -94,7 +91,6 @@ It is possible to define more resolvers for Object types: }; }, } - ``` ### Mock Resolver Context @@ -102,7 +98,6 @@ It is possible to define more resolvers for Object types: The first argument of the MockResolver is the object that contains Mock Resolver Context. It is possible to return dynamic values from mock resolvers based on the context - for instance, name or alias of the field, a path in the selection, arguments, or parent type. ```javascript - { String(context) { if (context.name === 'zip') { @@ -116,7 +111,6 @@ The first argument of the MockResolver is the object that contains Mock Resolver } } } - ``` ### ID Generation @@ -124,14 +118,12 @@ The first argument of the MockResolver is the object that contains Mock Resolver The second argument of the Mock Resolver its a function that will generate a sequence of integers, useful to generate unique IDs in the tests: ```javascript - { // will generate strings "my-id-1", "my-id-2", etc. ID(_, generateId) { return `my-id-${generateId()}`; }, } - ``` ### `@relay_test_operation` @@ -141,7 +133,6 @@ Most of GraphQL type information for a specific field in the selection is not av Operations with the `@relay_test_operation` directive will have additional metadata that will contain GraphQL type info for fields in the operation's selection. And it will improve the quality of the generated data. You also will be able to define Mock resolvers for Scalar (not only ID and String) and Abstract types: ```javascript - { Float() { return 123.456; @@ -159,7 +150,6 @@ Operations with the `@relay_test_operation` directive will have additional metad }; } } - ``` ## Examples @@ -169,7 +159,6 @@ Operations with the `@relay_test_operation` directive will have additional metad Using `createMockEnvironment` and `MockPayloadGenerator` allows writing concise tests for components that are using Relay Containers and Renderers. Both those modules can be imported from `relay-test-utils`. ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { @@ -222,7 +211,6 @@ test('Error State', () => { renderer.root.find(item => (item.props.testID = 'errorMessage')), ).toBeDefined(); }); - ``` ### Fragment Container Tests @@ -230,7 +218,6 @@ test('Error State', () => { Essentially, in the example above, `resolveMostRecentOperation` will generate data for all child fragment containers (pagination, refetch). Usually, the Root Components container may have many child fragment components and you may want to exercise a specific Fragment Container. The solution for that would be to wrap your fragment container with the QueryRenderer that renders a Query that's spreads fragments from your fragment container. ```javascript - test('Fragment Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -261,7 +248,6 @@ test('Fragment Container', () => { expect(renderer).toMatchSnapshot(); }); - ``` ### Pagination Container Test @@ -269,7 +255,6 @@ test('Fragment Container', () => { Essentially, tests for Pagination container are not different from Fragment Container tests. We can also do more here. We can actually see how the pagination works by asserting the behavior of our components when performing pagination (load more, refetch). ```javascript - // Pagination Example test('Pagination Container', () => { const environment = createMockEnvironment(); @@ -343,7 +328,6 @@ test('Pagination Container', () => { We can use similar approach here with wrapping container with Query Renderer. And for the sake of completeness, we will add example here: ```javascript - test('Refetch Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -385,7 +369,6 @@ test('Refetch Container', () => { ); // expect(renderer).toMatchSnapshot(); }); - ``` ### Mutations @@ -393,7 +376,6 @@ test('Refetch Container', () => { Mutations itself are operations so we can test them independently (unit-test) for specific mutation, or in combination with the view from which this mutation is called. ```javascript - // Say, you have a mutation function function sendMutation(environment, onCompleted, onError, variables) commitMutation(environment, { @@ -416,7 +398,6 @@ test('it should send mutation', () => { ); expect(onCompleted).toBeCalled(); }); - ``` ### Subscription @@ -424,7 +405,6 @@ test('it should send mutation', () => { We can test subscription in a similar way we test mutations ```javascript - // Example subscribe function function subscribe(environment, onNext, onError, variables) requestSubscription(environment, { @@ -447,7 +427,6 @@ test('it should subscribe', () => { ); expect(onNext).toBeCalled(); }); - ``` ### Example with `queueOperationResolver` @@ -455,7 +434,6 @@ test('it should subscribe', () => { With `queueOpeararionResolver`, it possible to define responses for operations that will be executed on the environment ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { diff --git a/website/versioned_docs/version-v1.7.0/Modern-TypeEmission.md b/website/versioned_docs/version-v1.7.0/Modern-TypeEmission.md index c25bc737d5684..9f41810a3618b 100644 --- a/website/versioned_docs/version-v1.7.0/Modern-TypeEmission.md +++ b/website/versioned_docs/version-v1.7.0/Modern-TypeEmission.md @@ -15,7 +15,6 @@ In this example the emitted type-information would require the variables object #### Flow ```javascript - /** * export type ExampleQueryVariables = {| * +artistID: string @@ -43,7 +42,6 @@ const variables: ExampleQueryVariables = { #### TypeScript ```javascript - /** * export type ExampleQueryVariables = { * readonly artistID: string @@ -78,7 +76,6 @@ In this example the emitted type-information describes the response data availab #### Flow ```javascript - /** * export type ExampleQueryResponse = {| * +artist: ?{| @@ -109,7 +106,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * export type ExampleQueryResponse = { * readonly artist?: { @@ -145,7 +141,6 @@ Similarly, in this example the emitted type-information describes the prop data #### Flow ```javascript - /** * export type ExampleFragment_artist = {| * +name: string @@ -171,7 +166,6 @@ export const ExampleFragment = createFragmentContainer( #### TypeScript ```javascript - /** * export type ExampleFragment_artist = { * readonly name: string @@ -205,7 +199,6 @@ Consider a component that composes the above fragment container example. In this #### Flow ```javascript - /** * import type { FragmentReference } from "relay-runtime"; * declare export opaque type ExampleFragment_artist$ref: FragmentReference; @@ -249,7 +242,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * declare const _ExampleFragment_artist$ref: unique symbol; * export type ExampleFragment_artist$ref = typeof _ExampleFragment_artist$ref; @@ -314,7 +306,6 @@ $ relay-compiler --artifactDirectory ./src/__generated__ […] ["relay", { "artifactDirectory": "./src/__generated__" }] ] } - ``` It is recommended to alias this directory in your module resolution configuration such that you don’t need to specify relative paths in your source files. This is what is also done in the above examples, where artifacts are imported from a `__generated__` alias, rather than relative paths like `../../../../__generated__`. diff --git a/website/versioned_docs/version-v1.7.0/Modern-UpgradingSetVariables.md b/website/versioned_docs/version-v1.7.0/Modern-UpgradingSetVariables.md index d5b086fafce20..ff73feec04f8b 100644 --- a/website/versioned_docs/version-v1.7.0/Modern-UpgradingSetVariables.md +++ b/website/versioned_docs/version-v1.7.0/Modern-UpgradingSetVariables.md @@ -36,7 +36,6 @@ fragment on User { # ... } } - ``` This should be upgraded to use a [`PaginationContainer`](./pagination-container). @@ -61,7 +60,6 @@ fragment on User { # ... } } - ``` This can be upgraded by using a [`RefetchContainer`](./refetch-container) which allows you to specify the exact query to use to fetch the new data. @@ -86,7 +84,6 @@ fragment on FeedbackTarget { # ... } } - ``` This can be upgraded by conditionally rendering a [`QueryRenderer`](./query-renderer) which will load the data once it is rendered. The code overhead of doing this is dramatically reduced with the new API. diff --git a/website/versioned_docs/version-v1.7.0/Modern-fetchQuery.md b/website/versioned_docs/version-v1.7.0/Modern-fetchQuery.md index 939631d03832b..b4922b01b6c2b 100644 --- a/website/versioned_docs/version-v1.7.0/Modern-fetchQuery.md +++ b/website/versioned_docs/version-v1.7.0/Modern-fetchQuery.md @@ -6,7 +6,6 @@ original_id: fetch-query You can use the `fetchQuery` function to imperatively make GraphQL Requests. This is useful for cases where you want to make requests outside of React but still utilize the Relay store and network layer. ```javascript - import {fetchQuery, graphql} from 'relay-runtime'; const query = graphql` @@ -25,7 +24,6 @@ fetchQuery(environment, query, variables) .then(data => { // access the graphql response }); - ``` ## Arguments diff --git a/website/versioned_docs/version-v1.7.0/PrinciplesAndArchitecture-Compiler.md b/website/versioned_docs/version-v1.7.0/PrinciplesAndArchitecture-Compiler.md index c195491682b1f..fcd0490cb724f 100644 --- a/website/versioned_docs/version-v1.7.0/PrinciplesAndArchitecture-Compiler.md +++ b/website/versioned_docs/version-v1.7.0/PrinciplesAndArchitecture-Compiler.md @@ -74,7 +74,6 @@ foo { # type FooType foo { id } - ``` - `SkipRedundantNodeTransform`: A more advanced version of flattening, this eliminates more complex cases of field duplication such as when a field is fetched both unconditionally and conditionally, or is fetched by two different sub-fragments. For example: @@ -97,7 +96,6 @@ foo { id } } - ``` - `GenerateRequisiteFieldTransform`: This optional, Relay-specific transform inserts `id` fields for globally identifiable objects and `__typename` fields wherever the type cannot be statically determined (e.g. for unions). diff --git a/website/versioned_docs/version-v1.7.0/PrinciplesAndArchitecture-Runtime.md b/website/versioned_docs/version-v1.7.0/PrinciplesAndArchitecture-Runtime.md index 9491d290c146f..e9221631a701d 100644 --- a/website/versioned_docs/version-v1.7.0/PrinciplesAndArchitecture-Runtime.md +++ b/website/versioned_docs/version-v1.7.0/PrinciplesAndArchitecture-Runtime.md @@ -77,7 +77,6 @@ RecordSource { city: 'Seattle', } } - ``` [1] Note that GraphQL itself does not impose this constraint, and Relay Runtime may also be used for schemas that do not conform to it. For example, both systems can be used to query a single denormalized table. However, many of the features that Relay Runtime provides, such as caching and normalization, work best when the data is represented as a normalized graph with stable identities for discrete pieces of information. diff --git a/website/versioned_docs/version-v1.7.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md b/website/versioned_docs/version-v1.7.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md index a8842ae084922..9ff8a7840df90 100644 --- a/website/versioned_docs/version-v1.7.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md +++ b/website/versioned_docs/version-v1.7.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md @@ -12,7 +12,6 @@ In this article we'll explore what it means to build a GraphQL client framework Imagine we have a simple application that fetches a list of stories, and some details about each one. Here's how that might look in resource-oriented REST: ```javascript - // Fetch the list of story IDs but not their details: rest.get('/stories').then(stories => // This resolves to a list of items with linked resources: @@ -25,13 +24,11 @@ rest.get('/stories').then(stories => // `[ { id: "...", text: "..." } ]` console.log(stories); }); - ``` Note that this approach requires _n+1_ requests to the server: 1 to fetch the list, and _n_ to fetch each item. With GraphQL we can fetch the same data in a single network request to the server (without creating a custom endpoint that we'd then have to maintain): ```javascript - graphql.get(`query { stories { id, text } }`).then( stories => { // A list of story items: @@ -39,7 +36,6 @@ graphql.get(`query { stories { id, text } }`).then( console.log(stories); } ); - ``` So far we're just using GraphQL as a more efficient version of typical REST approaches. Note two important benefits in the GraphQL version: @@ -56,7 +52,6 @@ Repeatedly refetching information from the server can get quite slow. For exampl In a resource-oriented REST system, we can maintain a **response cache** based on URIs: ```javascript - var _cache = new Map(); rest.get = uri => { if (!_cache.has(uri)) { @@ -64,13 +59,11 @@ rest.get = uri => { } return _cache.get(uri); }; - ``` Response-caching can also be applied to GraphQL. A basic approach would work similarly to the REST version. The text of the query itself can be used as a cache key: ```javascript - var _cache = new Map(); graphql.get = queryText => { if (!_cache.has(queryText)) { @@ -78,7 +71,6 @@ graphql.get = queryText => { } return _cache.get(queryText); }; - ``` Now, requests for previously cached data can be answered immediately without making a network request. This is a practical approach to improving the perceived performance of an application. However, this method of caching can cause problems with data consistency. @@ -90,7 +82,6 @@ With GraphQL it is very common for the results of multiple queries to overlap. H ``` query { stories { id, text, likeCount } } - ``` and then later refetch one of the stories whose `likeCount` has since been incremented: @@ -98,7 +89,6 @@ and then later refetch one of the stories whose `likeCount` has since been incre ``` query { story(id: "123") { id, text, likeCount } } - ``` We'll now see different `likeCount`s depending on how the story is accessed. A view that uses the first query will see an outdated count, while a view using the second query will see the updated count. @@ -119,7 +109,6 @@ query { } } } - ``` And here's a possible response: @@ -134,13 +123,11 @@ query: { } } } - ``` Although the response is hierarchical, we'll cache it by flattening all the records. Here is an example of how Relay would cache this query response: ```javascript - Map { // `story(id: "1")` 1: Map { @@ -152,7 +139,6 @@ Map { name: 'Jan', }, }; - ``` This is only a simple example: in reality the cache must handle one-to-many associations and pagination (among other things). @@ -182,7 +168,6 @@ The first query was for a list of stories: ``` query { stories { id, text, likeCount } } - ``` With a normalized response cache, a record would be created for each story in the list. The `stories` field would store links to each of these records. @@ -192,7 +177,6 @@ The second query refetched the information for one of those stories: ``` query { story(id: "123") { id, text, likeCount } } - ``` When this response is normalized, Relay can detect that this result overlaps with existing data based on its `id`. Rather than create a new record, Relay will update the existing `123` record. The new `likeCount` is therefore available to _both_ queries, as well as any other query that might reference this story. @@ -215,7 +199,6 @@ query { } } } - ``` After initially fetching this story our cache might be as follows. Note that the story and comment both link to the same record as `author`: @@ -242,7 +225,6 @@ Map { author: Link(2), }, } - ``` The author of this story also commented on it — quite common. Now imagine that some other view fetches new information about the author, and her profile photo has changed to a new URI. Here's the _only_ part of our cached data that changes: @@ -256,7 +238,6 @@ Map { photo: 'http://.../photo2.jpg', }, } - ``` The value of the `photo` field has changed; and therefore the record `2` has also changed. And that's it. Nothing else in the _cache_ is affected. But clearly our _view_ needs to reflect the update: both instances of the author in the UI (as story author and comment author) need to show the new photo. @@ -273,7 +254,6 @@ ImmutableMap { }, 3: ImmutableMap // same as before } - ``` If we replace `2` with a new immutable record, we'll also get a new immutable instance of the cache object. However, records `1` and `3` are untouched. Because the data is normalized, we can't tell that `story`'s contents have changed just by looking at the `story` record alone. @@ -299,7 +279,6 @@ mutation StoryLike($storyID: String) { likeCount } } - ``` Notice that we're querying for data that _may_ have changed as a result of the mutation. An obvious question is: why can't the server just tell us what changed? The answer is: it's complicated. GraphQL abstracts over _any_ data storage layer (or an aggregation of multiple sources), and works with any programming language. Furthermore, the goal of GraphQL is to provide data in a form that is useful to product developers building a view. diff --git a/website/versioned_docs/version-v1.7.0/PrinciplesAndArchitecture-ThinkingInRelay.md b/website/versioned_docs/version-v1.7.0/PrinciplesAndArchitecture-ThinkingInRelay.md index d6f1572d5590b..4fb68372ec4b3 100644 --- a/website/versioned_docs/version-v1.7.0/PrinciplesAndArchitecture-ThinkingInRelay.md +++ b/website/versioned_docs/version-v1.7.0/PrinciplesAndArchitecture-ThinkingInRelay.md @@ -30,13 +30,11 @@ fragment Story_story on Story { photo } } - ``` And this fragment can then be used to define the Story container: ```javascript - const {createFragmentContainer, graphql} = require('react-relay'); // Plain React component. @@ -64,7 +62,6 @@ const StoryContainer = createFragmentContainer(Story, { In React, rendering a view requires two inputs: the _component_ to render, and a _root_ DOM (UI) node to render into. Rendering Relay containers is similar: we need a _container_ to render, and a _root_ in the graph from which to start our query. We also must ensure that the queries for the container are executed and may want to show a loading indicator while data is being fetched. Similar to `ReactDOM.render(component, domNode)`, Relay provides `` for this purpose. The `query` and `variables` define what data to fetch and `render` defines what to render. Here's how we might render ``: ```javascript - ReactDOM.render( { ); } } - ``` The above code is doing something very similar to our [previous example](#rendering-graphql-queries). However, we are now passing a `$userID` variable to the GraphQL query via the `variables` prop. This has a couple of important implications: @@ -228,7 +216,6 @@ Now that we know how to define and fetch queries, let's actually start building First, let's start at the bottom. Suppose that we want to render a component that simply displays a given todo item's text and completed state: ```javascript - // Todo.js import React from 'react'; @@ -258,7 +245,6 @@ export default class Todo extends React.Component { ); } } - ``` From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L112), we know that we can query this data on the `Todo` type. However, we don't want to have to send a separate query for each todo item; that would defeat the purpose of using GraphQL over a traditional REST API. We could manually query for these fields directly in our `QueryRenderer` query, but that would hurt re-usability: what if we want to query the same set of fields as part of a different query? Additionally, we wouldn't know which component needs the data we're querying, which is a problem Relay directly tries to address. @@ -266,18 +252,15 @@ From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/dat Instead, we can define a reusable [Fragment](http://graphql.org/learn/queries/#fragments), which allows us to define a set of fields on a type and reuse them within our queries wherever we need to: ```graphql - fragment TodoItemFragment on Todo { complete text } - ``` Our component can then use this fragment to declare its data dependency on the `Todo` GraphQL type: ```javascript - // Todo.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -340,7 +323,6 @@ Before proceeding, don't forget to run the Relay Compiler with `yarn relay`. Given that [Fragment Containers](./fragment-container) are just React components, we can compose them as such. We can even re-use fragment containers within other fragment containers. As an example, let's see how we would define a `TodoList` component that just renders a list of todo items, and whether all have been completed or not: ```javascript - // TodoList.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -401,7 +383,6 @@ export default createFragmentContainer( `, }, ); - ``` As with the first fragment container we defined, `TodoList` declares it's data dependencies via a fragment. However, this component additionally re-uses the fragment previously defined by the `Todo` component, and passes the appropriate data when rendering the child `Todo` components (a.k.a. fragment containers). @@ -416,7 +397,6 @@ fragment containers do not directly fetch data. Instead, containers declare a sp A `QueryRenderer` rendering these fragment containers could look like the following: ```javascript - // ViewerTodoList.js import React from 'react'; import {graphql, QueryRenderer} from 'react-relay'; @@ -457,7 +437,6 @@ export default class ViewerTodoList extends React.Component { ); } } - ``` Check out our docs for [Fragment Containers](./fragment-container) for more details, and our guides on [Refetch](./refetch-container) and [Pagination](./pagination-container) for more advanced usage of containers. @@ -469,7 +448,6 @@ Now that we know how to query for and render data, let's move on to changing our From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L35), we know that we have some mutations available to us, so let's start by writing a mutation to change the `complete` status of a given todo item (i.e. mark or unmark it as done): ```graphql - mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { changeTodoStatus(input: $input) { todo { @@ -478,7 +456,6 @@ mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { } } } - ``` This mutation allows us to query back some data as a [result of the mutation](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L18), so we're going to query for the updated `complete` status on the todo item. @@ -486,7 +463,6 @@ This mutation allows us to query back some data as a [result of the mutation](ht In order to execute this mutation in Relay, we're going to write a new mutation using Relay's `commitMutation` api: ```javascript - // ChangeTodoStatusMutation.js import {graphql, commitMutation} from 'react-relay'; @@ -520,7 +496,6 @@ function commit( } export default {commit}; - ``` Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mutation to the server and, in our case, upon receiving a response it will automatically update the local data store with the latest data from the server. This also means that upon receiving the response, Relay will ensure that any components (i.e. containers) that depend on the updated data are re-rendered. @@ -528,7 +503,6 @@ Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mut In order to actually use this mutation in our component, we could update our `Todo` component in the following way: ```javascript - // Todo.js // ... @@ -562,7 +536,6 @@ In order to make the experience better, we can configure our mutation to do an o In Relay, there's a couple of options we can pass to `commitMutation` to enable optimistic updates. Let's see what that would look like in our `ChangeTodoStatusMutation`: ```javascript - // ChangeTodoStatusMutation.js // ... @@ -597,7 +570,6 @@ function commit( } export default {commit}; - ``` In the simplest case above, we just need to pass an `optimisticResponse` option, which should refer to an object having the same shape as the mutation response payload. When we pass this option, Relay will know to immediately update our local data with the optimistic response, and then update it with the actual server response or roll it back if an error occurs. diff --git a/website/versioned_docs/version-v10.0.0/Modern-ConvertingMutations.md b/website/versioned_docs/version-v10.0.0/Modern-ConvertingMutations.md index 08ad2e998cb2d..8f4bdc1d8e0d2 100644 --- a/website/versioned_docs/version-v10.0.0/Modern-ConvertingMutations.md +++ b/website/versioned_docs/version-v10.0.0/Modern-ConvertingMutations.md @@ -12,19 +12,16 @@ FatQueries in Relay Classic mutations was a concept that was confusing for a num Example of existing fat query: ```javascript - RelayClassic.QL` fragment on MarkReadNotificationResponsePayload @relay(pattern: true) { notification } `; - ``` Example of converted mutation query: ```javascript - graphql` mutation MarkReadNotificationMutation( $input: MarkReadNotificationData! @@ -37,7 +34,6 @@ graphql` } } `; - ``` ## Migrating Configs @@ -67,7 +63,6 @@ This is no longer needed in Compatibility Mode for neither environments. Simply Take this example of a simple mutation in Relay Classic: ```javascript - class LikeStoryMutation extends RelayClassic.Mutation { getMutation() { return RelayClassic.QL`mutation {likeStory}`; @@ -106,7 +101,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { `, }; } - ``` ### Converting `getMutation()` and `getFatQuery()` @@ -114,7 +108,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { We combine these two into a regular GraphQL mutation, which list out specific fields that needs to be updated. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story(data: $input) { @@ -126,7 +119,6 @@ const mutation = graphql` } } `; - ``` ### Converting `getConfigs()` @@ -138,13 +130,11 @@ As specified above, `FIELDS_CHANGE` configs can be omitted. To convert `getVariables()`, we take the return value from the original function and wrap it in an object that contains a property that matches the variable name for the mutation. In this case, the mutation has a `input` variable that is of type `LikeStoryData`. ```javascript - const variables = { input: { storyID: args.storyID } } - ``` ### Final Result @@ -152,7 +142,6 @@ const variables = { As you can see, our resulting mutation is a lot simpler and more like regular GraphQL than the Relay Classic version we started out with. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story { @@ -178,7 +167,6 @@ function commit(environment: CompatEnvironment, args) { variables, }); } - ``` See [Mutation](./mutations) for additional options on `commitMutation` for more complex mutations. diff --git a/website/versioned_docs/version-v10.0.0/Modern-FragmentContainer.md b/website/versioned_docs/version-v10.0.0/Modern-FragmentContainer.md index 423f446cbb054..6a40bbcfb5d0a 100644 --- a/website/versioned_docs/version-v10.0.0/Modern-FragmentContainer.md +++ b/website/versioned_docs/version-v10.0.0/Modern-FragmentContainer.md @@ -17,12 +17,10 @@ Table of Contents: `createFragmentContainer` has the following signature: ```javascript - createFragmentContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, ): ReactComponentClass; - ``` ### Arguments @@ -43,7 +41,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -58,7 +55,6 @@ To start, let's build the plain React version of a hypothetical `` c Here's a basic implementation of `` that ignores styling in order to highlight the functionality: ```javascript - // TodoItem.js class TodoItem extends React.Component { render() { @@ -78,7 +74,6 @@ class TodoItem extends React.Component { ); } } - ``` ### Data Dependencies With GraphQL @@ -86,7 +81,6 @@ class TodoItem extends React.Component { In Relay, data dependencies are described using [GraphQL](https://github.com/facebook/graphql). For ``, the dependency can be expressed as follows. Note that this exactly matches the shape that the component expected for the `item` prop. ```javascript - graphql` # This fragment only applies to objects of type 'Todo'. fragment TodoItem_item on Todo { @@ -102,7 +96,6 @@ graphql` Given the plain React component and a GraphQL fragment, we can now define a Fragment Container to specify this component's data requirements. Let's look at the code first and then see what's happening: ```javascript - // TodoItem.js import {createFragmentContainer, graphql} from 'react-relay'; @@ -120,7 +113,6 @@ export default createFragmentContainer(TodoItem, { } `, }); - ``` ## Container Composition @@ -134,7 +126,6 @@ Let's explore how this works via a `` component that composes the `< View composition is _exactly_ what you're used to — Relay containers are just standard React components. Here's the `` component: ```javascript - class TodoList extends React.Component { render() { // Expects a `list` with a string `title`, as well as the information @@ -151,7 +142,6 @@ class TodoList extends React.Component { ); } } - ``` ### Composing Fragments @@ -159,7 +149,6 @@ class TodoList extends React.Component { Fragment composition works similarly — a parent container's fragment composes the fragment for each of its children. In this case, `` needs to fetch information about the `Todo`s that are required by ``. ```javascript - class TodoList extends React.Component // as above export default createFragmentContainer(TodoList, { @@ -176,7 +165,6 @@ export default createFragmentContainer(TodoList, { } `, }); - ``` Note that when composing fragments, the type of the composed fragment must match the field on the parent in which it is embedded. For example, it wouldn't make sense to embed a fragment of type `Story` into a parent's field of type `User`. Relay and GraphQL will provide helpful error messages if you get this wrong (and if they aren't helpful, let us know!). @@ -190,7 +178,6 @@ When defining a fragment, you can use the [`@argumentDefinitions`](./graphql-in- For example, let's redefine our `TodoList_list` fragment to take some arguments using `@argumentDefinitions`: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -200,7 +187,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` Any arguments defined inside `@argumentDefinitions` will be local variables available inside the fragment's scope. However, a fragment can also reference global variables that were defined in the root query. @@ -212,11 +198,9 @@ In order to pass arguments to a fragment that has `@argumentDefinitions`, you ne Following our `TodoList_list` example, we would pass arguments to the fragment like so: ```graphql - query TodoListQuery($count: Int, $userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` ## Rendering Containers diff --git a/website/versioned_docs/version-v10.0.0/Modern-GraphQLInRelay.md b/website/versioned_docs/version-v10.0.0/Modern-GraphQLInRelay.md index c4dc8f3463e53..715b119492cc7 100644 --- a/website/versioned_docs/version-v10.0.0/Modern-GraphQLInRelay.md +++ b/website/versioned_docs/version-v10.0.0/Modern-GraphQLInRelay.md @@ -14,7 +14,6 @@ Table of Contents: The `graphql` template tag provided by Relay serves as the mechanism to write queries, fragments, mutations or subscriptions in the [GraphQL](http://graphql.org/learn/) language. For example: ```javascript - import {graphql} from 'react-relay'; graphql` @@ -24,7 +23,6 @@ graphql` } } `; - ``` The result of using the `graphql` template tag is a `GraphQLTaggedNode`; a runtime representation of the GraphQL document which can be used to define [Query Renderers](./query-renderer), [Fragment Containers](./fragment-container), [Refetch Containers](./refetch-container), [Pagination Containers](./pagination-container), etc. @@ -42,11 +40,9 @@ Relay uses directives to add additional information to GraphQL documents, which `@arguments` is a directive used to pass arguments to a fragment that was defined using [`@argumentDefinitions`](#argumentdefinitions). For example: ```graphql - query TodoListQuery($userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -56,7 +52,6 @@ See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fr `@argumentDefinitions` is a directive used to specify arguments taken by a fragment. For example: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -66,7 +61,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -80,7 +74,6 @@ When using the [Pagination Container](./pagination-container), Relay expects con When defining a fragment for use with a Fragment container, you can use the `@relay(plural: true)` directive to indicate that container expects the prop for that fragment to be a list of items instead of a single item. A query or parent that spreads a `@relay(plural: true)` fragment should do so within a plural field (ie a field backed by a [GraphQL list](http://graphql.org/learn/schema/#lists-and-non-null). For example: ```javascript - // Plural fragment definition graphql` fragment TodoItems_items on TodoItem @relay(plural: true) { @@ -95,7 +88,6 @@ fragment TodoApp_app on App { ...TodoItem_items } } - ``` ### `@inline` @@ -107,7 +99,6 @@ Non-React functions can also take advantage of data masking. A fragment can be d In the example below, the function `processItemData` is called from a React component. It requires an item object with a specific set of fields. All React components that use this function should spread the `processItemData_item` fragment to ensure all of the correct item data is loaded for this function. ```javascript - import {graphql, readInlineData} from 'react-relay'; // non-React function called from React @@ -127,11 +118,9 @@ function processItemData(itemRef) { creatorName: item.creator.name }); } - ``` ```javascript - // React Component function MyComponent({item}) { function handleClick() { @@ -151,7 +140,6 @@ export default createFragmentContainer(MyComponent, { } ` }); - ``` ### `@relay(mask: Boolean)` @@ -169,7 +157,6 @@ Keep in mind that it is typically considered an **anti-pattern** to create a sin In the example below, the `user` prop will include the data for `id` and `name` fields wherever `...Component_internUser` is included, instead of Relay's normal behavior to mask those fields: ```javascript - graphql` fragment Component_internUser on InternUser @relay(mask: false) { id @@ -197,7 +184,6 @@ export default createFragmentContainer( } `, ); - ``` ## Relay Compiler @@ -207,7 +193,6 @@ Relay uses the Relay Compiler to convert [`graphql`](#graphql) literals into gen A query like the following: ```javascript - graphql` fragment MyComponent on Type { field @@ -228,12 +213,10 @@ Relay Compiler supports the use of **persisted queries**, in which each version Persisted queries can be enabled by instructing Relay Compiler to emit metadata about each query, mutation, and subscription into a JSON file. The generated file will contain a mapping of query identifiers to query text, which you can then save to your server. To enable persisted queries, use the `--persist-output` flag to the compiler: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` Relay Compiler will then create the id => query text mapping in the path you specify. You can then use this complete @@ -250,7 +233,6 @@ See our relay-compiler section in our [Installation and Setup guide](./installat To use the Relay Compiler, you need either a .graphql or .json GraphQL schema file, describing your GraphQL server's API. Typically these files are local representations of a server source of truth and are not edited directly. For example, we might have a `schema.graphql` like: ```graphql - schema { query: Root } @@ -268,7 +250,6 @@ type WordDefinition { text: String image: String } - ``` ### Source files @@ -284,7 +265,6 @@ For example, given the two files: - `src/Components/DictionaryComponent.js` ```javascript - const DictionaryWordFragment = graphql` fragment DictionaryComponent_word on Word { id @@ -306,7 +286,6 @@ For example, given the two files: - `src/Queries/DictionaryQuery.js` ```javascript - const DictionaryQuery = graphql` query DictionaryQuery { dictionary { @@ -330,9 +309,7 @@ Typically you will not need to import your generated definitions. The [Relay Bab However the Relay Compiler also automatically generates [Flow](https://flow.org) types as [type comments](https://flow.org/en/docs/types/comments/). For example, you can import the generated Flow types like so: ```javascript - import type {DictionaryComponent_word} from './__generated__/DictionaryComponent_word.graphql'; - ``` ### Client schema extensions @@ -342,7 +319,6 @@ The Relay Compiler fully supports client-side schema extensions, which allows yo For example, assuming the server schema `./schema.graphql`: ```graphql - schema { query: Root } @@ -350,28 +326,23 @@ schema { type Root { title: String! } - ``` We can create a `./src/clientSchema.graphql` and define a new type called `Setting`: ```graphql - type Setting { name: String! active: Boolean! } - ``` We can then extend existing server types in the client schema `./src/clientSchema.graphql` with our new `Setting` type, like so: ```graphql - extend type Root { settings: [Setting] } - ``` Any fields specified in the client schema, can be fetched from the [Relay Store](./relay-store), by selecting it in a query or fragment. diff --git a/website/versioned_docs/version-v10.0.0/Modern-LocalStateManagement.md b/website/versioned_docs/version-v10.0.0/Modern-LocalStateManagement.md index da71a0dd33246..3ecbf6801f91c 100644 --- a/website/versioned_docs/version-v10.0.0/Modern-LocalStateManagement.md +++ b/website/versioned_docs/version-v10.0.0/Modern-LocalStateManagement.md @@ -24,23 +24,19 @@ It can even be used to extend an existing server schema. For example, we can create a new type called `Note`: ```graphql - type Note { id: ID! title: String body: String } - ``` And then extend the server schema type `User`, with a list of `Note`, called `notes`. ```graphql - extend type User { notes: [Note] } - ``` ## Querying local state @@ -51,7 +47,6 @@ The field can be from the server schema, or it can be schema agnostic, like an i Here, we use a [QueryRenderer](./query-renderer) to get the current `User` via the `viewer` field, along with their id, name and the local list of notes. ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -97,7 +92,6 @@ const Example = (props) => { /> ); } - ``` ## Mutating local state @@ -111,7 +105,6 @@ To build upon the previous example, let's try creating, updating and deleting a ### Create ```javascript - import {commitLocalUpdate} from 'react-relay'; let tempID = 0; @@ -131,7 +124,6 @@ function createUserNote() { user.setLinkedRecords([...userNoteRecords, newNoteRecord], 'notes'); }); } - ``` Note that since this record will be rendered by the `ExampleQuery` in our `QueryRenderer`, the QueryRenderer will automatically retain this data so it isn't garbage collected. @@ -139,7 +131,6 @@ Note that since this record will be rendered by the `ExampleQuery` in our `Query If no component is rendering the local data and you want to manually retain it, you can do so by calling `environment.retain()`: ```javascript - import {createOperationDescriptor, getRequest} from 'relay-runtime'; // Create a query that references that record @@ -166,13 +157,11 @@ const disposable = environment.retain(operation); // Whenever you don't need that data anymore and it's okay for Relay to garbage collect it, // you can dispose of the retain disposable.dispose(); - ``` ### Update ```javascript - import {commitLocalUpdate} from 'react-relay'; function updateUserNote(dataID, body, title) { @@ -183,13 +172,11 @@ function updateUserNote(dataID, body, title) { note.setValue(title, 'title') }); } - ``` ### Delete ```javascript - import {commitLocalUpdate} from 'react-relay'; function deleteUserNote(dataID) { @@ -207,7 +194,6 @@ function deleteUserNote(dataID) { user.setLinkedRecords(newUserNoteRecords, 'notes'); }); } - ``` ## Initial local state @@ -216,7 +202,6 @@ All new client-side schema fields default to `undefined` value. Often however, y You can use an updater function via `commitLocalUpdate` to prime local state. ```javascript - import {commitLocalUpdate} from 'react-relay'; commitLocalUpdate(environment, store => { @@ -225,5 +210,4 @@ commitLocalUpdate(environment, store => { // initialize user notes to an empty array. user.setLinkedRecords([], 'notes'); }); - ``` diff --git a/website/versioned_docs/version-v10.0.0/Modern-MigrationSetup.md b/website/versioned_docs/version-v10.0.0/Modern-MigrationSetup.md index 66f1145357e25..a89c0e178e0e5 100644 --- a/website/versioned_docs/version-v10.0.0/Modern-MigrationSetup.md +++ b/website/versioned_docs/version-v10.0.0/Modern-MigrationSetup.md @@ -13,13 +13,11 @@ With some additional configuration, the `"relay"` babel plugin can also translat Relay Classic `Relay.QL` literals. Most importantly, include a reference to your GraphQL Schema as either a json file or graphql schema file. ```javascript - { "plugins": [ ["relay", {"schema": "path/schema.graphql"}] ] } - ``` ## Set up babel-plugin-relay for "[compatibility mode](./relay-compat)" @@ -29,13 +27,11 @@ literals can be translated to be usable by _both_ runtimes if configured to use compatibility mode: ```javascript - { "plugins": [ ["relay", {"compat": true, "schema": "path/schema.graphql"}] ] } - ``` ## Additional Options @@ -47,7 +43,6 @@ thrown at runtime. When compiling code for production deployment, the plugin can be configured to immediately throw upon encountering a validation problem. The plugin can be further customized for different environments with the following options: ```javascript - { "plugins": [ ["relay", { @@ -56,5 +51,4 @@ When compiling code for production deployment, the plugin can be configured to i }] ] } - ``` diff --git a/website/versioned_docs/version-v10.0.0/Modern-Mutations.md b/website/versioned_docs/version-v10.0.0/Modern-Mutations.md index 4efaf42b17d4b..b7d9a063e731d 100644 --- a/website/versioned_docs/version-v10.0.0/Modern-Mutations.md +++ b/website/versioned_docs/version-v10.0.0/Modern-Mutations.md @@ -17,7 +17,6 @@ Table of Contents: Use `commitMutation` to create and execute mutations. `commitMutation` has the following signature: ```javascript - commitMutation( environment: Environment, config: { @@ -32,7 +31,6 @@ commitMutation( cacheConfig?: CacheConfig, }, ); - ``` ### Arguments @@ -60,7 +58,6 @@ commitMutation( Example of a simple mutation: ```javascript - import {commitMutation, graphql} from 'react-relay'; const mutation = graphql` @@ -92,7 +89,6 @@ function markNotificationAsRead(environment, storyID) { }, ); } - ``` ## Optimistic Updates @@ -100,7 +96,6 @@ function markNotificationAsRead(environment, storyID) { To improve perceived responsiveness, you may wish to perform an "optimistic update", in which the client immediately updates to reflect the anticipated new value even before the response from the server has come back. The simplest way to do this is by providing an `optimisticResponse` and adding it to the `config` that we pass into `commitMutation`: ```javascript - const mutation = graphql` mutation MarkReadNotificationMutation( $storyID: ID! @@ -129,7 +124,6 @@ commitMutation( variables, }, ); - ``` Another way to enable optimistic updates is via the `optimisticUpdater`, which can be used for more complicated update scenarios. Using `optimisticUpdater` is covered in the section [below](#using-updater-and-optimisticupdater). @@ -151,7 +145,6 @@ Given a deletedIDFieldName, Relay will remove the node(s) from the store. #### Example ```javascript - const mutation = graphql` mutation DestroyShipMutation($target: ID!) { destroyShip(target: $target) { @@ -169,7 +162,6 @@ const configs = [{ type: 'NODE_DELETE', deletedIDFieldName: 'destroyedShipId', }]; - ``` ### RANGE_ADD @@ -189,7 +181,6 @@ Given a parent, information about the connection, and the name of the newly crea #### Example ```javascript - const mutation = graphql` mutation AddShipMutation($factionID: ID!, $name: String!) { addShip(factionID: $factionID, name: $name) { @@ -220,7 +211,6 @@ function commit(environment, factionID, name) { }], }); } - ``` ### RANGE_DELETE @@ -242,7 +232,6 @@ from the connection but leave the associated record(s) in the store. #### Example ```javascript - const mutation = graphql` mutation RemoveTagMutation($todoID: ID!, $tagID: ID!) { removeTag(todo: $todoID, tag: $tagID) { @@ -269,7 +258,6 @@ function commit(environment, todoID, tagID) { }], }); } - ``` ## Using updater and optimisticUpdater @@ -287,7 +275,6 @@ When you provide these functions, this is roughly what happens during the mutati Here are a quick example of adding a todo item to a Todo list using this [example schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L36): ```javascript - // AddTodoMutation.js import {commitMutation, graphql} from 'react-relay'; import {ConnectionHandler} from 'relay-runtime'; @@ -371,7 +358,6 @@ function commit(environment, text, user) { }, }); } - ``` For details on how to interact with the Relay Store, please refer to our Relay Store [docs](./relay-store). diff --git a/website/versioned_docs/version-v10.0.0/Modern-NetworkLayer.md b/website/versioned_docs/version-v10.0.0/Modern-NetworkLayer.md index 9dddd36d6c235..c9e069b812b01 100644 --- a/website/versioned_docs/version-v10.0.0/Modern-NetworkLayer.md +++ b/website/versioned_docs/version-v10.0.0/Modern-NetworkLayer.md @@ -8,7 +8,6 @@ In order to know how to access your GraphQL server, Relay Modern requires develo Currently the easiest way to create a network layer is via a helper from the `relay-runtime` package: ```javascript - import { Environment, Network, @@ -50,7 +49,6 @@ const environment = new Environment({ }); export default environment; - ``` Note that this is a basic example to help you get started. This example could be extended with additional features such as request/response caching (enabled e.g. when `cacheConfig.force` is false) and uploading form data for mutations (the `uploadables` parameter). @@ -62,7 +60,6 @@ Relay modern makes no assumptions about what to cache and will garbage collect a You have to implement your own cache strategy. A simple solution is to use `QueryResponseCache` (an in-memory cache): ```javascript - import { Environment, Network, @@ -126,7 +123,6 @@ const environment = new Environment({ }); export default environment; - ``` ## Custom open-source implementations diff --git a/website/versioned_docs/version-v10.0.0/Modern-PaginationContainer.md b/website/versioned_docs/version-v10.0.0/Modern-PaginationContainer.md index 6ac3aac8cfb8e..57980d553af9b 100644 --- a/website/versioned_docs/version-v10.0.0/Modern-PaginationContainer.md +++ b/website/versioned_docs/version-v10.0.0/Modern-PaginationContainer.md @@ -24,7 +24,6 @@ However, when [specifying connection fragments](#createpaginationcontainer) for The purpose of the `@connection` directive is to allow Relay to uniquely identify different connections under a parent type. The `@connection` directive takes 2 arguments that help identify the connection: ```graphql - @connection(key: String!, filters: [String]) ``` @@ -37,7 +36,6 @@ The purpose of the `@connection` directive is to allow Relay to uniquely identif Specifying just the `key`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and the value of `$orderBy` (given that no `filters` were provided) @@ -53,13 +51,11 @@ fragment Feed_user on User { } } } - ``` Specifying `key` and `filters`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and /only/ the value of `$searchTerm`, i.e. @@ -77,7 +73,6 @@ fragment Feed_user on User { } } } - ``` ## `createPaginationContainer` @@ -85,7 +80,6 @@ fragment Feed_user on User { `createPaginationContainer` has the following signature: ```javascript - createPaginationContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, @@ -113,7 +107,6 @@ type ConnectionData = { startCursor: ?string, }, }; - ``` ### Arguments @@ -134,7 +127,6 @@ type ConnectionData = { The Component resulting from `createPaginationContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -145,7 +137,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -160,7 +151,6 @@ type Props = { `hasMore` is a function available on the `relay` [prop](#available-props). This function indicates whether there are more pages to fetch from the server or not. ```javascript - hasMore: () => boolean, ``` @@ -170,7 +160,6 @@ hasMore: () => boolean, `isLoading` is a function available on the `relay` [prop](#available-props). This function indicates if a previous call to [`loadMore()`](#loadmore) is still pending. This is convenient for avoiding duplicate load calls. ```javascript - isLoading: () => boolean, ``` @@ -180,7 +169,6 @@ isLoading: () => boolean, `loadMore` is a function available on the `relay` [prop](#available-props). You can call `loadMore()` to fetch more items from the server based on the `connectionConfig` provided to the container. This will return null if there are no more items to fetch, otherwise it will fetch more items and return a Disposable that can be used to cancel the fetch. ```javascript - loadMore( pageSize: number, callback: ?(error: ?Error) => void, @@ -201,7 +189,6 @@ loadMore( `refetchConnection` is a function available on the `relay` [prop](#available-props). You can call `refetchConnection` to restart pagination on a connection from scratch, with optionally a completely new set of variables to pass to the pagination `query`. This is useful for example if you are paginating over a collection based on a userID and the userID changes, you'd want to start paginating over the new collection for the new user. ```javascript - refetchConnection:( totalCount: number, callback: (error: ?Error) => void, @@ -219,7 +206,6 @@ refetchConnection:( ## Pagination Example ```javascript - // Feed.js import {createPaginationContainer, graphql} from 'react-relay'; @@ -314,5 +300,4 @@ module.exports = createPaginationContainer( ` } ); - ``` diff --git a/website/versioned_docs/version-v10.0.0/Modern-PersistedQueries.md b/website/versioned_docs/version-v10.0.0/Modern-PersistedQueries.md index 137cc2e23220c..ec03b69ba09c3 100644 --- a/website/versioned_docs/version-v10.0.0/Modern-PersistedQueries.md +++ b/website/versioned_docs/version-v10.0.0/Modern-PersistedQueries.md @@ -17,12 +17,10 @@ The relay compiler supports persisted queries which is useful because: In your `npm` script in `package.json`, run the relay compiler using the `--persist-output` flag: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` The `--persist-ouput` flag does 3 things: @@ -31,8 +29,7 @@ The `--persist-ouput` flag does 3 things: For example without `--persist-output`, a generated `ConcreteRequest` might look like below: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -49,8 +46,7 @@ The `--persist-ouput` flag does 3 things: With `--persist-output ` this becomes: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -68,12 +64,10 @@ The `--persist-ouput` flag does 3 things: 2. It generates a JSON file at the `` you specify containing a mapping from query ids to the corresponding operation texts. -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./src/queryMaps/queryMap.json" } - ``` The example above writes the complete query map file to `./src/queryMaps/queryMap.json`. You need to ensure all the directories @@ -83,8 +77,7 @@ leading to the `queryMap.json` file exist. You'll need to modify your network layer fetch implementation to pass a documentId parameter in the POST body instead of a query parameter: -```js - +```javascript function fetchQuery(operation, variables,) { return fetch('/graphql', { method: 'POST', @@ -100,7 +93,6 @@ function fetchQuery(operation, variables,) { return response.json(); }); } - ``` ## Executing Persisted Queries on the Server @@ -116,13 +108,11 @@ the query map file in a common location accessible to both the client and the se For applications where the client and server projects are separate, one option is to have an additional npm run script to push the query map at compile time to a location accessible by your server: -```js - +```javascript "scripts": { "push-queries": "node ./pushQueries.js", "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-ouput && npm run push-queries" } - ``` Some possibilities of what you can do in `./pushQueries.js`: @@ -146,8 +136,7 @@ database technologies you use, so we'll just cover the most common and basic exa If you use `express-graphql` and have access to the query map file, you can import the `--persist-output` JSON file directly and perform the matching using the `matchQueryMiddleware` from [relay-compiler-plus](https://github.com/yusinto/relay-compiler-plus). -```js - +```javascript import Express from 'express'; import expressGraphql from 'express-graphql'; import {matchQueryMiddleware} from 'relay-compiler-plus'; @@ -158,7 +147,6 @@ const app = Express(); app.use('/graphql', matchQueryMiddleware(queryMapJson), expressGraphql({schema})); - ``` ## Using `--persist-output` and `--watch` diff --git a/website/versioned_docs/version-v10.0.0/Modern-QueryRenderer.md b/website/versioned_docs/version-v10.0.0/Modern-QueryRenderer.md index cf6c37f3d9a4d..b621ef9986bf1 100644 --- a/website/versioned_docs/version-v10.0.0/Modern-QueryRenderer.md +++ b/website/versioned_docs/version-v10.0.0/Modern-QueryRenderer.md @@ -24,7 +24,6 @@ However, a `QueryRenderer` will not start loading its data until it is mounted, ## Example ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -56,5 +55,4 @@ const Example = (props) => { /> ); } - ``` diff --git a/website/versioned_docs/version-v10.0.0/Modern-RefetchContainer.md b/website/versioned_docs/version-v10.0.0/Modern-RefetchContainer.md index 7ce0d14e45417..51c2c44db8941 100644 --- a/website/versioned_docs/version-v10.0.0/Modern-RefetchContainer.md +++ b/website/versioned_docs/version-v10.0.0/Modern-RefetchContainer.md @@ -16,13 +16,11 @@ Table of Contents: `createRefetchContainer` has the following signature: ```javascript - createRefetchContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, refetchQuery: GraphQLTaggedNode, ): ReactComponentClass; - ``` ### Arguments @@ -37,7 +35,6 @@ createRefetchContainer( The Component resulting from `createRefetchContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -45,7 +42,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -61,7 +57,6 @@ type Props = { `refetch` has the following signature: ```javascript - type RefetchOptions = { force?: boolean, }; @@ -102,7 +97,6 @@ Returns a `Disposable` on which you could call `dispose()` to cancel the refetch In this simple example, let's assume we want to fetch the latest data for a `TodoItem` from the server: ```javascript - // TodoItem.js import {createRefetchContainer, graphql} from 'react-relay'; @@ -148,7 +142,6 @@ export default createRefetchContainer( } ` ); - ``` ### Loading more data @@ -156,7 +149,6 @@ export default createRefetchContainer( In this example we are using a Refetch Container to fetch more stories in a story feed component. ```javascript - import {createRefetchContainer, graphql} from 'react-relay'; class FeedStories extends React.Component { @@ -212,5 +204,4 @@ export default createRefetchContainer( } `, ); - ``` diff --git a/website/versioned_docs/version-v10.0.0/Modern-RelayCompat.md b/website/versioned_docs/version-v10.0.0/Modern-RelayCompat.md index 36632d3a8f1a1..f47dbd845ba3e 100644 --- a/website/versioned_docs/version-v10.0.0/Modern-RelayCompat.md +++ b/website/versioned_docs/version-v10.0.0/Modern-RelayCompat.md @@ -31,7 +31,6 @@ Relay Modern. The components using Relay Compat can be referred to by both other Relay Modern and Relay Classic components. ```javascript - const {createFragmentContainer, graphql} = require('react-relay/compat'); class TodoItem extends React.Component { @@ -47,5 +46,4 @@ module.exports = createFragmentContainer(TodoItem, graphql` isComplete } `); - ``` diff --git a/website/versioned_docs/version-v10.0.0/Modern-RelayEnvironment.md b/website/versioned_docs/version-v10.0.0/Modern-RelayEnvironment.md index 27d90b2fc4fe1..99e728bce740d 100644 --- a/website/versioned_docs/version-v10.0.0/Modern-RelayEnvironment.md +++ b/website/versioned_docs/version-v10.0.0/Modern-RelayEnvironment.md @@ -12,7 +12,6 @@ Most applications will create a single Environment instance and use it throughou To create an environment instance in Relay Modern, use the `RelayModernEnvironment` class: ```javascript - const { Environment, Network, @@ -30,7 +29,6 @@ const environment = new Environment({ network, store, }); - ``` For more details on creating a Network, see the [NetworkLayer guide](./network-layer). @@ -44,7 +42,6 @@ The example above did not configure a `handlerProvider`, which means that a defa If you wish to provide your own `handlerProvider`, you can do so: ```javascript - const { ConnectionHandler, } = require('relay-runtime'); @@ -58,5 +55,4 @@ function handlerProvider(handle) { `handlerProvider: No handler provided for ${handle}` ); } - ``` diff --git a/website/versioned_docs/version-v10.0.0/Modern-RelayStore.md b/website/versioned_docs/version-v10.0.0/Modern-RelayStore.md index 6bb2e3744d55b..38f88c7f69edb 100644 --- a/website/versioned_docs/version-v10.0.0/Modern-RelayStore.md +++ b/website/versioned_docs/version-v10.0.0/Modern-RelayStore.md @@ -16,7 +16,6 @@ Table of Contents: The `RecordSourceSelectorProxy` is the type of the `store` that [`updater` functions](./mutations#using-updater-and-optimisticupdater) receive as an argument. The following is the `RecordSourceSelectorProxy` interface: ```javascript - interface RecordSourceSelectorProxy { create(dataID: string, typeName: string): RecordProxy; delete(dataID: string): void; @@ -26,7 +25,6 @@ interface RecordSourceSelectorProxy { getPluralRootField(fieldName: string): ?Array; invalidateStore(): void; } - ``` ### `create(dataID: string, typeName: string): RecordProxy` @@ -36,9 +34,7 @@ Creates a new record in the store given a `dataID` and the `typeName` as defined #### Example ```javascript - const record = store.create(dataID, 'Todo'); - ``` ### `delete(dataID: string): void` @@ -48,9 +44,7 @@ Deletes a record from the store given its `dataID`. #### Example ```javascript - store.delete(dataID); - ``` ### `get(dataID: string): ?RecordProxy` @@ -60,9 +54,7 @@ Retrieves a record from the store given its `dataID`. Returns a [`RecordProxy`]( #### Example ```javascript - const record = store.get(dataID); - ``` ### `getRoot(): RecordProxy` @@ -74,20 +66,16 @@ Returns the [`RecordProxy`](#recordproxy) representing the root of the GraphQL d Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - // Represents root query const root = store.getRoot(); - ``` ### `getRootField(fieldName: string): ?RecordProxy` @@ -99,19 +87,15 @@ Retrieves a root field from the store given the `fieldName`, as defined by the G Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - const viewer = store.getRootField('viewer'); - ``` ### `getPluralRootField(fieldName: string): ?Array` @@ -123,19 +107,15 @@ Retrieves a root field that represents a collection from the store given the `fi Given the GraphQL document: ```graphql - nodes(first: 10) { # ... } - ``` Usage: ```javascript - const nodes = store.getPluralRootField('nodes'); - ``` ### `invalidateStore(): void` @@ -145,15 +125,12 @@ Globally invalidates the Relay store. This will cause any data that was written #### Example ```javascript - store.invalidateStore(); - ``` After global invalidation, any query that is checked before refetching it will be considered stale: ```javascript - environment.check(query) === 'stale' ``` @@ -163,7 +140,6 @@ environment.check(query) === 'stale' The `RecordProxy` serves as an interface to mutate records: ```javascript - interface RecordProxy { copyFieldsFrom(sourceRecord: RecordProxy): void; getDataID(): string; @@ -189,7 +165,6 @@ interface RecordProxy { setValue(value: mixed, name: string, arguments?: ?Object): RecordProxy; invalidateRecord(): void; } - ``` ### `getDataID(): string` @@ -199,9 +174,7 @@ Returns the dataID of the current record. #### Example ```javascript - const id = record.getDataID(); - ``` ### `getType(): string` @@ -211,7 +184,6 @@ Gets the type of the current record, as defined by the GraphQL schema. #### Example ```javascript - const type = user.getType(); // User ``` @@ -225,20 +197,16 @@ Gets the value of a field in the current record given the field name. Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - const name = viewer.getValue('name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. @@ -248,20 +216,16 @@ Optionally, if the field takes arguments, you can pass a bag of `variables`. Given the GraphQL document: ```graphql - viewer { id name(arg: $arg) } - ``` Usage: ```javascript - const name = viewer.getValue('name', {arg: 'value'}); - ``` ### `getLinkedRecord(name: string, arguments?: ?Object): ?RecordProxy` @@ -273,23 +237,19 @@ Retrieves a record associated with the current record given the field name, as d Given the GraphQL document: ```graphql - rootField { viewer { id name } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -299,22 +259,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { viewer(arg: $arg) { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {arg: 'value'}); - ``` ### `getLinkedRecords(name: string, arguments?: ?Object): ?Array` @@ -326,22 +282,18 @@ Retrieves the set of records associated with the current record given the field Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const nodes = rootField.getLinkedRecords('nodes'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -351,22 +303,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { nodes(first: $count) { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {count: 10}); - ``` ### `getOrCreateLinkedRecord(name: string, typeName: string, arguments?: ?Object)` @@ -378,19 +326,16 @@ Retrieves the a record associated with the current record given the field name, Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = rootField.getOrCreateLinkedRecord('viewer', 'User'); // Will create if it doesn't exist @@ -405,28 +350,22 @@ Mutates the current record by setting a new value on the specified field. Return Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - viewer.setValue('New Name', 'name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. ```javascript - viewer.setValue('New Name', 'name', {arg: 'value'}); - ``` ### `copyFieldsFrom(sourceRecord: RecordProxy): void` @@ -436,7 +375,6 @@ Mutates the current record by copying the fields over from the passed in record #### Example ```javascript - const record = store.get(id1); const otherRecord = store.get(id2); record.copyFieldsFrom(otherRecord); // Mutates `record` @@ -452,19 +390,16 @@ Mutates the current record by setting a new linked record on the given the field Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = store.create(/* ... */)'' rootField.setLinkedRecord(newViewer, 'viewer'); // @@ -482,19 +417,16 @@ Mutates the current record by setting a new set of linked records on the given t Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newNode = store.create(/* ... */); const newNodes = [...rootField.getLinkedRecords('nodes'), newNode]; @@ -511,16 +443,13 @@ Invalidates the record. This will cause any query that references this record to #### Example ```javascript - const record = store.get('4'); record.invalidateRecord(); - ``` After invalidating a record, any query that references the invalidated record and that is checked before refetching it will be considered stale: ```javascript - environment.check(query) === 'stale' ``` @@ -530,7 +459,6 @@ environment.check(query) === 'stale' `ConnectionHandler` is a utility module exposed by `relay-runtime` that aids in the manipulation of connections. `ConnectionHandler` exposes the following interface: ```javascript - interface ConnectionHandler { getConnection( record: RecordProxy, @@ -555,7 +483,6 @@ interface ConnectionHandler { ): void, deleteNode(connection: RecordProxy, nodeID: string): void } - ``` ### `getConnection(record: RecordProxy, key: string, filters?: ?Object)` @@ -565,7 +492,6 @@ Given a record and a connection key, and optionally a set of filters, `getConnec First, let's take a look at a plain connection: ```graphql - fragment FriendsFragment on User { friends(first: 10) { edges { @@ -575,26 +501,22 @@ fragment FriendsFragment on User { } } } - ``` Accessing a plain connection field like this is the same as other regular field: ```javascript - // The `friends` connection record can be accessed with: const user = store.get(userID); const friends = user && user.getLinkedRecord('friends'); // Access fields on the connection: const edges = friends && friends.getLinkedRecords('edges'); - ``` In a [pagination container](./pagination-container), we usually annotate the actual connection field with `@connection` to tell Relay which part needs to be paginated: ```graphql - fragment FriendsFragment on User { friends(first: 10, orderby: "firstname") @connection( key: "FriendsFragment_friends", @@ -606,7 +528,6 @@ fragment FriendsFragment on User { } } } - ``` For connections like the above, `ConnectionHandler` helps us find the record: @@ -624,7 +545,6 @@ const friends = ConnectionHandler.getConnection( ); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` ### Edge creation and insertion @@ -654,7 +574,6 @@ ConnectionHandler.insertEdgeAfter(friends, edge); // No cursor provided, Insert the edge at the front: ConnectionHandler.insertEdgeBefore(friends, edge); - ``` ### `deleteNode(connection: RecordProxy, nodeID: string): void` @@ -668,5 +587,4 @@ Given a connection, deletes any edges whose id matches the given id. const user = store.get(userID); const friends = ConnectionHandler.getConnection(user, 'friends'); ConnectionHandler.deleteNode(friends, idToDelete); - ``` diff --git a/website/versioned_docs/version-v10.0.0/Modern-Subscriptions.md b/website/versioned_docs/version-v10.0.0/Modern-Subscriptions.md index 1b37765384e94..556c415e5529c 100644 --- a/website/versioned_docs/version-v10.0.0/Modern-Subscriptions.md +++ b/website/versioned_docs/version-v10.0.0/Modern-Subscriptions.md @@ -6,7 +6,6 @@ original_id: subscriptions Relay exposes the following APIs to create subscriptions. ```javascript - const {requestSubscription} = require('react-relay'); type Variables = {[name: string]: any}; @@ -28,7 +27,6 @@ requestSubscription( cacheConfig?: CacheConfig, }, ) => Disposable; - ``` The function returns a `Disposable` on which you could call `dispose()` to cancel the refetch. @@ -55,7 +53,6 @@ appropriate when you are only changing the properties of existing records that can be identified by their `id`: ```javascript - const { requestSubscription, graphql, @@ -89,7 +86,6 @@ requestSubscription( onError: error => console.error(error), } ); - ``` # Updating the client on each response @@ -99,7 +95,6 @@ Relay's in-memory cache when each subscription response is received. To do so, pass an `updater` function: ```javascript - const {ConnectionHandler} = require('relay-runtime'); requestSubscription( @@ -125,5 +120,4 @@ requestSubscription( }, }, ); - ``` diff --git a/website/versioned_docs/version-v10.0.0/Modern-TestingRelayComponents.md b/website/versioned_docs/version-v10.0.0/Modern-TestingRelayComponents.md index 919e20bc4f044..160536d908e7b 100644 --- a/website/versioned_docs/version-v10.0.0/Modern-TestingRelayComponents.md +++ b/website/versioned_docs/version-v10.0.0/Modern-TestingRelayComponents.md @@ -65,7 +65,6 @@ MockPayloadGenerator may drastically simplify the process of creating and mainta Example of a simple Mock Resolver: ```javascript - { ID() { // Return mock value for a scalar filed with type ID @@ -76,13 +75,11 @@ Example of a simple Mock Resolver: return "Lorem Ipsum" } } - ``` It is possible to define more resolvers for Object types ```javascript - { // This will be the default values for User object in the query response User() { @@ -95,7 +92,6 @@ It is possible to define more resolvers for Object types }; }, } - ``` ### Mock Resolver Context @@ -103,7 +99,6 @@ It is possible to define more resolvers for Object types The first argument of the MockResolver is the object that contains Mock Resolver Context. It is possible to return dynamic values from mock resolvers based on the context - for instance, name or alias of the field, a path in the selection, arguments, or parent type. ```javascript - { String(context) { if (context.name === 'zip') { @@ -117,7 +112,6 @@ The first argument of the MockResolver is the object that contains Mock Resolver } } } - ``` ### ID Generation @@ -125,14 +119,12 @@ The first argument of the MockResolver is the object that contains Mock Resolver The second argument of the Mock Resolver its a function that will generate a sequence of integers, useful to generate unique ids in the tests ```javascript - { // will generate strings "my-id-1", "my-id-2", etc. ID(_, generateId) { return `my-id-${generateId()}`; }, } - ``` ### @relay_test_operation @@ -142,7 +134,6 @@ Most of GraphQL type information for a specific field in the selection is not av Operation with the @relay_test_operation directive will have additional metadata that will contain GraphQL type info for fields in the operation's selection. And it will improve the quality of the generated data. You also will be able to define Mock resolvers for Scalar (not only ID and String) and Abstract types: ```javascript - { Float() { return 123.456; @@ -160,7 +151,6 @@ Operation with the @relay_test_operation directive will have additional metadata }; } } - ``` ## Examples @@ -170,7 +160,6 @@ Operation with the @relay_test_operation directive will have additional metadata Using `createMockEnvironment` and `MockPayloadGenerator` allows writing concise tests for components that are using Relay Containers and Renderers. Both those modules can be imported from `relay-test-utils` ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { @@ -223,7 +212,6 @@ test('Error State', () => { renderer.root.find(item => (item.props.testID = 'errorMessage')), ).toBeDefined(); }); - ``` ### Fragment Container Tests @@ -231,7 +219,6 @@ test('Error State', () => { Essentially, in the example above will `resolveMostRecentOperation` will generate data for all child fragment containers (pagination, refetch). But, usually the Root Components container may have many child fragment components and you may want to exercise a specific Fragment Container. The solution for that would be to wrap you fragment container with the QueryRenderer that renders a Query that's spreads fragments from you fragment container. ```javascript - test('Fragment Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -262,7 +249,6 @@ test('Fragment Container', () => { expect(renderer).toMatchSnapshot(); }); - ``` ### Pagination Container Test @@ -270,7 +256,6 @@ test('Fragment Container', () => { Essentially, tests for Pagination container are not different from Fragment Container tests. But we can do more here, we can actually see how the pagination works - we can assert the behavior of our components when performing pagination (load more, refetch). ```javascript - // Pagination Example test('Pagination Container', () => { const environment = createMockEnvironment(); @@ -344,7 +329,6 @@ test('Pagination Container', () => { We can use similar approach here with wrapping container with Query Renderer. And for the sake of completeness, we will add example here: ```javascript - test('Refetch Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -386,7 +370,6 @@ test('Refetch Container', () => { ); // expect(renderer).toMatchSnapshot(); }); - ``` ### Mutations @@ -394,7 +377,6 @@ test('Refetch Container', () => { Mutations itself are operations so we can test them independently (unit-test) for specific mutation, or in combination with the view from which this mutation is called. ```javascript - // Say, you have a mutation function function sendMutation(environment, onCompleted, onError, variables) commitMutation(environment, { @@ -417,7 +399,6 @@ test('it should send mutation', () => { ); expect(onCompleted).toBeCalled(); }); - ``` ### Subscription @@ -425,7 +406,6 @@ test('it should send mutation', () => { We can test subscription in a similar way we test mutations ```javascript - // Example subscribe function function subscribe(environment, onNext, onError, variables) requestSubscription(environment, { @@ -448,7 +428,6 @@ test('it should subscribe', () => { ); expect(onNext).toBeCalled(); }); - ``` ### Example with `queueOperationResolver` @@ -456,7 +435,6 @@ test('it should subscribe', () => { With `queueOpeararionResolver` it possible to define responses for operations that will be executed on the environment ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { diff --git a/website/versioned_docs/version-v10.0.0/Modern-TypeEmission.md b/website/versioned_docs/version-v10.0.0/Modern-TypeEmission.md index 63614b869a322..4ff63e4a7d81b 100644 --- a/website/versioned_docs/version-v10.0.0/Modern-TypeEmission.md +++ b/website/versioned_docs/version-v10.0.0/Modern-TypeEmission.md @@ -16,7 +16,6 @@ In this example the emitted type-information would require the variables object #### Flow ```javascript - /** * export type ExampleQueryVariables = {| * +artistID: string @@ -44,7 +43,6 @@ const variables: ExampleQueryVariables = { #### TypeScript ```javascript - /** * export type ExampleQueryVariables = { * readonly artistID: string @@ -79,7 +77,6 @@ In this example the emitted type-information describes the response data availab #### Flow ```javascript - /** * export type ExampleQueryResponse = {| * +artist: ?{| @@ -110,7 +107,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * export type ExampleQueryResponse = { * readonly artist?: { @@ -146,7 +142,6 @@ Similarly, in this example the emitted type-information describes the prop data #### Flow ```javascript - /** * export type ExampleFragment_artist = {| * +name: string @@ -172,7 +167,6 @@ export const ExampleFragment = createFragmentContainer( #### TypeScript ```javascript - /** * export type ExampleFragment_artist = { * readonly name: string @@ -206,7 +200,6 @@ Consider a component that composes the above fragment container example. In this #### Flow ```javascript - /** * import type { FragmentReference } from "relay-runtime"; * declare export opaque type ExampleFragment_artist$ref: FragmentReference; @@ -250,7 +243,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * declare const _ExampleFragment_artist$ref: unique symbol; * export type ExampleFragment_artist$ref = typeof _ExampleFragment_artist$ref; @@ -315,7 +307,6 @@ $ relay-compiler --artifactDirectory ./src/__generated__ […] ["relay", { "artifactDirectory": "./src/__generated__" }] ] } - ``` It is recommended to alias this directory in your module resolution configuration such that you don’t need to specify relative paths in your source files. This is what is also done in the above examples, where artifacts are imported from a `__generated__` alias, rather than relative paths like `../../../../__generated__`. diff --git a/website/versioned_docs/version-v10.0.0/Modern-UpgradingSetVariables.md b/website/versioned_docs/version-v10.0.0/Modern-UpgradingSetVariables.md index d5b086fafce20..ff73feec04f8b 100644 --- a/website/versioned_docs/version-v10.0.0/Modern-UpgradingSetVariables.md +++ b/website/versioned_docs/version-v10.0.0/Modern-UpgradingSetVariables.md @@ -36,7 +36,6 @@ fragment on User { # ... } } - ``` This should be upgraded to use a [`PaginationContainer`](./pagination-container). @@ -61,7 +60,6 @@ fragment on User { # ... } } - ``` This can be upgraded by using a [`RefetchContainer`](./refetch-container) which allows you to specify the exact query to use to fetch the new data. @@ -86,7 +84,6 @@ fragment on FeedbackTarget { # ... } } - ``` This can be upgraded by conditionally rendering a [`QueryRenderer`](./query-renderer) which will load the data once it is rendered. The code overhead of doing this is dramatically reduced with the new API. diff --git a/website/versioned_docs/version-v10.0.0/Modern-fetchQuery.md b/website/versioned_docs/version-v10.0.0/Modern-fetchQuery.md index 2e9461ad527bd..c1a06ab7d2493 100644 --- a/website/versioned_docs/version-v10.0.0/Modern-fetchQuery.md +++ b/website/versioned_docs/version-v10.0.0/Modern-fetchQuery.md @@ -6,7 +6,6 @@ original_id: fetch-query You can use the `fetchQuery` function to imperatively make GraphQL Requests. This is useful for cases where you want to make requests outside of React but still utilize the Relay store and network layer. ```javascript - import {fetchQuery, graphql} from 'relay-runtime'; const query = graphql` @@ -25,7 +24,6 @@ fetchQuery(environment, query, variables) .then(data => { // access the graphql response }); - ``` ## Arguments diff --git a/website/versioned_docs/version-v10.0.0/PrinciplesAndArchitecture-Compiler.md b/website/versioned_docs/version-v10.0.0/PrinciplesAndArchitecture-Compiler.md index c195491682b1f..fcd0490cb724f 100644 --- a/website/versioned_docs/version-v10.0.0/PrinciplesAndArchitecture-Compiler.md +++ b/website/versioned_docs/version-v10.0.0/PrinciplesAndArchitecture-Compiler.md @@ -74,7 +74,6 @@ foo { # type FooType foo { id } - ``` - `SkipRedundantNodeTransform`: A more advanced version of flattening, this eliminates more complex cases of field duplication such as when a field is fetched both unconditionally and conditionally, or is fetched by two different sub-fragments. For example: @@ -97,7 +96,6 @@ foo { id } } - ``` - `GenerateRequisiteFieldTransform`: This optional, Relay-specific transform inserts `id` fields for globally identifiable objects and `__typename` fields wherever the type cannot be statically determined (e.g. for unions). diff --git a/website/versioned_docs/version-v10.0.0/PrinciplesAndArchitecture-Runtime.md b/website/versioned_docs/version-v10.0.0/PrinciplesAndArchitecture-Runtime.md index 9491d290c146f..e9221631a701d 100644 --- a/website/versioned_docs/version-v10.0.0/PrinciplesAndArchitecture-Runtime.md +++ b/website/versioned_docs/version-v10.0.0/PrinciplesAndArchitecture-Runtime.md @@ -77,7 +77,6 @@ RecordSource { city: 'Seattle', } } - ``` [1] Note that GraphQL itself does not impose this constraint, and Relay Runtime may also be used for schemas that do not conform to it. For example, both systems can be used to query a single denormalized table. However, many of the features that Relay Runtime provides, such as caching and normalization, work best when the data is represented as a normalized graph with stable identities for discrete pieces of information. diff --git a/website/versioned_docs/version-v10.0.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md b/website/versioned_docs/version-v10.0.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md index a8842ae084922..9ff8a7840df90 100644 --- a/website/versioned_docs/version-v10.0.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md +++ b/website/versioned_docs/version-v10.0.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md @@ -12,7 +12,6 @@ In this article we'll explore what it means to build a GraphQL client framework Imagine we have a simple application that fetches a list of stories, and some details about each one. Here's how that might look in resource-oriented REST: ```javascript - // Fetch the list of story IDs but not their details: rest.get('/stories').then(stories => // This resolves to a list of items with linked resources: @@ -25,13 +24,11 @@ rest.get('/stories').then(stories => // `[ { id: "...", text: "..." } ]` console.log(stories); }); - ``` Note that this approach requires _n+1_ requests to the server: 1 to fetch the list, and _n_ to fetch each item. With GraphQL we can fetch the same data in a single network request to the server (without creating a custom endpoint that we'd then have to maintain): ```javascript - graphql.get(`query { stories { id, text } }`).then( stories => { // A list of story items: @@ -39,7 +36,6 @@ graphql.get(`query { stories { id, text } }`).then( console.log(stories); } ); - ``` So far we're just using GraphQL as a more efficient version of typical REST approaches. Note two important benefits in the GraphQL version: @@ -56,7 +52,6 @@ Repeatedly refetching information from the server can get quite slow. For exampl In a resource-oriented REST system, we can maintain a **response cache** based on URIs: ```javascript - var _cache = new Map(); rest.get = uri => { if (!_cache.has(uri)) { @@ -64,13 +59,11 @@ rest.get = uri => { } return _cache.get(uri); }; - ``` Response-caching can also be applied to GraphQL. A basic approach would work similarly to the REST version. The text of the query itself can be used as a cache key: ```javascript - var _cache = new Map(); graphql.get = queryText => { if (!_cache.has(queryText)) { @@ -78,7 +71,6 @@ graphql.get = queryText => { } return _cache.get(queryText); }; - ``` Now, requests for previously cached data can be answered immediately without making a network request. This is a practical approach to improving the perceived performance of an application. However, this method of caching can cause problems with data consistency. @@ -90,7 +82,6 @@ With GraphQL it is very common for the results of multiple queries to overlap. H ``` query { stories { id, text, likeCount } } - ``` and then later refetch one of the stories whose `likeCount` has since been incremented: @@ -98,7 +89,6 @@ and then later refetch one of the stories whose `likeCount` has since been incre ``` query { story(id: "123") { id, text, likeCount } } - ``` We'll now see different `likeCount`s depending on how the story is accessed. A view that uses the first query will see an outdated count, while a view using the second query will see the updated count. @@ -119,7 +109,6 @@ query { } } } - ``` And here's a possible response: @@ -134,13 +123,11 @@ query: { } } } - ``` Although the response is hierarchical, we'll cache it by flattening all the records. Here is an example of how Relay would cache this query response: ```javascript - Map { // `story(id: "1")` 1: Map { @@ -152,7 +139,6 @@ Map { name: 'Jan', }, }; - ``` This is only a simple example: in reality the cache must handle one-to-many associations and pagination (among other things). @@ -182,7 +168,6 @@ The first query was for a list of stories: ``` query { stories { id, text, likeCount } } - ``` With a normalized response cache, a record would be created for each story in the list. The `stories` field would store links to each of these records. @@ -192,7 +177,6 @@ The second query refetched the information for one of those stories: ``` query { story(id: "123") { id, text, likeCount } } - ``` When this response is normalized, Relay can detect that this result overlaps with existing data based on its `id`. Rather than create a new record, Relay will update the existing `123` record. The new `likeCount` is therefore available to _both_ queries, as well as any other query that might reference this story. @@ -215,7 +199,6 @@ query { } } } - ``` After initially fetching this story our cache might be as follows. Note that the story and comment both link to the same record as `author`: @@ -242,7 +225,6 @@ Map { author: Link(2), }, } - ``` The author of this story also commented on it — quite common. Now imagine that some other view fetches new information about the author, and her profile photo has changed to a new URI. Here's the _only_ part of our cached data that changes: @@ -256,7 +238,6 @@ Map { photo: 'http://.../photo2.jpg', }, } - ``` The value of the `photo` field has changed; and therefore the record `2` has also changed. And that's it. Nothing else in the _cache_ is affected. But clearly our _view_ needs to reflect the update: both instances of the author in the UI (as story author and comment author) need to show the new photo. @@ -273,7 +254,6 @@ ImmutableMap { }, 3: ImmutableMap // same as before } - ``` If we replace `2` with a new immutable record, we'll also get a new immutable instance of the cache object. However, records `1` and `3` are untouched. Because the data is normalized, we can't tell that `story`'s contents have changed just by looking at the `story` record alone. @@ -299,7 +279,6 @@ mutation StoryLike($storyID: String) { likeCount } } - ``` Notice that we're querying for data that _may_ have changed as a result of the mutation. An obvious question is: why can't the server just tell us what changed? The answer is: it's complicated. GraphQL abstracts over _any_ data storage layer (or an aggregation of multiple sources), and works with any programming language. Furthermore, the goal of GraphQL is to provide data in a form that is useful to product developers building a view. diff --git a/website/versioned_docs/version-v10.0.0/PrinciplesAndArchitecture-ThinkingInRelay.md b/website/versioned_docs/version-v10.0.0/PrinciplesAndArchitecture-ThinkingInRelay.md index e61f3fd21c933..62b1914ef3ff9 100644 --- a/website/versioned_docs/version-v10.0.0/PrinciplesAndArchitecture-ThinkingInRelay.md +++ b/website/versioned_docs/version-v10.0.0/PrinciplesAndArchitecture-ThinkingInRelay.md @@ -30,13 +30,11 @@ fragment Story_story on Story { photo } } - ``` And this fragment can then be used to define the Story container: ```javascript - const {createFragmentContainer, graphql} = require('react-relay'); // Plain React component. @@ -64,7 +62,6 @@ const StoryContainer = createFragmentContainer(Story, { In React, rendering a view requires two inputs: the _component_ to render, and a _root_ DOM (UI) node to render into. Rendering Relay containers is similar: we need a _container_ to render, and a _root_ in the graph from which to start our query. We also must ensure that the queries for the container are executed and may want to show a loading indicator while data is being fetched. Similar to `ReactDOM.render(component, domNode)`, Relay provides `` for this purpose. The `query` and `variables` define what data to fetch and `render` defines what to render. Here's how we might render ``: ```javascript - ReactDOM.render( { ); } } - ``` The above code is doing something very similar to our [previous example](#rendering-graphql-queries). However, we are now passing a `$userID` variable to the GraphQL query via the `variables` prop. This has a couple of important implications: @@ -228,7 +216,6 @@ Now that we know how to define and fetch queries, let's actually start building First, let's start at the bottom. Suppose that we want to render a component that simply displays a given todo item's text and completed state: ```javascript - // Todo.js import React from 'react'; @@ -258,7 +245,6 @@ export default class Todo extends React.Component { ); } } - ``` From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L112), we know that we can query this data on the `Todo` type. However, we don't want to have to send a separate query for each todo item; that would defeat the purpose of using GraphQL over a traditional REST API. We could manually query for these fields directly in our `QueryRenderer` query, but that would hurt re-usability: what if we want to query the same set of fields as part of a different query? Additionally, we wouldn't know which component needs the data we're querying, which is a problem Relay directly tries to address. @@ -266,18 +252,15 @@ From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/dat Instead, we can define a reusable [Fragment](http://graphql.org/learn/queries/#fragments), which allows us to define a set of fields on a type and reuse them within our queries wherever we need to: ```graphql - fragment TodoItemFragment on Todo { complete text } - ``` Our component can then use this fragment to declare its data dependency on the `Todo` GraphQL type: ```javascript - // Todo.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -340,7 +323,6 @@ Before proceeding, don't forget to run the Relay Compiler with `yarn relay`. Given that [Fragment Containers](./fragment-container) are just React components, we can compose them as such. We can even re-use fragment containers within other fragment containers. As an example, let's see how we would define a `TodoList` component that just renders a list of todo items, and whether all have been completed or not: ```javascript - // TodoList.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -401,7 +383,6 @@ export default createFragmentContainer( `, }, ); - ``` As with the first fragment container we defined, `TodoList` declares it's data dependencies via a fragment. However, this component additionally re-uses the fragment previously defined by the `Todo` component, and passes the appropriate data when rendering the child `Todo` components (a.k.a. fragment containers). @@ -416,7 +397,6 @@ fragment containers do not directly fetch data. Instead, containers declare a sp A `QueryRenderer` rendering these fragment containers could look like the following: ```javascript - // ViewerTodoList.js import React from 'react'; import {graphql, QueryRenderer} from 'react-relay'; @@ -457,7 +437,6 @@ export default class ViewerTodoList extends React.Component { ); } } - ``` Check out our docs for [Fragment Containers](./fragment-container) for more details, and our guides on [Refetch](./refetch-container) and [Pagination](./pagination-container) for more advanced usage of containers. @@ -469,7 +448,6 @@ Now that we know how to query for and render data, let's move on to changing our From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L35), we know that we have some mutations available to us, so let's start by writing a mutation to change the `complete` status of a given todo item (i.e. mark or unmark it as done): ```graphql - mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { changeTodoStatus(input: $input) { todo { @@ -478,7 +456,6 @@ mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { } } } - ``` This mutation allows us to query back some data as a [result of the mutation](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L18), so we're going to query for the updated `complete` status on the todo item. @@ -486,7 +463,6 @@ This mutation allows us to query back some data as a [result of the mutation](ht In order to execute this mutation in Relay, we're going to write a new mutation using Relay's `commitMutation` api: ```javascript - // ChangeTodoStatusMutation.js import {graphql, commitMutation} from 'react-relay'; @@ -520,7 +496,6 @@ function commit( } export default {commit}; - ``` Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mutation to the server and, in our case, upon receiving a response it will automatically update the local data store with the latest data from the server. This also means that upon receiving the response, Relay will ensure that any components (i.e. containers) that depend on the updated data are re-rendered. @@ -528,7 +503,6 @@ Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mut In order to actually use this mutation in our component, we could update our `Todo` component in the following way: ```javascript - // Todo.js // ... @@ -562,7 +536,6 @@ In order to make the experience better, we can configure our mutation to do an o In Relay, there's a couple of options we can pass to `commitMutation` to enable optimistic updates. Let's see what that would look like in our `ChangeTodoStatusMutation`: ```javascript - // ChangeTodoStatusMutation.js // ... @@ -597,7 +570,6 @@ function commit( } export default {commit}; - ``` In the simplest case above, we just need to pass an `optimisticResponse` option, which should refer to an object having the same shape as the mutation response payload. When we pass this option, Relay will know to immediately update our local data with the optimistic response, and then update it with the actual server response or roll it back if an error occurs. diff --git a/website/versioned_docs/version-v10.0.1/Modern-ConvertingMutations.md b/website/versioned_docs/version-v10.0.1/Modern-ConvertingMutations.md index 08ad2e998cb2d..8f4bdc1d8e0d2 100644 --- a/website/versioned_docs/version-v10.0.1/Modern-ConvertingMutations.md +++ b/website/versioned_docs/version-v10.0.1/Modern-ConvertingMutations.md @@ -12,19 +12,16 @@ FatQueries in Relay Classic mutations was a concept that was confusing for a num Example of existing fat query: ```javascript - RelayClassic.QL` fragment on MarkReadNotificationResponsePayload @relay(pattern: true) { notification } `; - ``` Example of converted mutation query: ```javascript - graphql` mutation MarkReadNotificationMutation( $input: MarkReadNotificationData! @@ -37,7 +34,6 @@ graphql` } } `; - ``` ## Migrating Configs @@ -67,7 +63,6 @@ This is no longer needed in Compatibility Mode for neither environments. Simply Take this example of a simple mutation in Relay Classic: ```javascript - class LikeStoryMutation extends RelayClassic.Mutation { getMutation() { return RelayClassic.QL`mutation {likeStory}`; @@ -106,7 +101,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { `, }; } - ``` ### Converting `getMutation()` and `getFatQuery()` @@ -114,7 +108,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { We combine these two into a regular GraphQL mutation, which list out specific fields that needs to be updated. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story(data: $input) { @@ -126,7 +119,6 @@ const mutation = graphql` } } `; - ``` ### Converting `getConfigs()` @@ -138,13 +130,11 @@ As specified above, `FIELDS_CHANGE` configs can be omitted. To convert `getVariables()`, we take the return value from the original function and wrap it in an object that contains a property that matches the variable name for the mutation. In this case, the mutation has a `input` variable that is of type `LikeStoryData`. ```javascript - const variables = { input: { storyID: args.storyID } } - ``` ### Final Result @@ -152,7 +142,6 @@ const variables = { As you can see, our resulting mutation is a lot simpler and more like regular GraphQL than the Relay Classic version we started out with. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story { @@ -178,7 +167,6 @@ function commit(environment: CompatEnvironment, args) { variables, }); } - ``` See [Mutation](./mutations) for additional options on `commitMutation` for more complex mutations. diff --git a/website/versioned_docs/version-v10.0.1/Modern-FragmentContainer.md b/website/versioned_docs/version-v10.0.1/Modern-FragmentContainer.md index 423f446cbb054..6a40bbcfb5d0a 100644 --- a/website/versioned_docs/version-v10.0.1/Modern-FragmentContainer.md +++ b/website/versioned_docs/version-v10.0.1/Modern-FragmentContainer.md @@ -17,12 +17,10 @@ Table of Contents: `createFragmentContainer` has the following signature: ```javascript - createFragmentContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, ): ReactComponentClass; - ``` ### Arguments @@ -43,7 +41,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -58,7 +55,6 @@ To start, let's build the plain React version of a hypothetical `` c Here's a basic implementation of `` that ignores styling in order to highlight the functionality: ```javascript - // TodoItem.js class TodoItem extends React.Component { render() { @@ -78,7 +74,6 @@ class TodoItem extends React.Component { ); } } - ``` ### Data Dependencies With GraphQL @@ -86,7 +81,6 @@ class TodoItem extends React.Component { In Relay, data dependencies are described using [GraphQL](https://github.com/facebook/graphql). For ``, the dependency can be expressed as follows. Note that this exactly matches the shape that the component expected for the `item` prop. ```javascript - graphql` # This fragment only applies to objects of type 'Todo'. fragment TodoItem_item on Todo { @@ -102,7 +96,6 @@ graphql` Given the plain React component and a GraphQL fragment, we can now define a Fragment Container to specify this component's data requirements. Let's look at the code first and then see what's happening: ```javascript - // TodoItem.js import {createFragmentContainer, graphql} from 'react-relay'; @@ -120,7 +113,6 @@ export default createFragmentContainer(TodoItem, { } `, }); - ``` ## Container Composition @@ -134,7 +126,6 @@ Let's explore how this works via a `` component that composes the `< View composition is _exactly_ what you're used to — Relay containers are just standard React components. Here's the `` component: ```javascript - class TodoList extends React.Component { render() { // Expects a `list` with a string `title`, as well as the information @@ -151,7 +142,6 @@ class TodoList extends React.Component { ); } } - ``` ### Composing Fragments @@ -159,7 +149,6 @@ class TodoList extends React.Component { Fragment composition works similarly — a parent container's fragment composes the fragment for each of its children. In this case, `` needs to fetch information about the `Todo`s that are required by ``. ```javascript - class TodoList extends React.Component // as above export default createFragmentContainer(TodoList, { @@ -176,7 +165,6 @@ export default createFragmentContainer(TodoList, { } `, }); - ``` Note that when composing fragments, the type of the composed fragment must match the field on the parent in which it is embedded. For example, it wouldn't make sense to embed a fragment of type `Story` into a parent's field of type `User`. Relay and GraphQL will provide helpful error messages if you get this wrong (and if they aren't helpful, let us know!). @@ -190,7 +178,6 @@ When defining a fragment, you can use the [`@argumentDefinitions`](./graphql-in- For example, let's redefine our `TodoList_list` fragment to take some arguments using `@argumentDefinitions`: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -200,7 +187,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` Any arguments defined inside `@argumentDefinitions` will be local variables available inside the fragment's scope. However, a fragment can also reference global variables that were defined in the root query. @@ -212,11 +198,9 @@ In order to pass arguments to a fragment that has `@argumentDefinitions`, you ne Following our `TodoList_list` example, we would pass arguments to the fragment like so: ```graphql - query TodoListQuery($count: Int, $userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` ## Rendering Containers diff --git a/website/versioned_docs/version-v10.0.1/Modern-GraphQLInRelay.md b/website/versioned_docs/version-v10.0.1/Modern-GraphQLInRelay.md index c4dc8f3463e53..715b119492cc7 100644 --- a/website/versioned_docs/version-v10.0.1/Modern-GraphQLInRelay.md +++ b/website/versioned_docs/version-v10.0.1/Modern-GraphQLInRelay.md @@ -14,7 +14,6 @@ Table of Contents: The `graphql` template tag provided by Relay serves as the mechanism to write queries, fragments, mutations or subscriptions in the [GraphQL](http://graphql.org/learn/) language. For example: ```javascript - import {graphql} from 'react-relay'; graphql` @@ -24,7 +23,6 @@ graphql` } } `; - ``` The result of using the `graphql` template tag is a `GraphQLTaggedNode`; a runtime representation of the GraphQL document which can be used to define [Query Renderers](./query-renderer), [Fragment Containers](./fragment-container), [Refetch Containers](./refetch-container), [Pagination Containers](./pagination-container), etc. @@ -42,11 +40,9 @@ Relay uses directives to add additional information to GraphQL documents, which `@arguments` is a directive used to pass arguments to a fragment that was defined using [`@argumentDefinitions`](#argumentdefinitions). For example: ```graphql - query TodoListQuery($userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -56,7 +52,6 @@ See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fr `@argumentDefinitions` is a directive used to specify arguments taken by a fragment. For example: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -66,7 +61,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -80,7 +74,6 @@ When using the [Pagination Container](./pagination-container), Relay expects con When defining a fragment for use with a Fragment container, you can use the `@relay(plural: true)` directive to indicate that container expects the prop for that fragment to be a list of items instead of a single item. A query or parent that spreads a `@relay(plural: true)` fragment should do so within a plural field (ie a field backed by a [GraphQL list](http://graphql.org/learn/schema/#lists-and-non-null). For example: ```javascript - // Plural fragment definition graphql` fragment TodoItems_items on TodoItem @relay(plural: true) { @@ -95,7 +88,6 @@ fragment TodoApp_app on App { ...TodoItem_items } } - ``` ### `@inline` @@ -107,7 +99,6 @@ Non-React functions can also take advantage of data masking. A fragment can be d In the example below, the function `processItemData` is called from a React component. It requires an item object with a specific set of fields. All React components that use this function should spread the `processItemData_item` fragment to ensure all of the correct item data is loaded for this function. ```javascript - import {graphql, readInlineData} from 'react-relay'; // non-React function called from React @@ -127,11 +118,9 @@ function processItemData(itemRef) { creatorName: item.creator.name }); } - ``` ```javascript - // React Component function MyComponent({item}) { function handleClick() { @@ -151,7 +140,6 @@ export default createFragmentContainer(MyComponent, { } ` }); - ``` ### `@relay(mask: Boolean)` @@ -169,7 +157,6 @@ Keep in mind that it is typically considered an **anti-pattern** to create a sin In the example below, the `user` prop will include the data for `id` and `name` fields wherever `...Component_internUser` is included, instead of Relay's normal behavior to mask those fields: ```javascript - graphql` fragment Component_internUser on InternUser @relay(mask: false) { id @@ -197,7 +184,6 @@ export default createFragmentContainer( } `, ); - ``` ## Relay Compiler @@ -207,7 +193,6 @@ Relay uses the Relay Compiler to convert [`graphql`](#graphql) literals into gen A query like the following: ```javascript - graphql` fragment MyComponent on Type { field @@ -228,12 +213,10 @@ Relay Compiler supports the use of **persisted queries**, in which each version Persisted queries can be enabled by instructing Relay Compiler to emit metadata about each query, mutation, and subscription into a JSON file. The generated file will contain a mapping of query identifiers to query text, which you can then save to your server. To enable persisted queries, use the `--persist-output` flag to the compiler: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` Relay Compiler will then create the id => query text mapping in the path you specify. You can then use this complete @@ -250,7 +233,6 @@ See our relay-compiler section in our [Installation and Setup guide](./installat To use the Relay Compiler, you need either a .graphql or .json GraphQL schema file, describing your GraphQL server's API. Typically these files are local representations of a server source of truth and are not edited directly. For example, we might have a `schema.graphql` like: ```graphql - schema { query: Root } @@ -268,7 +250,6 @@ type WordDefinition { text: String image: String } - ``` ### Source files @@ -284,7 +265,6 @@ For example, given the two files: - `src/Components/DictionaryComponent.js` ```javascript - const DictionaryWordFragment = graphql` fragment DictionaryComponent_word on Word { id @@ -306,7 +286,6 @@ For example, given the two files: - `src/Queries/DictionaryQuery.js` ```javascript - const DictionaryQuery = graphql` query DictionaryQuery { dictionary { @@ -330,9 +309,7 @@ Typically you will not need to import your generated definitions. The [Relay Bab However the Relay Compiler also automatically generates [Flow](https://flow.org) types as [type comments](https://flow.org/en/docs/types/comments/). For example, you can import the generated Flow types like so: ```javascript - import type {DictionaryComponent_word} from './__generated__/DictionaryComponent_word.graphql'; - ``` ### Client schema extensions @@ -342,7 +319,6 @@ The Relay Compiler fully supports client-side schema extensions, which allows yo For example, assuming the server schema `./schema.graphql`: ```graphql - schema { query: Root } @@ -350,28 +326,23 @@ schema { type Root { title: String! } - ``` We can create a `./src/clientSchema.graphql` and define a new type called `Setting`: ```graphql - type Setting { name: String! active: Boolean! } - ``` We can then extend existing server types in the client schema `./src/clientSchema.graphql` with our new `Setting` type, like so: ```graphql - extend type Root { settings: [Setting] } - ``` Any fields specified in the client schema, can be fetched from the [Relay Store](./relay-store), by selecting it in a query or fragment. diff --git a/website/versioned_docs/version-v10.0.1/Modern-LocalStateManagement.md b/website/versioned_docs/version-v10.0.1/Modern-LocalStateManagement.md index da71a0dd33246..3ecbf6801f91c 100644 --- a/website/versioned_docs/version-v10.0.1/Modern-LocalStateManagement.md +++ b/website/versioned_docs/version-v10.0.1/Modern-LocalStateManagement.md @@ -24,23 +24,19 @@ It can even be used to extend an existing server schema. For example, we can create a new type called `Note`: ```graphql - type Note { id: ID! title: String body: String } - ``` And then extend the server schema type `User`, with a list of `Note`, called `notes`. ```graphql - extend type User { notes: [Note] } - ``` ## Querying local state @@ -51,7 +47,6 @@ The field can be from the server schema, or it can be schema agnostic, like an i Here, we use a [QueryRenderer](./query-renderer) to get the current `User` via the `viewer` field, along with their id, name and the local list of notes. ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -97,7 +92,6 @@ const Example = (props) => { /> ); } - ``` ## Mutating local state @@ -111,7 +105,6 @@ To build upon the previous example, let's try creating, updating and deleting a ### Create ```javascript - import {commitLocalUpdate} from 'react-relay'; let tempID = 0; @@ -131,7 +124,6 @@ function createUserNote() { user.setLinkedRecords([...userNoteRecords, newNoteRecord], 'notes'); }); } - ``` Note that since this record will be rendered by the `ExampleQuery` in our `QueryRenderer`, the QueryRenderer will automatically retain this data so it isn't garbage collected. @@ -139,7 +131,6 @@ Note that since this record will be rendered by the `ExampleQuery` in our `Query If no component is rendering the local data and you want to manually retain it, you can do so by calling `environment.retain()`: ```javascript - import {createOperationDescriptor, getRequest} from 'relay-runtime'; // Create a query that references that record @@ -166,13 +157,11 @@ const disposable = environment.retain(operation); // Whenever you don't need that data anymore and it's okay for Relay to garbage collect it, // you can dispose of the retain disposable.dispose(); - ``` ### Update ```javascript - import {commitLocalUpdate} from 'react-relay'; function updateUserNote(dataID, body, title) { @@ -183,13 +172,11 @@ function updateUserNote(dataID, body, title) { note.setValue(title, 'title') }); } - ``` ### Delete ```javascript - import {commitLocalUpdate} from 'react-relay'; function deleteUserNote(dataID) { @@ -207,7 +194,6 @@ function deleteUserNote(dataID) { user.setLinkedRecords(newUserNoteRecords, 'notes'); }); } - ``` ## Initial local state @@ -216,7 +202,6 @@ All new client-side schema fields default to `undefined` value. Often however, y You can use an updater function via `commitLocalUpdate` to prime local state. ```javascript - import {commitLocalUpdate} from 'react-relay'; commitLocalUpdate(environment, store => { @@ -225,5 +210,4 @@ commitLocalUpdate(environment, store => { // initialize user notes to an empty array. user.setLinkedRecords([], 'notes'); }); - ``` diff --git a/website/versioned_docs/version-v10.0.1/Modern-MigrationSetup.md b/website/versioned_docs/version-v10.0.1/Modern-MigrationSetup.md index 66f1145357e25..a89c0e178e0e5 100644 --- a/website/versioned_docs/version-v10.0.1/Modern-MigrationSetup.md +++ b/website/versioned_docs/version-v10.0.1/Modern-MigrationSetup.md @@ -13,13 +13,11 @@ With some additional configuration, the `"relay"` babel plugin can also translat Relay Classic `Relay.QL` literals. Most importantly, include a reference to your GraphQL Schema as either a json file or graphql schema file. ```javascript - { "plugins": [ ["relay", {"schema": "path/schema.graphql"}] ] } - ``` ## Set up babel-plugin-relay for "[compatibility mode](./relay-compat)" @@ -29,13 +27,11 @@ literals can be translated to be usable by _both_ runtimes if configured to use compatibility mode: ```javascript - { "plugins": [ ["relay", {"compat": true, "schema": "path/schema.graphql"}] ] } - ``` ## Additional Options @@ -47,7 +43,6 @@ thrown at runtime. When compiling code for production deployment, the plugin can be configured to immediately throw upon encountering a validation problem. The plugin can be further customized for different environments with the following options: ```javascript - { "plugins": [ ["relay", { @@ -56,5 +51,4 @@ When compiling code for production deployment, the plugin can be configured to i }] ] } - ``` diff --git a/website/versioned_docs/version-v10.0.1/Modern-Mutations.md b/website/versioned_docs/version-v10.0.1/Modern-Mutations.md index 27be2a4bd7e2d..4dbecb9dbf7df 100644 --- a/website/versioned_docs/version-v10.0.1/Modern-Mutations.md +++ b/website/versioned_docs/version-v10.0.1/Modern-Mutations.md @@ -17,7 +17,6 @@ Table of Contents: Use `commitMutation` to create and execute mutations. `commitMutation` has the following signature: ```javascript - commitMutation( environment: Environment, config: { @@ -32,7 +31,6 @@ commitMutation( cacheConfig?: CacheConfig, }, ); - ``` ### Arguments @@ -60,7 +58,6 @@ commitMutation( Example of a simple mutation: ```javascript - import {commitMutation, graphql} from 'react-relay'; const mutation = graphql` @@ -92,7 +89,6 @@ function markNotificationAsRead(environment, storyID) { }, ); } - ``` ## Optimistic Updates @@ -100,7 +96,6 @@ function markNotificationAsRead(environment, storyID) { To improve perceived responsiveness, you may wish to perform an "optimistic update", in which the client immediately updates to reflect the anticipated new value even before the response from the server has come back. The simplest way to do this is by providing an `optimisticResponse` and adding it to the `config` that we pass into `commitMutation`: ```javascript - const mutation = graphql` mutation MarkReadNotificationMutation( $storyID: ID! @@ -129,7 +124,6 @@ commitMutation( variables, }, ); - ``` Another way to enable optimistic updates is via the `optimisticUpdater`, which can be used for more complicated update scenarios. Using `optimisticUpdater` is covered in the section [below](#using-updater-and-optimisticupdater). @@ -151,7 +145,6 @@ Given a deletedIDFieldName, Relay will remove the node(s) from the store. #### Example ```javascript - const mutation = graphql` mutation DestroyShipMutation($target: ID!) { destroyShip(target: $target) { @@ -169,7 +162,6 @@ const configs = [{ type: 'NODE_DELETE', deletedIDFieldName: 'destroyedShipId', }]; - ``` ### RANGE_ADD @@ -189,7 +181,6 @@ Given a parent, information about the connection, and the name of the newly crea #### Example ```javascript - const mutation = graphql` mutation AddShipMutation($factionID: ID!, $name: String!) { addShip(factionID: $factionID, name: $name) { @@ -220,7 +211,6 @@ function commit(environment, factionID, name) { }], }); } - ``` ### RANGE_DELETE @@ -242,7 +232,6 @@ from the connection but leave the associated record(s) in the store. #### Example ```javascript - const mutation = graphql` mutation RemoveTagMutation($todoID: ID!, $tagID: ID!) { removeTag(todo: $todoID, tag: $tagID) { @@ -269,7 +258,6 @@ function commit(environment, todoID, tagID) { }], }); } - ``` ## Using updater and optimisticUpdater @@ -287,7 +275,6 @@ When you provide these functions, this is roughly what happens during the mutati Here are a quick example of adding a todo item to a Todo list using this [example schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L36): ```javascript - // AddTodoMutation.js import {commitMutation, graphql} from 'react-relay'; import {ConnectionHandler} from 'relay-runtime'; @@ -371,7 +358,6 @@ function commit(environment, text, user) { }, }); } - ``` For details on how to interact with the Relay Store, please refer to our Relay Store [docs](./relay-store). diff --git a/website/versioned_docs/version-v10.0.1/Modern-NetworkLayer.md b/website/versioned_docs/version-v10.0.1/Modern-NetworkLayer.md index 9dddd36d6c235..c9e069b812b01 100644 --- a/website/versioned_docs/version-v10.0.1/Modern-NetworkLayer.md +++ b/website/versioned_docs/version-v10.0.1/Modern-NetworkLayer.md @@ -8,7 +8,6 @@ In order to know how to access your GraphQL server, Relay Modern requires develo Currently the easiest way to create a network layer is via a helper from the `relay-runtime` package: ```javascript - import { Environment, Network, @@ -50,7 +49,6 @@ const environment = new Environment({ }); export default environment; - ``` Note that this is a basic example to help you get started. This example could be extended with additional features such as request/response caching (enabled e.g. when `cacheConfig.force` is false) and uploading form data for mutations (the `uploadables` parameter). @@ -62,7 +60,6 @@ Relay modern makes no assumptions about what to cache and will garbage collect a You have to implement your own cache strategy. A simple solution is to use `QueryResponseCache` (an in-memory cache): ```javascript - import { Environment, Network, @@ -126,7 +123,6 @@ const environment = new Environment({ }); export default environment; - ``` ## Custom open-source implementations diff --git a/website/versioned_docs/version-v10.0.1/Modern-PaginationContainer.md b/website/versioned_docs/version-v10.0.1/Modern-PaginationContainer.md index 6ac3aac8cfb8e..57980d553af9b 100644 --- a/website/versioned_docs/version-v10.0.1/Modern-PaginationContainer.md +++ b/website/versioned_docs/version-v10.0.1/Modern-PaginationContainer.md @@ -24,7 +24,6 @@ However, when [specifying connection fragments](#createpaginationcontainer) for The purpose of the `@connection` directive is to allow Relay to uniquely identify different connections under a parent type. The `@connection` directive takes 2 arguments that help identify the connection: ```graphql - @connection(key: String!, filters: [String]) ``` @@ -37,7 +36,6 @@ The purpose of the `@connection` directive is to allow Relay to uniquely identif Specifying just the `key`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and the value of `$orderBy` (given that no `filters` were provided) @@ -53,13 +51,11 @@ fragment Feed_user on User { } } } - ``` Specifying `key` and `filters`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and /only/ the value of `$searchTerm`, i.e. @@ -77,7 +73,6 @@ fragment Feed_user on User { } } } - ``` ## `createPaginationContainer` @@ -85,7 +80,6 @@ fragment Feed_user on User { `createPaginationContainer` has the following signature: ```javascript - createPaginationContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, @@ -113,7 +107,6 @@ type ConnectionData = { startCursor: ?string, }, }; - ``` ### Arguments @@ -134,7 +127,6 @@ type ConnectionData = { The Component resulting from `createPaginationContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -145,7 +137,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -160,7 +151,6 @@ type Props = { `hasMore` is a function available on the `relay` [prop](#available-props). This function indicates whether there are more pages to fetch from the server or not. ```javascript - hasMore: () => boolean, ``` @@ -170,7 +160,6 @@ hasMore: () => boolean, `isLoading` is a function available on the `relay` [prop](#available-props). This function indicates if a previous call to [`loadMore()`](#loadmore) is still pending. This is convenient for avoiding duplicate load calls. ```javascript - isLoading: () => boolean, ``` @@ -180,7 +169,6 @@ isLoading: () => boolean, `loadMore` is a function available on the `relay` [prop](#available-props). You can call `loadMore()` to fetch more items from the server based on the `connectionConfig` provided to the container. This will return null if there are no more items to fetch, otherwise it will fetch more items and return a Disposable that can be used to cancel the fetch. ```javascript - loadMore( pageSize: number, callback: ?(error: ?Error) => void, @@ -201,7 +189,6 @@ loadMore( `refetchConnection` is a function available on the `relay` [prop](#available-props). You can call `refetchConnection` to restart pagination on a connection from scratch, with optionally a completely new set of variables to pass to the pagination `query`. This is useful for example if you are paginating over a collection based on a userID and the userID changes, you'd want to start paginating over the new collection for the new user. ```javascript - refetchConnection:( totalCount: number, callback: (error: ?Error) => void, @@ -219,7 +206,6 @@ refetchConnection:( ## Pagination Example ```javascript - // Feed.js import {createPaginationContainer, graphql} from 'react-relay'; @@ -314,5 +300,4 @@ module.exports = createPaginationContainer( ` } ); - ``` diff --git a/website/versioned_docs/version-v10.0.1/Modern-PersistedQueries.md b/website/versioned_docs/version-v10.0.1/Modern-PersistedQueries.md index 137cc2e23220c..ec03b69ba09c3 100644 --- a/website/versioned_docs/version-v10.0.1/Modern-PersistedQueries.md +++ b/website/versioned_docs/version-v10.0.1/Modern-PersistedQueries.md @@ -17,12 +17,10 @@ The relay compiler supports persisted queries which is useful because: In your `npm` script in `package.json`, run the relay compiler using the `--persist-output` flag: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` The `--persist-ouput` flag does 3 things: @@ -31,8 +29,7 @@ The `--persist-ouput` flag does 3 things: For example without `--persist-output`, a generated `ConcreteRequest` might look like below: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -49,8 +46,7 @@ The `--persist-ouput` flag does 3 things: With `--persist-output ` this becomes: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -68,12 +64,10 @@ The `--persist-ouput` flag does 3 things: 2. It generates a JSON file at the `` you specify containing a mapping from query ids to the corresponding operation texts. -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./src/queryMaps/queryMap.json" } - ``` The example above writes the complete query map file to `./src/queryMaps/queryMap.json`. You need to ensure all the directories @@ -83,8 +77,7 @@ leading to the `queryMap.json` file exist. You'll need to modify your network layer fetch implementation to pass a documentId parameter in the POST body instead of a query parameter: -```js - +```javascript function fetchQuery(operation, variables,) { return fetch('/graphql', { method: 'POST', @@ -100,7 +93,6 @@ function fetchQuery(operation, variables,) { return response.json(); }); } - ``` ## Executing Persisted Queries on the Server @@ -116,13 +108,11 @@ the query map file in a common location accessible to both the client and the se For applications where the client and server projects are separate, one option is to have an additional npm run script to push the query map at compile time to a location accessible by your server: -```js - +```javascript "scripts": { "push-queries": "node ./pushQueries.js", "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-ouput && npm run push-queries" } - ``` Some possibilities of what you can do in `./pushQueries.js`: @@ -146,8 +136,7 @@ database technologies you use, so we'll just cover the most common and basic exa If you use `express-graphql` and have access to the query map file, you can import the `--persist-output` JSON file directly and perform the matching using the `matchQueryMiddleware` from [relay-compiler-plus](https://github.com/yusinto/relay-compiler-plus). -```js - +```javascript import Express from 'express'; import expressGraphql from 'express-graphql'; import {matchQueryMiddleware} from 'relay-compiler-plus'; @@ -158,7 +147,6 @@ const app = Express(); app.use('/graphql', matchQueryMiddleware(queryMapJson), expressGraphql({schema})); - ``` ## Using `--persist-output` and `--watch` diff --git a/website/versioned_docs/version-v10.0.1/Modern-QueryRenderer.md b/website/versioned_docs/version-v10.0.1/Modern-QueryRenderer.md index cf6c37f3d9a4d..b621ef9986bf1 100644 --- a/website/versioned_docs/version-v10.0.1/Modern-QueryRenderer.md +++ b/website/versioned_docs/version-v10.0.1/Modern-QueryRenderer.md @@ -24,7 +24,6 @@ However, a `QueryRenderer` will not start loading its data until it is mounted, ## Example ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -56,5 +55,4 @@ const Example = (props) => { /> ); } - ``` diff --git a/website/versioned_docs/version-v10.0.1/Modern-RefetchContainer.md b/website/versioned_docs/version-v10.0.1/Modern-RefetchContainer.md index 7ce0d14e45417..51c2c44db8941 100644 --- a/website/versioned_docs/version-v10.0.1/Modern-RefetchContainer.md +++ b/website/versioned_docs/version-v10.0.1/Modern-RefetchContainer.md @@ -16,13 +16,11 @@ Table of Contents: `createRefetchContainer` has the following signature: ```javascript - createRefetchContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, refetchQuery: GraphQLTaggedNode, ): ReactComponentClass; - ``` ### Arguments @@ -37,7 +35,6 @@ createRefetchContainer( The Component resulting from `createRefetchContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -45,7 +42,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -61,7 +57,6 @@ type Props = { `refetch` has the following signature: ```javascript - type RefetchOptions = { force?: boolean, }; @@ -102,7 +97,6 @@ Returns a `Disposable` on which you could call `dispose()` to cancel the refetch In this simple example, let's assume we want to fetch the latest data for a `TodoItem` from the server: ```javascript - // TodoItem.js import {createRefetchContainer, graphql} from 'react-relay'; @@ -148,7 +142,6 @@ export default createRefetchContainer( } ` ); - ``` ### Loading more data @@ -156,7 +149,6 @@ export default createRefetchContainer( In this example we are using a Refetch Container to fetch more stories in a story feed component. ```javascript - import {createRefetchContainer, graphql} from 'react-relay'; class FeedStories extends React.Component { @@ -212,5 +204,4 @@ export default createRefetchContainer( } `, ); - ``` diff --git a/website/versioned_docs/version-v10.0.1/Modern-RelayCompat.md b/website/versioned_docs/version-v10.0.1/Modern-RelayCompat.md index 36632d3a8f1a1..f47dbd845ba3e 100644 --- a/website/versioned_docs/version-v10.0.1/Modern-RelayCompat.md +++ b/website/versioned_docs/version-v10.0.1/Modern-RelayCompat.md @@ -31,7 +31,6 @@ Relay Modern. The components using Relay Compat can be referred to by both other Relay Modern and Relay Classic components. ```javascript - const {createFragmentContainer, graphql} = require('react-relay/compat'); class TodoItem extends React.Component { @@ -47,5 +46,4 @@ module.exports = createFragmentContainer(TodoItem, graphql` isComplete } `); - ``` diff --git a/website/versioned_docs/version-v10.0.1/Modern-RelayEnvironment.md b/website/versioned_docs/version-v10.0.1/Modern-RelayEnvironment.md index 27d90b2fc4fe1..99e728bce740d 100644 --- a/website/versioned_docs/version-v10.0.1/Modern-RelayEnvironment.md +++ b/website/versioned_docs/version-v10.0.1/Modern-RelayEnvironment.md @@ -12,7 +12,6 @@ Most applications will create a single Environment instance and use it throughou To create an environment instance in Relay Modern, use the `RelayModernEnvironment` class: ```javascript - const { Environment, Network, @@ -30,7 +29,6 @@ const environment = new Environment({ network, store, }); - ``` For more details on creating a Network, see the [NetworkLayer guide](./network-layer). @@ -44,7 +42,6 @@ The example above did not configure a `handlerProvider`, which means that a defa If you wish to provide your own `handlerProvider`, you can do so: ```javascript - const { ConnectionHandler, } = require('relay-runtime'); @@ -58,5 +55,4 @@ function handlerProvider(handle) { `handlerProvider: No handler provided for ${handle}` ); } - ``` diff --git a/website/versioned_docs/version-v10.0.1/Modern-RelayStore.md b/website/versioned_docs/version-v10.0.1/Modern-RelayStore.md index 6bb2e3744d55b..38f88c7f69edb 100644 --- a/website/versioned_docs/version-v10.0.1/Modern-RelayStore.md +++ b/website/versioned_docs/version-v10.0.1/Modern-RelayStore.md @@ -16,7 +16,6 @@ Table of Contents: The `RecordSourceSelectorProxy` is the type of the `store` that [`updater` functions](./mutations#using-updater-and-optimisticupdater) receive as an argument. The following is the `RecordSourceSelectorProxy` interface: ```javascript - interface RecordSourceSelectorProxy { create(dataID: string, typeName: string): RecordProxy; delete(dataID: string): void; @@ -26,7 +25,6 @@ interface RecordSourceSelectorProxy { getPluralRootField(fieldName: string): ?Array; invalidateStore(): void; } - ``` ### `create(dataID: string, typeName: string): RecordProxy` @@ -36,9 +34,7 @@ Creates a new record in the store given a `dataID` and the `typeName` as defined #### Example ```javascript - const record = store.create(dataID, 'Todo'); - ``` ### `delete(dataID: string): void` @@ -48,9 +44,7 @@ Deletes a record from the store given its `dataID`. #### Example ```javascript - store.delete(dataID); - ``` ### `get(dataID: string): ?RecordProxy` @@ -60,9 +54,7 @@ Retrieves a record from the store given its `dataID`. Returns a [`RecordProxy`]( #### Example ```javascript - const record = store.get(dataID); - ``` ### `getRoot(): RecordProxy` @@ -74,20 +66,16 @@ Returns the [`RecordProxy`](#recordproxy) representing the root of the GraphQL d Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - // Represents root query const root = store.getRoot(); - ``` ### `getRootField(fieldName: string): ?RecordProxy` @@ -99,19 +87,15 @@ Retrieves a root field from the store given the `fieldName`, as defined by the G Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - const viewer = store.getRootField('viewer'); - ``` ### `getPluralRootField(fieldName: string): ?Array` @@ -123,19 +107,15 @@ Retrieves a root field that represents a collection from the store given the `fi Given the GraphQL document: ```graphql - nodes(first: 10) { # ... } - ``` Usage: ```javascript - const nodes = store.getPluralRootField('nodes'); - ``` ### `invalidateStore(): void` @@ -145,15 +125,12 @@ Globally invalidates the Relay store. This will cause any data that was written #### Example ```javascript - store.invalidateStore(); - ``` After global invalidation, any query that is checked before refetching it will be considered stale: ```javascript - environment.check(query) === 'stale' ``` @@ -163,7 +140,6 @@ environment.check(query) === 'stale' The `RecordProxy` serves as an interface to mutate records: ```javascript - interface RecordProxy { copyFieldsFrom(sourceRecord: RecordProxy): void; getDataID(): string; @@ -189,7 +165,6 @@ interface RecordProxy { setValue(value: mixed, name: string, arguments?: ?Object): RecordProxy; invalidateRecord(): void; } - ``` ### `getDataID(): string` @@ -199,9 +174,7 @@ Returns the dataID of the current record. #### Example ```javascript - const id = record.getDataID(); - ``` ### `getType(): string` @@ -211,7 +184,6 @@ Gets the type of the current record, as defined by the GraphQL schema. #### Example ```javascript - const type = user.getType(); // User ``` @@ -225,20 +197,16 @@ Gets the value of a field in the current record given the field name. Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - const name = viewer.getValue('name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. @@ -248,20 +216,16 @@ Optionally, if the field takes arguments, you can pass a bag of `variables`. Given the GraphQL document: ```graphql - viewer { id name(arg: $arg) } - ``` Usage: ```javascript - const name = viewer.getValue('name', {arg: 'value'}); - ``` ### `getLinkedRecord(name: string, arguments?: ?Object): ?RecordProxy` @@ -273,23 +237,19 @@ Retrieves a record associated with the current record given the field name, as d Given the GraphQL document: ```graphql - rootField { viewer { id name } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -299,22 +259,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { viewer(arg: $arg) { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {arg: 'value'}); - ``` ### `getLinkedRecords(name: string, arguments?: ?Object): ?Array` @@ -326,22 +282,18 @@ Retrieves the set of records associated with the current record given the field Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const nodes = rootField.getLinkedRecords('nodes'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -351,22 +303,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { nodes(first: $count) { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {count: 10}); - ``` ### `getOrCreateLinkedRecord(name: string, typeName: string, arguments?: ?Object)` @@ -378,19 +326,16 @@ Retrieves the a record associated with the current record given the field name, Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = rootField.getOrCreateLinkedRecord('viewer', 'User'); // Will create if it doesn't exist @@ -405,28 +350,22 @@ Mutates the current record by setting a new value on the specified field. Return Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - viewer.setValue('New Name', 'name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. ```javascript - viewer.setValue('New Name', 'name', {arg: 'value'}); - ``` ### `copyFieldsFrom(sourceRecord: RecordProxy): void` @@ -436,7 +375,6 @@ Mutates the current record by copying the fields over from the passed in record #### Example ```javascript - const record = store.get(id1); const otherRecord = store.get(id2); record.copyFieldsFrom(otherRecord); // Mutates `record` @@ -452,19 +390,16 @@ Mutates the current record by setting a new linked record on the given the field Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = store.create(/* ... */)'' rootField.setLinkedRecord(newViewer, 'viewer'); // @@ -482,19 +417,16 @@ Mutates the current record by setting a new set of linked records on the given t Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newNode = store.create(/* ... */); const newNodes = [...rootField.getLinkedRecords('nodes'), newNode]; @@ -511,16 +443,13 @@ Invalidates the record. This will cause any query that references this record to #### Example ```javascript - const record = store.get('4'); record.invalidateRecord(); - ``` After invalidating a record, any query that references the invalidated record and that is checked before refetching it will be considered stale: ```javascript - environment.check(query) === 'stale' ``` @@ -530,7 +459,6 @@ environment.check(query) === 'stale' `ConnectionHandler` is a utility module exposed by `relay-runtime` that aids in the manipulation of connections. `ConnectionHandler` exposes the following interface: ```javascript - interface ConnectionHandler { getConnection( record: RecordProxy, @@ -555,7 +483,6 @@ interface ConnectionHandler { ): void, deleteNode(connection: RecordProxy, nodeID: string): void } - ``` ### `getConnection(record: RecordProxy, key: string, filters?: ?Object)` @@ -565,7 +492,6 @@ Given a record and a connection key, and optionally a set of filters, `getConnec First, let's take a look at a plain connection: ```graphql - fragment FriendsFragment on User { friends(first: 10) { edges { @@ -575,26 +501,22 @@ fragment FriendsFragment on User { } } } - ``` Accessing a plain connection field like this is the same as other regular field: ```javascript - // The `friends` connection record can be accessed with: const user = store.get(userID); const friends = user && user.getLinkedRecord('friends'); // Access fields on the connection: const edges = friends && friends.getLinkedRecords('edges'); - ``` In a [pagination container](./pagination-container), we usually annotate the actual connection field with `@connection` to tell Relay which part needs to be paginated: ```graphql - fragment FriendsFragment on User { friends(first: 10, orderby: "firstname") @connection( key: "FriendsFragment_friends", @@ -606,7 +528,6 @@ fragment FriendsFragment on User { } } } - ``` For connections like the above, `ConnectionHandler` helps us find the record: @@ -624,7 +545,6 @@ const friends = ConnectionHandler.getConnection( ); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` ### Edge creation and insertion @@ -654,7 +574,6 @@ ConnectionHandler.insertEdgeAfter(friends, edge); // No cursor provided, Insert the edge at the front: ConnectionHandler.insertEdgeBefore(friends, edge); - ``` ### `deleteNode(connection: RecordProxy, nodeID: string): void` @@ -668,5 +587,4 @@ Given a connection, deletes any edges whose id matches the given id. const user = store.get(userID); const friends = ConnectionHandler.getConnection(user, 'friends'); ConnectionHandler.deleteNode(friends, idToDelete); - ``` diff --git a/website/versioned_docs/version-v10.0.1/Modern-Subscriptions.md b/website/versioned_docs/version-v10.0.1/Modern-Subscriptions.md index 671b28f684403..85ade0f34c511 100644 --- a/website/versioned_docs/version-v10.0.1/Modern-Subscriptions.md +++ b/website/versioned_docs/version-v10.0.1/Modern-Subscriptions.md @@ -6,7 +6,6 @@ original_id: subscriptions Relay exposes the following APIs to create subscriptions. ```javascript - import { requestSubscription } from 'react-relay'; type Variables = {[name: string]: any}; @@ -28,7 +27,6 @@ requestSubscription( cacheConfig?: CacheConfig, }, ) => Disposable; - ``` The function returns a `Disposable` on which you could call `dispose()` to cancel the refetch. @@ -55,7 +53,6 @@ appropriate when you are only changing the properties of existing records that can be identified by their `id`: ```javascript - import { requestSubscription, graphql, @@ -89,7 +86,6 @@ requestSubscription( onError: error => console.error(error), } ); - ``` # Configure Network @@ -97,7 +93,6 @@ requestSubscription( You will need to Configure your [Network](./network-layer) to handle subscriptions. The below example uses [subscriptions-transport-ws](https://github.com/apollographql/subscriptions-transport-ws): ```javascript - import { ... Network, @@ -134,7 +129,6 @@ Relay's in-memory cache when each subscription response is received. To do so, pass an `updater` function: ```javascript - import { ConnectionHandler } from 'relay-runtime'; requestSubscription( @@ -160,5 +154,4 @@ requestSubscription( }, }, ); - ``` diff --git a/website/versioned_docs/version-v10.0.1/Modern-TestingRelayComponents.md b/website/versioned_docs/version-v10.0.1/Modern-TestingRelayComponents.md index da8f520bd7917..91003cab931f2 100644 --- a/website/versioned_docs/version-v10.0.1/Modern-TestingRelayComponents.md +++ b/website/versioned_docs/version-v10.0.1/Modern-TestingRelayComponents.md @@ -65,7 +65,6 @@ MockPayloadGenerator may drastically simplify the process of creating and mainta Example of a simple Mock Resolver: ```javascript - { ID() { // Return mock value for a scalar filed with type ID @@ -76,13 +75,11 @@ Example of a simple Mock Resolver: return "Lorem Ipsum" } } - ``` It is possible to define more resolvers for Object types ```javascript - { // This will be the default values for User object in the query response User() { @@ -95,7 +92,6 @@ It is possible to define more resolvers for Object types }; }, } - ``` ### Mock Resolver Context @@ -103,7 +99,6 @@ It is possible to define more resolvers for Object types The first argument of the MockResolver is the object that contains Mock Resolver Context. It is possible to return dynamic values from mock resolvers based on the context - for instance, name or alias of the field, a path in the selection, arguments, or parent type. ```javascript - { String(context) { if (context.name === 'zip') { @@ -117,7 +112,6 @@ The first argument of the MockResolver is the object that contains Mock Resolver } } } - ``` ### ID Generation @@ -125,14 +119,12 @@ The first argument of the MockResolver is the object that contains Mock Resolver The second argument of the Mock Resolver its a function that will generate a sequence of integers, useful to generate unique ids in the tests ```javascript - { // will generate strings "my-id-1", "my-id-2", etc. ID(_, generateId) { return `my-id-${generateId()}`; }, } - ``` ### @relay_test_operation @@ -142,7 +134,6 @@ Most of GraphQL type information for a specific field in the selection is not av Operation with the @relay_test_operation directive will have additional metadata that will contain GraphQL type info for fields in the operation's selection. And it will improve the quality of the generated data. You also will be able to define Mock resolvers for Scalar (not only ID and String) and Abstract types: ```javascript - { Float() { return 123.456; @@ -160,7 +151,6 @@ Operation with the @relay_test_operation directive will have additional metadata }; } } - ``` ## Examples @@ -170,7 +160,6 @@ Operation with the @relay_test_operation directive will have additional metadata Using `createMockEnvironment` and `MockPayloadGenerator` allows writing concise tests for components that are using Relay Containers and Renderers. Both those modules can be imported from `relay-test-utils` ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { @@ -223,7 +212,6 @@ test('Error State', () => { renderer.root.find(item => (item.props.testID = 'errorMessage')), ).toBeDefined(); }); - ``` ### Fragment Container Tests @@ -231,7 +219,6 @@ test('Error State', () => { Essentially, in the example above will `resolveMostRecentOperation` will generate data for all child fragment containers (pagination, refetch). But, usually the Root Components container may have many child fragment components and you may want to exercise a specific Fragment Container. The solution for that would be to wrap your fragment container with the QueryRenderer that renders a Query that's spreads fragments from your fragment container. ```javascript - test('Fragment Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -262,7 +249,6 @@ test('Fragment Container', () => { expect(renderer).toMatchSnapshot(); }); - ``` ### Pagination Container Test @@ -270,7 +256,6 @@ test('Fragment Container', () => { Essentially, tests for Pagination container are not different from Fragment Container tests. But we can do more here, we can actually see how the pagination works - we can assert the behavior of our components when performing pagination (load more, refetch). ```javascript - // Pagination Example test('Pagination Container', () => { const environment = createMockEnvironment(); @@ -344,7 +329,6 @@ test('Pagination Container', () => { We can use similar approach here with wrapping container with Query Renderer. And for the sake of completeness, we will add example here: ```javascript - test('Refetch Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -386,7 +370,6 @@ test('Refetch Container', () => { ); // expect(renderer).toMatchSnapshot(); }); - ``` ### Mutations @@ -394,7 +377,6 @@ test('Refetch Container', () => { Mutations itself are operations so we can test them independently (unit-test) for specific mutation, or in combination with the view from which this mutation is called. ```javascript - // Say, you have a mutation function function sendMutation(environment, onCompleted, onError, variables) commitMutation(environment, { @@ -417,7 +399,6 @@ test('it should send mutation', () => { ); expect(onCompleted).toBeCalled(); }); - ``` ### Subscription @@ -425,7 +406,6 @@ test('it should send mutation', () => { We can test subscription in a similar way we test mutations ```javascript - // Example subscribe function function subscribe(environment, onNext, onError, variables) requestSubscription(environment, { @@ -448,7 +428,6 @@ test('it should subscribe', () => { ); expect(onNext).toBeCalled(); }); - ``` ### Example with `queueOperationResolver` @@ -456,7 +435,6 @@ test('it should subscribe', () => { With `queueOpeararionResolver` it possible to define responses for operations that will be executed on the environment ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { diff --git a/website/versioned_docs/version-v10.0.1/Modern-TypeEmission.md b/website/versioned_docs/version-v10.0.1/Modern-TypeEmission.md index 63614b869a322..4ff63e4a7d81b 100644 --- a/website/versioned_docs/version-v10.0.1/Modern-TypeEmission.md +++ b/website/versioned_docs/version-v10.0.1/Modern-TypeEmission.md @@ -16,7 +16,6 @@ In this example the emitted type-information would require the variables object #### Flow ```javascript - /** * export type ExampleQueryVariables = {| * +artistID: string @@ -44,7 +43,6 @@ const variables: ExampleQueryVariables = { #### TypeScript ```javascript - /** * export type ExampleQueryVariables = { * readonly artistID: string @@ -79,7 +77,6 @@ In this example the emitted type-information describes the response data availab #### Flow ```javascript - /** * export type ExampleQueryResponse = {| * +artist: ?{| @@ -110,7 +107,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * export type ExampleQueryResponse = { * readonly artist?: { @@ -146,7 +142,6 @@ Similarly, in this example the emitted type-information describes the prop data #### Flow ```javascript - /** * export type ExampleFragment_artist = {| * +name: string @@ -172,7 +167,6 @@ export const ExampleFragment = createFragmentContainer( #### TypeScript ```javascript - /** * export type ExampleFragment_artist = { * readonly name: string @@ -206,7 +200,6 @@ Consider a component that composes the above fragment container example. In this #### Flow ```javascript - /** * import type { FragmentReference } from "relay-runtime"; * declare export opaque type ExampleFragment_artist$ref: FragmentReference; @@ -250,7 +243,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * declare const _ExampleFragment_artist$ref: unique symbol; * export type ExampleFragment_artist$ref = typeof _ExampleFragment_artist$ref; @@ -315,7 +307,6 @@ $ relay-compiler --artifactDirectory ./src/__generated__ […] ["relay", { "artifactDirectory": "./src/__generated__" }] ] } - ``` It is recommended to alias this directory in your module resolution configuration such that you don’t need to specify relative paths in your source files. This is what is also done in the above examples, where artifacts are imported from a `__generated__` alias, rather than relative paths like `../../../../__generated__`. diff --git a/website/versioned_docs/version-v10.0.1/Modern-UpgradingSetVariables.md b/website/versioned_docs/version-v10.0.1/Modern-UpgradingSetVariables.md index d5b086fafce20..ff73feec04f8b 100644 --- a/website/versioned_docs/version-v10.0.1/Modern-UpgradingSetVariables.md +++ b/website/versioned_docs/version-v10.0.1/Modern-UpgradingSetVariables.md @@ -36,7 +36,6 @@ fragment on User { # ... } } - ``` This should be upgraded to use a [`PaginationContainer`](./pagination-container). @@ -61,7 +60,6 @@ fragment on User { # ... } } - ``` This can be upgraded by using a [`RefetchContainer`](./refetch-container) which allows you to specify the exact query to use to fetch the new data. @@ -86,7 +84,6 @@ fragment on FeedbackTarget { # ... } } - ``` This can be upgraded by conditionally rendering a [`QueryRenderer`](./query-renderer) which will load the data once it is rendered. The code overhead of doing this is dramatically reduced with the new API. diff --git a/website/versioned_docs/version-v10.0.1/Modern-fetchQuery.md b/website/versioned_docs/version-v10.0.1/Modern-fetchQuery.md index 2e9461ad527bd..c1a06ab7d2493 100644 --- a/website/versioned_docs/version-v10.0.1/Modern-fetchQuery.md +++ b/website/versioned_docs/version-v10.0.1/Modern-fetchQuery.md @@ -6,7 +6,6 @@ original_id: fetch-query You can use the `fetchQuery` function to imperatively make GraphQL Requests. This is useful for cases where you want to make requests outside of React but still utilize the Relay store and network layer. ```javascript - import {fetchQuery, graphql} from 'relay-runtime'; const query = graphql` @@ -25,7 +24,6 @@ fetchQuery(environment, query, variables) .then(data => { // access the graphql response }); - ``` ## Arguments diff --git a/website/versioned_docs/version-v10.0.1/PrinciplesAndArchitecture-Compiler.md b/website/versioned_docs/version-v10.0.1/PrinciplesAndArchitecture-Compiler.md index c195491682b1f..fcd0490cb724f 100644 --- a/website/versioned_docs/version-v10.0.1/PrinciplesAndArchitecture-Compiler.md +++ b/website/versioned_docs/version-v10.0.1/PrinciplesAndArchitecture-Compiler.md @@ -74,7 +74,6 @@ foo { # type FooType foo { id } - ``` - `SkipRedundantNodeTransform`: A more advanced version of flattening, this eliminates more complex cases of field duplication such as when a field is fetched both unconditionally and conditionally, or is fetched by two different sub-fragments. For example: @@ -97,7 +96,6 @@ foo { id } } - ``` - `GenerateRequisiteFieldTransform`: This optional, Relay-specific transform inserts `id` fields for globally identifiable objects and `__typename` fields wherever the type cannot be statically determined (e.g. for unions). diff --git a/website/versioned_docs/version-v10.0.1/PrinciplesAndArchitecture-Runtime.md b/website/versioned_docs/version-v10.0.1/PrinciplesAndArchitecture-Runtime.md index 9491d290c146f..e9221631a701d 100644 --- a/website/versioned_docs/version-v10.0.1/PrinciplesAndArchitecture-Runtime.md +++ b/website/versioned_docs/version-v10.0.1/PrinciplesAndArchitecture-Runtime.md @@ -77,7 +77,6 @@ RecordSource { city: 'Seattle', } } - ``` [1] Note that GraphQL itself does not impose this constraint, and Relay Runtime may also be used for schemas that do not conform to it. For example, both systems can be used to query a single denormalized table. However, many of the features that Relay Runtime provides, such as caching and normalization, work best when the data is represented as a normalized graph with stable identities for discrete pieces of information. diff --git a/website/versioned_docs/version-v10.0.1/PrinciplesAndArchitecture-ThinkingInGraphQL.md b/website/versioned_docs/version-v10.0.1/PrinciplesAndArchitecture-ThinkingInGraphQL.md index a8842ae084922..9ff8a7840df90 100644 --- a/website/versioned_docs/version-v10.0.1/PrinciplesAndArchitecture-ThinkingInGraphQL.md +++ b/website/versioned_docs/version-v10.0.1/PrinciplesAndArchitecture-ThinkingInGraphQL.md @@ -12,7 +12,6 @@ In this article we'll explore what it means to build a GraphQL client framework Imagine we have a simple application that fetches a list of stories, and some details about each one. Here's how that might look in resource-oriented REST: ```javascript - // Fetch the list of story IDs but not their details: rest.get('/stories').then(stories => // This resolves to a list of items with linked resources: @@ -25,13 +24,11 @@ rest.get('/stories').then(stories => // `[ { id: "...", text: "..." } ]` console.log(stories); }); - ``` Note that this approach requires _n+1_ requests to the server: 1 to fetch the list, and _n_ to fetch each item. With GraphQL we can fetch the same data in a single network request to the server (without creating a custom endpoint that we'd then have to maintain): ```javascript - graphql.get(`query { stories { id, text } }`).then( stories => { // A list of story items: @@ -39,7 +36,6 @@ graphql.get(`query { stories { id, text } }`).then( console.log(stories); } ); - ``` So far we're just using GraphQL as a more efficient version of typical REST approaches. Note two important benefits in the GraphQL version: @@ -56,7 +52,6 @@ Repeatedly refetching information from the server can get quite slow. For exampl In a resource-oriented REST system, we can maintain a **response cache** based on URIs: ```javascript - var _cache = new Map(); rest.get = uri => { if (!_cache.has(uri)) { @@ -64,13 +59,11 @@ rest.get = uri => { } return _cache.get(uri); }; - ``` Response-caching can also be applied to GraphQL. A basic approach would work similarly to the REST version. The text of the query itself can be used as a cache key: ```javascript - var _cache = new Map(); graphql.get = queryText => { if (!_cache.has(queryText)) { @@ -78,7 +71,6 @@ graphql.get = queryText => { } return _cache.get(queryText); }; - ``` Now, requests for previously cached data can be answered immediately without making a network request. This is a practical approach to improving the perceived performance of an application. However, this method of caching can cause problems with data consistency. @@ -90,7 +82,6 @@ With GraphQL it is very common for the results of multiple queries to overlap. H ``` query { stories { id, text, likeCount } } - ``` and then later refetch one of the stories whose `likeCount` has since been incremented: @@ -98,7 +89,6 @@ and then later refetch one of the stories whose `likeCount` has since been incre ``` query { story(id: "123") { id, text, likeCount } } - ``` We'll now see different `likeCount`s depending on how the story is accessed. A view that uses the first query will see an outdated count, while a view using the second query will see the updated count. @@ -119,7 +109,6 @@ query { } } } - ``` And here's a possible response: @@ -134,13 +123,11 @@ query: { } } } - ``` Although the response is hierarchical, we'll cache it by flattening all the records. Here is an example of how Relay would cache this query response: ```javascript - Map { // `story(id: "1")` 1: Map { @@ -152,7 +139,6 @@ Map { name: 'Jan', }, }; - ``` This is only a simple example: in reality the cache must handle one-to-many associations and pagination (among other things). @@ -182,7 +168,6 @@ The first query was for a list of stories: ``` query { stories { id, text, likeCount } } - ``` With a normalized response cache, a record would be created for each story in the list. The `stories` field would store links to each of these records. @@ -192,7 +177,6 @@ The second query refetched the information for one of those stories: ``` query { story(id: "123") { id, text, likeCount } } - ``` When this response is normalized, Relay can detect that this result overlaps with existing data based on its `id`. Rather than create a new record, Relay will update the existing `123` record. The new `likeCount` is therefore available to _both_ queries, as well as any other query that might reference this story. @@ -215,7 +199,6 @@ query { } } } - ``` After initially fetching this story our cache might be as follows. Note that the story and comment both link to the same record as `author`: @@ -242,7 +225,6 @@ Map { author: Link(2), }, } - ``` The author of this story also commented on it — quite common. Now imagine that some other view fetches new information about the author, and her profile photo has changed to a new URI. Here's the _only_ part of our cached data that changes: @@ -256,7 +238,6 @@ Map { photo: 'http://.../photo2.jpg', }, } - ``` The value of the `photo` field has changed; and therefore the record `2` has also changed. And that's it. Nothing else in the _cache_ is affected. But clearly our _view_ needs to reflect the update: both instances of the author in the UI (as story author and comment author) need to show the new photo. @@ -273,7 +254,6 @@ ImmutableMap { }, 3: ImmutableMap // same as before } - ``` If we replace `2` with a new immutable record, we'll also get a new immutable instance of the cache object. However, records `1` and `3` are untouched. Because the data is normalized, we can't tell that `story`'s contents have changed just by looking at the `story` record alone. @@ -299,7 +279,6 @@ mutation StoryLike($storyID: String) { likeCount } } - ``` Notice that we're querying for data that _may_ have changed as a result of the mutation. An obvious question is: why can't the server just tell us what changed? The answer is: it's complicated. GraphQL abstracts over _any_ data storage layer (or an aggregation of multiple sources), and works with any programming language. Furthermore, the goal of GraphQL is to provide data in a form that is useful to product developers building a view. diff --git a/website/versioned_docs/version-v10.0.1/PrinciplesAndArchitecture-ThinkingInRelay.md b/website/versioned_docs/version-v10.0.1/PrinciplesAndArchitecture-ThinkingInRelay.md index e61f3fd21c933..62b1914ef3ff9 100644 --- a/website/versioned_docs/version-v10.0.1/PrinciplesAndArchitecture-ThinkingInRelay.md +++ b/website/versioned_docs/version-v10.0.1/PrinciplesAndArchitecture-ThinkingInRelay.md @@ -30,13 +30,11 @@ fragment Story_story on Story { photo } } - ``` And this fragment can then be used to define the Story container: ```javascript - const {createFragmentContainer, graphql} = require('react-relay'); // Plain React component. @@ -64,7 +62,6 @@ const StoryContainer = createFragmentContainer(Story, { In React, rendering a view requires two inputs: the _component_ to render, and a _root_ DOM (UI) node to render into. Rendering Relay containers is similar: we need a _container_ to render, and a _root_ in the graph from which to start our query. We also must ensure that the queries for the container are executed and may want to show a loading indicator while data is being fetched. Similar to `ReactDOM.render(component, domNode)`, Relay provides `` for this purpose. The `query` and `variables` define what data to fetch and `render` defines what to render. Here's how we might render ``: ```javascript - ReactDOM.render( { ); } } - ``` The above code is doing something very similar to our [previous example](#rendering-graphql-queries). However, we are now passing a `$userID` variable to the GraphQL query via the `variables` prop. This has a couple of important implications: @@ -228,7 +216,6 @@ Now that we know how to define and fetch queries, let's actually start building First, let's start at the bottom. Suppose that we want to render a component that simply displays a given todo item's text and completed state: ```javascript - // Todo.js import React from 'react'; @@ -258,7 +245,6 @@ export default class Todo extends React.Component { ); } } - ``` From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L112), we know that we can query this data on the `Todo` type. However, we don't want to have to send a separate query for each todo item; that would defeat the purpose of using GraphQL over a traditional REST API. We could manually query for these fields directly in our `QueryRenderer` query, but that would hurt re-usability: what if we want to query the same set of fields as part of a different query? Additionally, we wouldn't know which component needs the data we're querying, which is a problem Relay directly tries to address. @@ -266,18 +252,15 @@ From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/dat Instead, we can define a reusable [Fragment](http://graphql.org/learn/queries/#fragments), which allows us to define a set of fields on a type and reuse them within our queries wherever we need to: ```graphql - fragment TodoItemFragment on Todo { complete text } - ``` Our component can then use this fragment to declare its data dependency on the `Todo` GraphQL type: ```javascript - // Todo.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -340,7 +323,6 @@ Before proceeding, don't forget to run the Relay Compiler with `yarn relay`. Given that [Fragment Containers](./fragment-container) are just React components, we can compose them as such. We can even re-use fragment containers within other fragment containers. As an example, let's see how we would define a `TodoList` component that just renders a list of todo items, and whether all have been completed or not: ```javascript - // TodoList.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -401,7 +383,6 @@ export default createFragmentContainer( `, }, ); - ``` As with the first fragment container we defined, `TodoList` declares its data dependencies via a fragment. However, this component additionally re-uses the fragment previously defined by the `Todo` component, and passes the appropriate data when rendering the child `Todo` components (a.k.a. fragment containers). @@ -416,7 +397,6 @@ fragment containers do not directly fetch data. Instead, containers declare a sp A `QueryRenderer` rendering these fragment containers could look like the following: ```javascript - // ViewerTodoList.js import React from 'react'; import {graphql, QueryRenderer} from 'react-relay'; @@ -457,7 +437,6 @@ export default class ViewerTodoList extends React.Component { ); } } - ``` Check out our docs for [Fragment Containers](./fragment-container) for more details, and our guides on [Refetch](./refetch-container) and [Pagination](./pagination-container) for more advanced usage of containers. @@ -469,7 +448,6 @@ Now that we know how to query for and render data, let's move on to changing our From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L35), we know that we have some mutations available to us, so let's start by writing a mutation to change the `complete` status of a given todo item (i.e. mark or unmark it as done): ```graphql - mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { changeTodoStatus(input: $input) { todo { @@ -478,7 +456,6 @@ mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { } } } - ``` This mutation allows us to query back some data as a [result of the mutation](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L18), so we're going to query for the updated `complete` status on the todo item. @@ -486,7 +463,6 @@ This mutation allows us to query back some data as a [result of the mutation](ht In order to execute this mutation in Relay, we're going to write a new mutation using Relay's `commitMutation` api: ```javascript - // ChangeTodoStatusMutation.js import {graphql, commitMutation} from 'react-relay'; @@ -520,7 +496,6 @@ function commit( } export default {commit}; - ``` Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mutation to the server and, in our case, upon receiving a response it will automatically update the local data store with the latest data from the server. This also means that upon receiving the response, Relay will ensure that any components (i.e. containers) that depend on the updated data are re-rendered. @@ -528,7 +503,6 @@ Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mut In order to actually use this mutation in our component, we could update our `Todo` component in the following way: ```javascript - // Todo.js // ... @@ -562,7 +536,6 @@ In order to make the experience better, we can configure our mutation to do an o In Relay, there's a couple of options we can pass to `commitMutation` to enable optimistic updates. Let's see what that would look like in our `ChangeTodoStatusMutation`: ```javascript - // ChangeTodoStatusMutation.js // ... @@ -597,7 +570,6 @@ function commit( } export default {commit}; - ``` In the simplest case above, we just need to pass an `optimisticResponse` option, which should refer to an object having the same shape as the mutation response payload. When we pass this option, Relay will know to immediately update our local data with the optimistic response, and then update it with the actual server response or roll it back if an error occurs. diff --git a/website/versioned_docs/version-v10.1.0/Modern-ConvertingMutations.md b/website/versioned_docs/version-v10.1.0/Modern-ConvertingMutations.md index 08ad2e998cb2d..8f4bdc1d8e0d2 100644 --- a/website/versioned_docs/version-v10.1.0/Modern-ConvertingMutations.md +++ b/website/versioned_docs/version-v10.1.0/Modern-ConvertingMutations.md @@ -12,19 +12,16 @@ FatQueries in Relay Classic mutations was a concept that was confusing for a num Example of existing fat query: ```javascript - RelayClassic.QL` fragment on MarkReadNotificationResponsePayload @relay(pattern: true) { notification } `; - ``` Example of converted mutation query: ```javascript - graphql` mutation MarkReadNotificationMutation( $input: MarkReadNotificationData! @@ -37,7 +34,6 @@ graphql` } } `; - ``` ## Migrating Configs @@ -67,7 +63,6 @@ This is no longer needed in Compatibility Mode for neither environments. Simply Take this example of a simple mutation in Relay Classic: ```javascript - class LikeStoryMutation extends RelayClassic.Mutation { getMutation() { return RelayClassic.QL`mutation {likeStory}`; @@ -106,7 +101,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { `, }; } - ``` ### Converting `getMutation()` and `getFatQuery()` @@ -114,7 +108,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { We combine these two into a regular GraphQL mutation, which list out specific fields that needs to be updated. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story(data: $input) { @@ -126,7 +119,6 @@ const mutation = graphql` } } `; - ``` ### Converting `getConfigs()` @@ -138,13 +130,11 @@ As specified above, `FIELDS_CHANGE` configs can be omitted. To convert `getVariables()`, we take the return value from the original function and wrap it in an object that contains a property that matches the variable name for the mutation. In this case, the mutation has a `input` variable that is of type `LikeStoryData`. ```javascript - const variables = { input: { storyID: args.storyID } } - ``` ### Final Result @@ -152,7 +142,6 @@ const variables = { As you can see, our resulting mutation is a lot simpler and more like regular GraphQL than the Relay Classic version we started out with. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story { @@ -178,7 +167,6 @@ function commit(environment: CompatEnvironment, args) { variables, }); } - ``` See [Mutation](./mutations) for additional options on `commitMutation` for more complex mutations. diff --git a/website/versioned_docs/version-v10.1.0/Modern-FragmentContainer.md b/website/versioned_docs/version-v10.1.0/Modern-FragmentContainer.md index 423f446cbb054..6a40bbcfb5d0a 100644 --- a/website/versioned_docs/version-v10.1.0/Modern-FragmentContainer.md +++ b/website/versioned_docs/version-v10.1.0/Modern-FragmentContainer.md @@ -17,12 +17,10 @@ Table of Contents: `createFragmentContainer` has the following signature: ```javascript - createFragmentContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, ): ReactComponentClass; - ``` ### Arguments @@ -43,7 +41,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -58,7 +55,6 @@ To start, let's build the plain React version of a hypothetical `` c Here's a basic implementation of `` that ignores styling in order to highlight the functionality: ```javascript - // TodoItem.js class TodoItem extends React.Component { render() { @@ -78,7 +74,6 @@ class TodoItem extends React.Component { ); } } - ``` ### Data Dependencies With GraphQL @@ -86,7 +81,6 @@ class TodoItem extends React.Component { In Relay, data dependencies are described using [GraphQL](https://github.com/facebook/graphql). For ``, the dependency can be expressed as follows. Note that this exactly matches the shape that the component expected for the `item` prop. ```javascript - graphql` # This fragment only applies to objects of type 'Todo'. fragment TodoItem_item on Todo { @@ -102,7 +96,6 @@ graphql` Given the plain React component and a GraphQL fragment, we can now define a Fragment Container to specify this component's data requirements. Let's look at the code first and then see what's happening: ```javascript - // TodoItem.js import {createFragmentContainer, graphql} from 'react-relay'; @@ -120,7 +113,6 @@ export default createFragmentContainer(TodoItem, { } `, }); - ``` ## Container Composition @@ -134,7 +126,6 @@ Let's explore how this works via a `` component that composes the `< View composition is _exactly_ what you're used to — Relay containers are just standard React components. Here's the `` component: ```javascript - class TodoList extends React.Component { render() { // Expects a `list` with a string `title`, as well as the information @@ -151,7 +142,6 @@ class TodoList extends React.Component { ); } } - ``` ### Composing Fragments @@ -159,7 +149,6 @@ class TodoList extends React.Component { Fragment composition works similarly — a parent container's fragment composes the fragment for each of its children. In this case, `` needs to fetch information about the `Todo`s that are required by ``. ```javascript - class TodoList extends React.Component // as above export default createFragmentContainer(TodoList, { @@ -176,7 +165,6 @@ export default createFragmentContainer(TodoList, { } `, }); - ``` Note that when composing fragments, the type of the composed fragment must match the field on the parent in which it is embedded. For example, it wouldn't make sense to embed a fragment of type `Story` into a parent's field of type `User`. Relay and GraphQL will provide helpful error messages if you get this wrong (and if they aren't helpful, let us know!). @@ -190,7 +178,6 @@ When defining a fragment, you can use the [`@argumentDefinitions`](./graphql-in- For example, let's redefine our `TodoList_list` fragment to take some arguments using `@argumentDefinitions`: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -200,7 +187,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` Any arguments defined inside `@argumentDefinitions` will be local variables available inside the fragment's scope. However, a fragment can also reference global variables that were defined in the root query. @@ -212,11 +198,9 @@ In order to pass arguments to a fragment that has `@argumentDefinitions`, you ne Following our `TodoList_list` example, we would pass arguments to the fragment like so: ```graphql - query TodoListQuery($count: Int, $userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` ## Rendering Containers diff --git a/website/versioned_docs/version-v10.1.0/Modern-GraphQLInRelay.md b/website/versioned_docs/version-v10.1.0/Modern-GraphQLInRelay.md index c4dc8f3463e53..715b119492cc7 100644 --- a/website/versioned_docs/version-v10.1.0/Modern-GraphQLInRelay.md +++ b/website/versioned_docs/version-v10.1.0/Modern-GraphQLInRelay.md @@ -14,7 +14,6 @@ Table of Contents: The `graphql` template tag provided by Relay serves as the mechanism to write queries, fragments, mutations or subscriptions in the [GraphQL](http://graphql.org/learn/) language. For example: ```javascript - import {graphql} from 'react-relay'; graphql` @@ -24,7 +23,6 @@ graphql` } } `; - ``` The result of using the `graphql` template tag is a `GraphQLTaggedNode`; a runtime representation of the GraphQL document which can be used to define [Query Renderers](./query-renderer), [Fragment Containers](./fragment-container), [Refetch Containers](./refetch-container), [Pagination Containers](./pagination-container), etc. @@ -42,11 +40,9 @@ Relay uses directives to add additional information to GraphQL documents, which `@arguments` is a directive used to pass arguments to a fragment that was defined using [`@argumentDefinitions`](#argumentdefinitions). For example: ```graphql - query TodoListQuery($userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -56,7 +52,6 @@ See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fr `@argumentDefinitions` is a directive used to specify arguments taken by a fragment. For example: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -66,7 +61,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -80,7 +74,6 @@ When using the [Pagination Container](./pagination-container), Relay expects con When defining a fragment for use with a Fragment container, you can use the `@relay(plural: true)` directive to indicate that container expects the prop for that fragment to be a list of items instead of a single item. A query or parent that spreads a `@relay(plural: true)` fragment should do so within a plural field (ie a field backed by a [GraphQL list](http://graphql.org/learn/schema/#lists-and-non-null). For example: ```javascript - // Plural fragment definition graphql` fragment TodoItems_items on TodoItem @relay(plural: true) { @@ -95,7 +88,6 @@ fragment TodoApp_app on App { ...TodoItem_items } } - ``` ### `@inline` @@ -107,7 +99,6 @@ Non-React functions can also take advantage of data masking. A fragment can be d In the example below, the function `processItemData` is called from a React component. It requires an item object with a specific set of fields. All React components that use this function should spread the `processItemData_item` fragment to ensure all of the correct item data is loaded for this function. ```javascript - import {graphql, readInlineData} from 'react-relay'; // non-React function called from React @@ -127,11 +118,9 @@ function processItemData(itemRef) { creatorName: item.creator.name }); } - ``` ```javascript - // React Component function MyComponent({item}) { function handleClick() { @@ -151,7 +140,6 @@ export default createFragmentContainer(MyComponent, { } ` }); - ``` ### `@relay(mask: Boolean)` @@ -169,7 +157,6 @@ Keep in mind that it is typically considered an **anti-pattern** to create a sin In the example below, the `user` prop will include the data for `id` and `name` fields wherever `...Component_internUser` is included, instead of Relay's normal behavior to mask those fields: ```javascript - graphql` fragment Component_internUser on InternUser @relay(mask: false) { id @@ -197,7 +184,6 @@ export default createFragmentContainer( } `, ); - ``` ## Relay Compiler @@ -207,7 +193,6 @@ Relay uses the Relay Compiler to convert [`graphql`](#graphql) literals into gen A query like the following: ```javascript - graphql` fragment MyComponent on Type { field @@ -228,12 +213,10 @@ Relay Compiler supports the use of **persisted queries**, in which each version Persisted queries can be enabled by instructing Relay Compiler to emit metadata about each query, mutation, and subscription into a JSON file. The generated file will contain a mapping of query identifiers to query text, which you can then save to your server. To enable persisted queries, use the `--persist-output` flag to the compiler: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` Relay Compiler will then create the id => query text mapping in the path you specify. You can then use this complete @@ -250,7 +233,6 @@ See our relay-compiler section in our [Installation and Setup guide](./installat To use the Relay Compiler, you need either a .graphql or .json GraphQL schema file, describing your GraphQL server's API. Typically these files are local representations of a server source of truth and are not edited directly. For example, we might have a `schema.graphql` like: ```graphql - schema { query: Root } @@ -268,7 +250,6 @@ type WordDefinition { text: String image: String } - ``` ### Source files @@ -284,7 +265,6 @@ For example, given the two files: - `src/Components/DictionaryComponent.js` ```javascript - const DictionaryWordFragment = graphql` fragment DictionaryComponent_word on Word { id @@ -306,7 +286,6 @@ For example, given the two files: - `src/Queries/DictionaryQuery.js` ```javascript - const DictionaryQuery = graphql` query DictionaryQuery { dictionary { @@ -330,9 +309,7 @@ Typically you will not need to import your generated definitions. The [Relay Bab However the Relay Compiler also automatically generates [Flow](https://flow.org) types as [type comments](https://flow.org/en/docs/types/comments/). For example, you can import the generated Flow types like so: ```javascript - import type {DictionaryComponent_word} from './__generated__/DictionaryComponent_word.graphql'; - ``` ### Client schema extensions @@ -342,7 +319,6 @@ The Relay Compiler fully supports client-side schema extensions, which allows yo For example, assuming the server schema `./schema.graphql`: ```graphql - schema { query: Root } @@ -350,28 +326,23 @@ schema { type Root { title: String! } - ``` We can create a `./src/clientSchema.graphql` and define a new type called `Setting`: ```graphql - type Setting { name: String! active: Boolean! } - ``` We can then extend existing server types in the client schema `./src/clientSchema.graphql` with our new `Setting` type, like so: ```graphql - extend type Root { settings: [Setting] } - ``` Any fields specified in the client schema, can be fetched from the [Relay Store](./relay-store), by selecting it in a query or fragment. diff --git a/website/versioned_docs/version-v10.1.0/Modern-LocalStateManagement.md b/website/versioned_docs/version-v10.1.0/Modern-LocalStateManagement.md index da71a0dd33246..3ecbf6801f91c 100644 --- a/website/versioned_docs/version-v10.1.0/Modern-LocalStateManagement.md +++ b/website/versioned_docs/version-v10.1.0/Modern-LocalStateManagement.md @@ -24,23 +24,19 @@ It can even be used to extend an existing server schema. For example, we can create a new type called `Note`: ```graphql - type Note { id: ID! title: String body: String } - ``` And then extend the server schema type `User`, with a list of `Note`, called `notes`. ```graphql - extend type User { notes: [Note] } - ``` ## Querying local state @@ -51,7 +47,6 @@ The field can be from the server schema, or it can be schema agnostic, like an i Here, we use a [QueryRenderer](./query-renderer) to get the current `User` via the `viewer` field, along with their id, name and the local list of notes. ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -97,7 +92,6 @@ const Example = (props) => { /> ); } - ``` ## Mutating local state @@ -111,7 +105,6 @@ To build upon the previous example, let's try creating, updating and deleting a ### Create ```javascript - import {commitLocalUpdate} from 'react-relay'; let tempID = 0; @@ -131,7 +124,6 @@ function createUserNote() { user.setLinkedRecords([...userNoteRecords, newNoteRecord], 'notes'); }); } - ``` Note that since this record will be rendered by the `ExampleQuery` in our `QueryRenderer`, the QueryRenderer will automatically retain this data so it isn't garbage collected. @@ -139,7 +131,6 @@ Note that since this record will be rendered by the `ExampleQuery` in our `Query If no component is rendering the local data and you want to manually retain it, you can do so by calling `environment.retain()`: ```javascript - import {createOperationDescriptor, getRequest} from 'relay-runtime'; // Create a query that references that record @@ -166,13 +157,11 @@ const disposable = environment.retain(operation); // Whenever you don't need that data anymore and it's okay for Relay to garbage collect it, // you can dispose of the retain disposable.dispose(); - ``` ### Update ```javascript - import {commitLocalUpdate} from 'react-relay'; function updateUserNote(dataID, body, title) { @@ -183,13 +172,11 @@ function updateUserNote(dataID, body, title) { note.setValue(title, 'title') }); } - ``` ### Delete ```javascript - import {commitLocalUpdate} from 'react-relay'; function deleteUserNote(dataID) { @@ -207,7 +194,6 @@ function deleteUserNote(dataID) { user.setLinkedRecords(newUserNoteRecords, 'notes'); }); } - ``` ## Initial local state @@ -216,7 +202,6 @@ All new client-side schema fields default to `undefined` value. Often however, y You can use an updater function via `commitLocalUpdate` to prime local state. ```javascript - import {commitLocalUpdate} from 'react-relay'; commitLocalUpdate(environment, store => { @@ -225,5 +210,4 @@ commitLocalUpdate(environment, store => { // initialize user notes to an empty array. user.setLinkedRecords([], 'notes'); }); - ``` diff --git a/website/versioned_docs/version-v10.1.0/Modern-MigrationSetup.md b/website/versioned_docs/version-v10.1.0/Modern-MigrationSetup.md index 66f1145357e25..a89c0e178e0e5 100644 --- a/website/versioned_docs/version-v10.1.0/Modern-MigrationSetup.md +++ b/website/versioned_docs/version-v10.1.0/Modern-MigrationSetup.md @@ -13,13 +13,11 @@ With some additional configuration, the `"relay"` babel plugin can also translat Relay Classic `Relay.QL` literals. Most importantly, include a reference to your GraphQL Schema as either a json file or graphql schema file. ```javascript - { "plugins": [ ["relay", {"schema": "path/schema.graphql"}] ] } - ``` ## Set up babel-plugin-relay for "[compatibility mode](./relay-compat)" @@ -29,13 +27,11 @@ literals can be translated to be usable by _both_ runtimes if configured to use compatibility mode: ```javascript - { "plugins": [ ["relay", {"compat": true, "schema": "path/schema.graphql"}] ] } - ``` ## Additional Options @@ -47,7 +43,6 @@ thrown at runtime. When compiling code for production deployment, the plugin can be configured to immediately throw upon encountering a validation problem. The plugin can be further customized for different environments with the following options: ```javascript - { "plugins": [ ["relay", { @@ -56,5 +51,4 @@ When compiling code for production deployment, the plugin can be configured to i }] ] } - ``` diff --git a/website/versioned_docs/version-v10.1.0/Modern-Mutations.md b/website/versioned_docs/version-v10.1.0/Modern-Mutations.md index bc7545a967717..412672f0bf588 100644 --- a/website/versioned_docs/version-v10.1.0/Modern-Mutations.md +++ b/website/versioned_docs/version-v10.1.0/Modern-Mutations.md @@ -17,7 +17,6 @@ Table of Contents: Use `commitMutation` to create and execute mutations. `commitMutation` has the following signature: ```javascript - commitMutation( environment: Environment, config: { @@ -32,7 +31,6 @@ commitMutation( cacheConfig?: CacheConfig, }, ); - ``` ### Arguments @@ -60,7 +58,6 @@ commitMutation( Example of a simple mutation: ```javascript - import {commitMutation, graphql} from 'react-relay'; const mutation = graphql` @@ -92,7 +89,6 @@ function markNotificationAsRead(environment, storyID) { }, ); } - ``` ## Optimistic Updates @@ -100,7 +96,6 @@ function markNotificationAsRead(environment, storyID) { To improve perceived responsiveness, you may wish to perform an "optimistic update", in which the client immediately updates to reflect the anticipated new value even before the response from the server has come back. The simplest way to do this is by providing an `optimisticResponse` and adding it to the `config` that we pass into `commitMutation`: ```javascript - const mutation = graphql` mutation MarkReadNotificationMutation( $storyID: ID! @@ -129,7 +124,6 @@ commitMutation( variables, }, ); - ``` Another way to enable optimistic updates is via the `optimisticUpdater`, which can be used for more complicated update scenarios. Using `optimisticUpdater` is covered in the section [below](#using-updater-and-optimisticupdater). @@ -151,7 +145,6 @@ Given a `deletedIDFieldName`, Relay will remove the node(s) from the store. #### Example ```javascript - const mutation = graphql` mutation DestroyShipMutation($target: ID!) { destroyShip(target: $target) { @@ -169,7 +162,6 @@ const configs = [{ type: 'NODE_DELETE', deletedIDFieldName: 'destroyedShipId', }]; - ``` ### RANGE_ADD @@ -189,7 +181,6 @@ Given a parent, information about the connection, and the name of the newly crea #### Example ```javascript - const mutation = graphql` mutation AddShipMutation($factionID: ID!, $name: String!) { addShip(factionID: $factionID, name: $name) { @@ -220,7 +211,6 @@ function commit(environment, factionID, name) { }], }); } - ``` ### RANGE_DELETE @@ -242,7 +232,6 @@ from the connection but leave the associated record(s) in the store. #### Example ```javascript - const mutation = graphql` mutation RemoveTagMutation($todoID: ID!, $tagID: ID!) { removeTag(todo: $todoID, tag: $tagID) { @@ -269,7 +258,6 @@ function commit(environment, todoID, tagID) { }], }); } - ``` ## Using updater and optimisticUpdater @@ -287,7 +275,6 @@ When you provide these functions, this is roughly what happens during the mutati Here are a quick example of adding a todo item to a Todo list using this [example schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L36): ```javascript - // AddTodoMutation.js import {commitMutation, graphql} from 'react-relay'; import {ConnectionHandler} from 'relay-runtime'; @@ -371,7 +358,6 @@ function commit(environment, text, user) { }, }); } - ``` For details on how to interact with the Relay Store, please refer to our Relay Store [docs](./relay-store). diff --git a/website/versioned_docs/version-v10.1.0/Modern-NetworkLayer.md b/website/versioned_docs/version-v10.1.0/Modern-NetworkLayer.md index 9dddd36d6c235..c9e069b812b01 100644 --- a/website/versioned_docs/version-v10.1.0/Modern-NetworkLayer.md +++ b/website/versioned_docs/version-v10.1.0/Modern-NetworkLayer.md @@ -8,7 +8,6 @@ In order to know how to access your GraphQL server, Relay Modern requires develo Currently the easiest way to create a network layer is via a helper from the `relay-runtime` package: ```javascript - import { Environment, Network, @@ -50,7 +49,6 @@ const environment = new Environment({ }); export default environment; - ``` Note that this is a basic example to help you get started. This example could be extended with additional features such as request/response caching (enabled e.g. when `cacheConfig.force` is false) and uploading form data for mutations (the `uploadables` parameter). @@ -62,7 +60,6 @@ Relay modern makes no assumptions about what to cache and will garbage collect a You have to implement your own cache strategy. A simple solution is to use `QueryResponseCache` (an in-memory cache): ```javascript - import { Environment, Network, @@ -126,7 +123,6 @@ const environment = new Environment({ }); export default environment; - ``` ## Custom open-source implementations diff --git a/website/versioned_docs/version-v10.1.0/Modern-PaginationContainer.md b/website/versioned_docs/version-v10.1.0/Modern-PaginationContainer.md index 6ac3aac8cfb8e..57980d553af9b 100644 --- a/website/versioned_docs/version-v10.1.0/Modern-PaginationContainer.md +++ b/website/versioned_docs/version-v10.1.0/Modern-PaginationContainer.md @@ -24,7 +24,6 @@ However, when [specifying connection fragments](#createpaginationcontainer) for The purpose of the `@connection` directive is to allow Relay to uniquely identify different connections under a parent type. The `@connection` directive takes 2 arguments that help identify the connection: ```graphql - @connection(key: String!, filters: [String]) ``` @@ -37,7 +36,6 @@ The purpose of the `@connection` directive is to allow Relay to uniquely identif Specifying just the `key`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and the value of `$orderBy` (given that no `filters` were provided) @@ -53,13 +51,11 @@ fragment Feed_user on User { } } } - ``` Specifying `key` and `filters`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and /only/ the value of `$searchTerm`, i.e. @@ -77,7 +73,6 @@ fragment Feed_user on User { } } } - ``` ## `createPaginationContainer` @@ -85,7 +80,6 @@ fragment Feed_user on User { `createPaginationContainer` has the following signature: ```javascript - createPaginationContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, @@ -113,7 +107,6 @@ type ConnectionData = { startCursor: ?string, }, }; - ``` ### Arguments @@ -134,7 +127,6 @@ type ConnectionData = { The Component resulting from `createPaginationContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -145,7 +137,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -160,7 +151,6 @@ type Props = { `hasMore` is a function available on the `relay` [prop](#available-props). This function indicates whether there are more pages to fetch from the server or not. ```javascript - hasMore: () => boolean, ``` @@ -170,7 +160,6 @@ hasMore: () => boolean, `isLoading` is a function available on the `relay` [prop](#available-props). This function indicates if a previous call to [`loadMore()`](#loadmore) is still pending. This is convenient for avoiding duplicate load calls. ```javascript - isLoading: () => boolean, ``` @@ -180,7 +169,6 @@ isLoading: () => boolean, `loadMore` is a function available on the `relay` [prop](#available-props). You can call `loadMore()` to fetch more items from the server based on the `connectionConfig` provided to the container. This will return null if there are no more items to fetch, otherwise it will fetch more items and return a Disposable that can be used to cancel the fetch. ```javascript - loadMore( pageSize: number, callback: ?(error: ?Error) => void, @@ -201,7 +189,6 @@ loadMore( `refetchConnection` is a function available on the `relay` [prop](#available-props). You can call `refetchConnection` to restart pagination on a connection from scratch, with optionally a completely new set of variables to pass to the pagination `query`. This is useful for example if you are paginating over a collection based on a userID and the userID changes, you'd want to start paginating over the new collection for the new user. ```javascript - refetchConnection:( totalCount: number, callback: (error: ?Error) => void, @@ -219,7 +206,6 @@ refetchConnection:( ## Pagination Example ```javascript - // Feed.js import {createPaginationContainer, graphql} from 'react-relay'; @@ -314,5 +300,4 @@ module.exports = createPaginationContainer( ` } ); - ``` diff --git a/website/versioned_docs/version-v10.1.0/Modern-PersistedQueries.md b/website/versioned_docs/version-v10.1.0/Modern-PersistedQueries.md index 137cc2e23220c..ec03b69ba09c3 100644 --- a/website/versioned_docs/version-v10.1.0/Modern-PersistedQueries.md +++ b/website/versioned_docs/version-v10.1.0/Modern-PersistedQueries.md @@ -17,12 +17,10 @@ The relay compiler supports persisted queries which is useful because: In your `npm` script in `package.json`, run the relay compiler using the `--persist-output` flag: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` The `--persist-ouput` flag does 3 things: @@ -31,8 +29,7 @@ The `--persist-ouput` flag does 3 things: For example without `--persist-output`, a generated `ConcreteRequest` might look like below: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -49,8 +46,7 @@ The `--persist-ouput` flag does 3 things: With `--persist-output ` this becomes: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -68,12 +64,10 @@ The `--persist-ouput` flag does 3 things: 2. It generates a JSON file at the `` you specify containing a mapping from query ids to the corresponding operation texts. -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./src/queryMaps/queryMap.json" } - ``` The example above writes the complete query map file to `./src/queryMaps/queryMap.json`. You need to ensure all the directories @@ -83,8 +77,7 @@ leading to the `queryMap.json` file exist. You'll need to modify your network layer fetch implementation to pass a documentId parameter in the POST body instead of a query parameter: -```js - +```javascript function fetchQuery(operation, variables,) { return fetch('/graphql', { method: 'POST', @@ -100,7 +93,6 @@ function fetchQuery(operation, variables,) { return response.json(); }); } - ``` ## Executing Persisted Queries on the Server @@ -116,13 +108,11 @@ the query map file in a common location accessible to both the client and the se For applications where the client and server projects are separate, one option is to have an additional npm run script to push the query map at compile time to a location accessible by your server: -```js - +```javascript "scripts": { "push-queries": "node ./pushQueries.js", "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-ouput && npm run push-queries" } - ``` Some possibilities of what you can do in `./pushQueries.js`: @@ -146,8 +136,7 @@ database technologies you use, so we'll just cover the most common and basic exa If you use `express-graphql` and have access to the query map file, you can import the `--persist-output` JSON file directly and perform the matching using the `matchQueryMiddleware` from [relay-compiler-plus](https://github.com/yusinto/relay-compiler-plus). -```js - +```javascript import Express from 'express'; import expressGraphql from 'express-graphql'; import {matchQueryMiddleware} from 'relay-compiler-plus'; @@ -158,7 +147,6 @@ const app = Express(); app.use('/graphql', matchQueryMiddleware(queryMapJson), expressGraphql({schema})); - ``` ## Using `--persist-output` and `--watch` diff --git a/website/versioned_docs/version-v10.1.0/Modern-QueryRenderer.md b/website/versioned_docs/version-v10.1.0/Modern-QueryRenderer.md index cf6c37f3d9a4d..b621ef9986bf1 100644 --- a/website/versioned_docs/version-v10.1.0/Modern-QueryRenderer.md +++ b/website/versioned_docs/version-v10.1.0/Modern-QueryRenderer.md @@ -24,7 +24,6 @@ However, a `QueryRenderer` will not start loading its data until it is mounted, ## Example ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -56,5 +55,4 @@ const Example = (props) => { /> ); } - ``` diff --git a/website/versioned_docs/version-v10.1.0/Modern-RefetchContainer.md b/website/versioned_docs/version-v10.1.0/Modern-RefetchContainer.md index 7ce0d14e45417..51c2c44db8941 100644 --- a/website/versioned_docs/version-v10.1.0/Modern-RefetchContainer.md +++ b/website/versioned_docs/version-v10.1.0/Modern-RefetchContainer.md @@ -16,13 +16,11 @@ Table of Contents: `createRefetchContainer` has the following signature: ```javascript - createRefetchContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, refetchQuery: GraphQLTaggedNode, ): ReactComponentClass; - ``` ### Arguments @@ -37,7 +35,6 @@ createRefetchContainer( The Component resulting from `createRefetchContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -45,7 +42,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -61,7 +57,6 @@ type Props = { `refetch` has the following signature: ```javascript - type RefetchOptions = { force?: boolean, }; @@ -102,7 +97,6 @@ Returns a `Disposable` on which you could call `dispose()` to cancel the refetch In this simple example, let's assume we want to fetch the latest data for a `TodoItem` from the server: ```javascript - // TodoItem.js import {createRefetchContainer, graphql} from 'react-relay'; @@ -148,7 +142,6 @@ export default createRefetchContainer( } ` ); - ``` ### Loading more data @@ -156,7 +149,6 @@ export default createRefetchContainer( In this example we are using a Refetch Container to fetch more stories in a story feed component. ```javascript - import {createRefetchContainer, graphql} from 'react-relay'; class FeedStories extends React.Component { @@ -212,5 +204,4 @@ export default createRefetchContainer( } `, ); - ``` diff --git a/website/versioned_docs/version-v10.1.0/Modern-RelayCompat.md b/website/versioned_docs/version-v10.1.0/Modern-RelayCompat.md index 36632d3a8f1a1..f47dbd845ba3e 100644 --- a/website/versioned_docs/version-v10.1.0/Modern-RelayCompat.md +++ b/website/versioned_docs/version-v10.1.0/Modern-RelayCompat.md @@ -31,7 +31,6 @@ Relay Modern. The components using Relay Compat can be referred to by both other Relay Modern and Relay Classic components. ```javascript - const {createFragmentContainer, graphql} = require('react-relay/compat'); class TodoItem extends React.Component { @@ -47,5 +46,4 @@ module.exports = createFragmentContainer(TodoItem, graphql` isComplete } `); - ``` diff --git a/website/versioned_docs/version-v10.1.0/Modern-RelayEnvironment.md b/website/versioned_docs/version-v10.1.0/Modern-RelayEnvironment.md index 27d90b2fc4fe1..99e728bce740d 100644 --- a/website/versioned_docs/version-v10.1.0/Modern-RelayEnvironment.md +++ b/website/versioned_docs/version-v10.1.0/Modern-RelayEnvironment.md @@ -12,7 +12,6 @@ Most applications will create a single Environment instance and use it throughou To create an environment instance in Relay Modern, use the `RelayModernEnvironment` class: ```javascript - const { Environment, Network, @@ -30,7 +29,6 @@ const environment = new Environment({ network, store, }); - ``` For more details on creating a Network, see the [NetworkLayer guide](./network-layer). @@ -44,7 +42,6 @@ The example above did not configure a `handlerProvider`, which means that a defa If you wish to provide your own `handlerProvider`, you can do so: ```javascript - const { ConnectionHandler, } = require('relay-runtime'); @@ -58,5 +55,4 @@ function handlerProvider(handle) { `handlerProvider: No handler provided for ${handle}` ); } - ``` diff --git a/website/versioned_docs/version-v10.1.0/Modern-RelayStore.md b/website/versioned_docs/version-v10.1.0/Modern-RelayStore.md index 6bb2e3744d55b..38f88c7f69edb 100644 --- a/website/versioned_docs/version-v10.1.0/Modern-RelayStore.md +++ b/website/versioned_docs/version-v10.1.0/Modern-RelayStore.md @@ -16,7 +16,6 @@ Table of Contents: The `RecordSourceSelectorProxy` is the type of the `store` that [`updater` functions](./mutations#using-updater-and-optimisticupdater) receive as an argument. The following is the `RecordSourceSelectorProxy` interface: ```javascript - interface RecordSourceSelectorProxy { create(dataID: string, typeName: string): RecordProxy; delete(dataID: string): void; @@ -26,7 +25,6 @@ interface RecordSourceSelectorProxy { getPluralRootField(fieldName: string): ?Array; invalidateStore(): void; } - ``` ### `create(dataID: string, typeName: string): RecordProxy` @@ -36,9 +34,7 @@ Creates a new record in the store given a `dataID` and the `typeName` as defined #### Example ```javascript - const record = store.create(dataID, 'Todo'); - ``` ### `delete(dataID: string): void` @@ -48,9 +44,7 @@ Deletes a record from the store given its `dataID`. #### Example ```javascript - store.delete(dataID); - ``` ### `get(dataID: string): ?RecordProxy` @@ -60,9 +54,7 @@ Retrieves a record from the store given its `dataID`. Returns a [`RecordProxy`]( #### Example ```javascript - const record = store.get(dataID); - ``` ### `getRoot(): RecordProxy` @@ -74,20 +66,16 @@ Returns the [`RecordProxy`](#recordproxy) representing the root of the GraphQL d Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - // Represents root query const root = store.getRoot(); - ``` ### `getRootField(fieldName: string): ?RecordProxy` @@ -99,19 +87,15 @@ Retrieves a root field from the store given the `fieldName`, as defined by the G Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - const viewer = store.getRootField('viewer'); - ``` ### `getPluralRootField(fieldName: string): ?Array` @@ -123,19 +107,15 @@ Retrieves a root field that represents a collection from the store given the `fi Given the GraphQL document: ```graphql - nodes(first: 10) { # ... } - ``` Usage: ```javascript - const nodes = store.getPluralRootField('nodes'); - ``` ### `invalidateStore(): void` @@ -145,15 +125,12 @@ Globally invalidates the Relay store. This will cause any data that was written #### Example ```javascript - store.invalidateStore(); - ``` After global invalidation, any query that is checked before refetching it will be considered stale: ```javascript - environment.check(query) === 'stale' ``` @@ -163,7 +140,6 @@ environment.check(query) === 'stale' The `RecordProxy` serves as an interface to mutate records: ```javascript - interface RecordProxy { copyFieldsFrom(sourceRecord: RecordProxy): void; getDataID(): string; @@ -189,7 +165,6 @@ interface RecordProxy { setValue(value: mixed, name: string, arguments?: ?Object): RecordProxy; invalidateRecord(): void; } - ``` ### `getDataID(): string` @@ -199,9 +174,7 @@ Returns the dataID of the current record. #### Example ```javascript - const id = record.getDataID(); - ``` ### `getType(): string` @@ -211,7 +184,6 @@ Gets the type of the current record, as defined by the GraphQL schema. #### Example ```javascript - const type = user.getType(); // User ``` @@ -225,20 +197,16 @@ Gets the value of a field in the current record given the field name. Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - const name = viewer.getValue('name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. @@ -248,20 +216,16 @@ Optionally, if the field takes arguments, you can pass a bag of `variables`. Given the GraphQL document: ```graphql - viewer { id name(arg: $arg) } - ``` Usage: ```javascript - const name = viewer.getValue('name', {arg: 'value'}); - ``` ### `getLinkedRecord(name: string, arguments?: ?Object): ?RecordProxy` @@ -273,23 +237,19 @@ Retrieves a record associated with the current record given the field name, as d Given the GraphQL document: ```graphql - rootField { viewer { id name } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -299,22 +259,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { viewer(arg: $arg) { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {arg: 'value'}); - ``` ### `getLinkedRecords(name: string, arguments?: ?Object): ?Array` @@ -326,22 +282,18 @@ Retrieves the set of records associated with the current record given the field Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const nodes = rootField.getLinkedRecords('nodes'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -351,22 +303,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { nodes(first: $count) { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {count: 10}); - ``` ### `getOrCreateLinkedRecord(name: string, typeName: string, arguments?: ?Object)` @@ -378,19 +326,16 @@ Retrieves the a record associated with the current record given the field name, Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = rootField.getOrCreateLinkedRecord('viewer', 'User'); // Will create if it doesn't exist @@ -405,28 +350,22 @@ Mutates the current record by setting a new value on the specified field. Return Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - viewer.setValue('New Name', 'name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. ```javascript - viewer.setValue('New Name', 'name', {arg: 'value'}); - ``` ### `copyFieldsFrom(sourceRecord: RecordProxy): void` @@ -436,7 +375,6 @@ Mutates the current record by copying the fields over from the passed in record #### Example ```javascript - const record = store.get(id1); const otherRecord = store.get(id2); record.copyFieldsFrom(otherRecord); // Mutates `record` @@ -452,19 +390,16 @@ Mutates the current record by setting a new linked record on the given the field Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = store.create(/* ... */)'' rootField.setLinkedRecord(newViewer, 'viewer'); // @@ -482,19 +417,16 @@ Mutates the current record by setting a new set of linked records on the given t Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newNode = store.create(/* ... */); const newNodes = [...rootField.getLinkedRecords('nodes'), newNode]; @@ -511,16 +443,13 @@ Invalidates the record. This will cause any query that references this record to #### Example ```javascript - const record = store.get('4'); record.invalidateRecord(); - ``` After invalidating a record, any query that references the invalidated record and that is checked before refetching it will be considered stale: ```javascript - environment.check(query) === 'stale' ``` @@ -530,7 +459,6 @@ environment.check(query) === 'stale' `ConnectionHandler` is a utility module exposed by `relay-runtime` that aids in the manipulation of connections. `ConnectionHandler` exposes the following interface: ```javascript - interface ConnectionHandler { getConnection( record: RecordProxy, @@ -555,7 +483,6 @@ interface ConnectionHandler { ): void, deleteNode(connection: RecordProxy, nodeID: string): void } - ``` ### `getConnection(record: RecordProxy, key: string, filters?: ?Object)` @@ -565,7 +492,6 @@ Given a record and a connection key, and optionally a set of filters, `getConnec First, let's take a look at a plain connection: ```graphql - fragment FriendsFragment on User { friends(first: 10) { edges { @@ -575,26 +501,22 @@ fragment FriendsFragment on User { } } } - ``` Accessing a plain connection field like this is the same as other regular field: ```javascript - // The `friends` connection record can be accessed with: const user = store.get(userID); const friends = user && user.getLinkedRecord('friends'); // Access fields on the connection: const edges = friends && friends.getLinkedRecords('edges'); - ``` In a [pagination container](./pagination-container), we usually annotate the actual connection field with `@connection` to tell Relay which part needs to be paginated: ```graphql - fragment FriendsFragment on User { friends(first: 10, orderby: "firstname") @connection( key: "FriendsFragment_friends", @@ -606,7 +528,6 @@ fragment FriendsFragment on User { } } } - ``` For connections like the above, `ConnectionHandler` helps us find the record: @@ -624,7 +545,6 @@ const friends = ConnectionHandler.getConnection( ); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` ### Edge creation and insertion @@ -654,7 +574,6 @@ ConnectionHandler.insertEdgeAfter(friends, edge); // No cursor provided, Insert the edge at the front: ConnectionHandler.insertEdgeBefore(friends, edge); - ``` ### `deleteNode(connection: RecordProxy, nodeID: string): void` @@ -668,5 +587,4 @@ Given a connection, deletes any edges whose id matches the given id. const user = store.get(userID); const friends = ConnectionHandler.getConnection(user, 'friends'); ConnectionHandler.deleteNode(friends, idToDelete); - ``` diff --git a/website/versioned_docs/version-v10.1.0/Modern-Subscriptions.md b/website/versioned_docs/version-v10.1.0/Modern-Subscriptions.md index 671b28f684403..85ade0f34c511 100644 --- a/website/versioned_docs/version-v10.1.0/Modern-Subscriptions.md +++ b/website/versioned_docs/version-v10.1.0/Modern-Subscriptions.md @@ -6,7 +6,6 @@ original_id: subscriptions Relay exposes the following APIs to create subscriptions. ```javascript - import { requestSubscription } from 'react-relay'; type Variables = {[name: string]: any}; @@ -28,7 +27,6 @@ requestSubscription( cacheConfig?: CacheConfig, }, ) => Disposable; - ``` The function returns a `Disposable` on which you could call `dispose()` to cancel the refetch. @@ -55,7 +53,6 @@ appropriate when you are only changing the properties of existing records that can be identified by their `id`: ```javascript - import { requestSubscription, graphql, @@ -89,7 +86,6 @@ requestSubscription( onError: error => console.error(error), } ); - ``` # Configure Network @@ -97,7 +93,6 @@ requestSubscription( You will need to Configure your [Network](./network-layer) to handle subscriptions. The below example uses [subscriptions-transport-ws](https://github.com/apollographql/subscriptions-transport-ws): ```javascript - import { ... Network, @@ -134,7 +129,6 @@ Relay's in-memory cache when each subscription response is received. To do so, pass an `updater` function: ```javascript - import { ConnectionHandler } from 'relay-runtime'; requestSubscription( @@ -160,5 +154,4 @@ requestSubscription( }, }, ); - ``` diff --git a/website/versioned_docs/version-v10.1.0/Modern-TestingRelayComponents.md b/website/versioned_docs/version-v10.1.0/Modern-TestingRelayComponents.md index da8f520bd7917..91003cab931f2 100644 --- a/website/versioned_docs/version-v10.1.0/Modern-TestingRelayComponents.md +++ b/website/versioned_docs/version-v10.1.0/Modern-TestingRelayComponents.md @@ -65,7 +65,6 @@ MockPayloadGenerator may drastically simplify the process of creating and mainta Example of a simple Mock Resolver: ```javascript - { ID() { // Return mock value for a scalar filed with type ID @@ -76,13 +75,11 @@ Example of a simple Mock Resolver: return "Lorem Ipsum" } } - ``` It is possible to define more resolvers for Object types ```javascript - { // This will be the default values for User object in the query response User() { @@ -95,7 +92,6 @@ It is possible to define more resolvers for Object types }; }, } - ``` ### Mock Resolver Context @@ -103,7 +99,6 @@ It is possible to define more resolvers for Object types The first argument of the MockResolver is the object that contains Mock Resolver Context. It is possible to return dynamic values from mock resolvers based on the context - for instance, name or alias of the field, a path in the selection, arguments, or parent type. ```javascript - { String(context) { if (context.name === 'zip') { @@ -117,7 +112,6 @@ The first argument of the MockResolver is the object that contains Mock Resolver } } } - ``` ### ID Generation @@ -125,14 +119,12 @@ The first argument of the MockResolver is the object that contains Mock Resolver The second argument of the Mock Resolver its a function that will generate a sequence of integers, useful to generate unique ids in the tests ```javascript - { // will generate strings "my-id-1", "my-id-2", etc. ID(_, generateId) { return `my-id-${generateId()}`; }, } - ``` ### @relay_test_operation @@ -142,7 +134,6 @@ Most of GraphQL type information for a specific field in the selection is not av Operation with the @relay_test_operation directive will have additional metadata that will contain GraphQL type info for fields in the operation's selection. And it will improve the quality of the generated data. You also will be able to define Mock resolvers for Scalar (not only ID and String) and Abstract types: ```javascript - { Float() { return 123.456; @@ -160,7 +151,6 @@ Operation with the @relay_test_operation directive will have additional metadata }; } } - ``` ## Examples @@ -170,7 +160,6 @@ Operation with the @relay_test_operation directive will have additional metadata Using `createMockEnvironment` and `MockPayloadGenerator` allows writing concise tests for components that are using Relay Containers and Renderers. Both those modules can be imported from `relay-test-utils` ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { @@ -223,7 +212,6 @@ test('Error State', () => { renderer.root.find(item => (item.props.testID = 'errorMessage')), ).toBeDefined(); }); - ``` ### Fragment Container Tests @@ -231,7 +219,6 @@ test('Error State', () => { Essentially, in the example above will `resolveMostRecentOperation` will generate data for all child fragment containers (pagination, refetch). But, usually the Root Components container may have many child fragment components and you may want to exercise a specific Fragment Container. The solution for that would be to wrap your fragment container with the QueryRenderer that renders a Query that's spreads fragments from your fragment container. ```javascript - test('Fragment Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -262,7 +249,6 @@ test('Fragment Container', () => { expect(renderer).toMatchSnapshot(); }); - ``` ### Pagination Container Test @@ -270,7 +256,6 @@ test('Fragment Container', () => { Essentially, tests for Pagination container are not different from Fragment Container tests. But we can do more here, we can actually see how the pagination works - we can assert the behavior of our components when performing pagination (load more, refetch). ```javascript - // Pagination Example test('Pagination Container', () => { const environment = createMockEnvironment(); @@ -344,7 +329,6 @@ test('Pagination Container', () => { We can use similar approach here with wrapping container with Query Renderer. And for the sake of completeness, we will add example here: ```javascript - test('Refetch Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -386,7 +370,6 @@ test('Refetch Container', () => { ); // expect(renderer).toMatchSnapshot(); }); - ``` ### Mutations @@ -394,7 +377,6 @@ test('Refetch Container', () => { Mutations itself are operations so we can test them independently (unit-test) for specific mutation, or in combination with the view from which this mutation is called. ```javascript - // Say, you have a mutation function function sendMutation(environment, onCompleted, onError, variables) commitMutation(environment, { @@ -417,7 +399,6 @@ test('it should send mutation', () => { ); expect(onCompleted).toBeCalled(); }); - ``` ### Subscription @@ -425,7 +406,6 @@ test('it should send mutation', () => { We can test subscription in a similar way we test mutations ```javascript - // Example subscribe function function subscribe(environment, onNext, onError, variables) requestSubscription(environment, { @@ -448,7 +428,6 @@ test('it should subscribe', () => { ); expect(onNext).toBeCalled(); }); - ``` ### Example with `queueOperationResolver` @@ -456,7 +435,6 @@ test('it should subscribe', () => { With `queueOpeararionResolver` it possible to define responses for operations that will be executed on the environment ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { diff --git a/website/versioned_docs/version-v10.1.0/Modern-TypeEmission.md b/website/versioned_docs/version-v10.1.0/Modern-TypeEmission.md index 63614b869a322..4ff63e4a7d81b 100644 --- a/website/versioned_docs/version-v10.1.0/Modern-TypeEmission.md +++ b/website/versioned_docs/version-v10.1.0/Modern-TypeEmission.md @@ -16,7 +16,6 @@ In this example the emitted type-information would require the variables object #### Flow ```javascript - /** * export type ExampleQueryVariables = {| * +artistID: string @@ -44,7 +43,6 @@ const variables: ExampleQueryVariables = { #### TypeScript ```javascript - /** * export type ExampleQueryVariables = { * readonly artistID: string @@ -79,7 +77,6 @@ In this example the emitted type-information describes the response data availab #### Flow ```javascript - /** * export type ExampleQueryResponse = {| * +artist: ?{| @@ -110,7 +107,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * export type ExampleQueryResponse = { * readonly artist?: { @@ -146,7 +142,6 @@ Similarly, in this example the emitted type-information describes the prop data #### Flow ```javascript - /** * export type ExampleFragment_artist = {| * +name: string @@ -172,7 +167,6 @@ export const ExampleFragment = createFragmentContainer( #### TypeScript ```javascript - /** * export type ExampleFragment_artist = { * readonly name: string @@ -206,7 +200,6 @@ Consider a component that composes the above fragment container example. In this #### Flow ```javascript - /** * import type { FragmentReference } from "relay-runtime"; * declare export opaque type ExampleFragment_artist$ref: FragmentReference; @@ -250,7 +243,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * declare const _ExampleFragment_artist$ref: unique symbol; * export type ExampleFragment_artist$ref = typeof _ExampleFragment_artist$ref; @@ -315,7 +307,6 @@ $ relay-compiler --artifactDirectory ./src/__generated__ […] ["relay", { "artifactDirectory": "./src/__generated__" }] ] } - ``` It is recommended to alias this directory in your module resolution configuration such that you don’t need to specify relative paths in your source files. This is what is also done in the above examples, where artifacts are imported from a `__generated__` alias, rather than relative paths like `../../../../__generated__`. diff --git a/website/versioned_docs/version-v10.1.0/Modern-UpgradingSetVariables.md b/website/versioned_docs/version-v10.1.0/Modern-UpgradingSetVariables.md index d5b086fafce20..ff73feec04f8b 100644 --- a/website/versioned_docs/version-v10.1.0/Modern-UpgradingSetVariables.md +++ b/website/versioned_docs/version-v10.1.0/Modern-UpgradingSetVariables.md @@ -36,7 +36,6 @@ fragment on User { # ... } } - ``` This should be upgraded to use a [`PaginationContainer`](./pagination-container). @@ -61,7 +60,6 @@ fragment on User { # ... } } - ``` This can be upgraded by using a [`RefetchContainer`](./refetch-container) which allows you to specify the exact query to use to fetch the new data. @@ -86,7 +84,6 @@ fragment on FeedbackTarget { # ... } } - ``` This can be upgraded by conditionally rendering a [`QueryRenderer`](./query-renderer) which will load the data once it is rendered. The code overhead of doing this is dramatically reduced with the new API. diff --git a/website/versioned_docs/version-v10.1.0/Modern-fetchQuery.md b/website/versioned_docs/version-v10.1.0/Modern-fetchQuery.md index 2e9461ad527bd..c1a06ab7d2493 100644 --- a/website/versioned_docs/version-v10.1.0/Modern-fetchQuery.md +++ b/website/versioned_docs/version-v10.1.0/Modern-fetchQuery.md @@ -6,7 +6,6 @@ original_id: fetch-query You can use the `fetchQuery` function to imperatively make GraphQL Requests. This is useful for cases where you want to make requests outside of React but still utilize the Relay store and network layer. ```javascript - import {fetchQuery, graphql} from 'relay-runtime'; const query = graphql` @@ -25,7 +24,6 @@ fetchQuery(environment, query, variables) .then(data => { // access the graphql response }); - ``` ## Arguments diff --git a/website/versioned_docs/version-v10.1.0/PrinciplesAndArchitecture-Compiler.md b/website/versioned_docs/version-v10.1.0/PrinciplesAndArchitecture-Compiler.md index c195491682b1f..fcd0490cb724f 100644 --- a/website/versioned_docs/version-v10.1.0/PrinciplesAndArchitecture-Compiler.md +++ b/website/versioned_docs/version-v10.1.0/PrinciplesAndArchitecture-Compiler.md @@ -74,7 +74,6 @@ foo { # type FooType foo { id } - ``` - `SkipRedundantNodeTransform`: A more advanced version of flattening, this eliminates more complex cases of field duplication such as when a field is fetched both unconditionally and conditionally, or is fetched by two different sub-fragments. For example: @@ -97,7 +96,6 @@ foo { id } } - ``` - `GenerateRequisiteFieldTransform`: This optional, Relay-specific transform inserts `id` fields for globally identifiable objects and `__typename` fields wherever the type cannot be statically determined (e.g. for unions). diff --git a/website/versioned_docs/version-v10.1.0/PrinciplesAndArchitecture-Runtime.md b/website/versioned_docs/version-v10.1.0/PrinciplesAndArchitecture-Runtime.md index 9491d290c146f..e9221631a701d 100644 --- a/website/versioned_docs/version-v10.1.0/PrinciplesAndArchitecture-Runtime.md +++ b/website/versioned_docs/version-v10.1.0/PrinciplesAndArchitecture-Runtime.md @@ -77,7 +77,6 @@ RecordSource { city: 'Seattle', } } - ``` [1] Note that GraphQL itself does not impose this constraint, and Relay Runtime may also be used for schemas that do not conform to it. For example, both systems can be used to query a single denormalized table. However, many of the features that Relay Runtime provides, such as caching and normalization, work best when the data is represented as a normalized graph with stable identities for discrete pieces of information. diff --git a/website/versioned_docs/version-v10.1.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md b/website/versioned_docs/version-v10.1.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md index a8842ae084922..9ff8a7840df90 100644 --- a/website/versioned_docs/version-v10.1.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md +++ b/website/versioned_docs/version-v10.1.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md @@ -12,7 +12,6 @@ In this article we'll explore what it means to build a GraphQL client framework Imagine we have a simple application that fetches a list of stories, and some details about each one. Here's how that might look in resource-oriented REST: ```javascript - // Fetch the list of story IDs but not their details: rest.get('/stories').then(stories => // This resolves to a list of items with linked resources: @@ -25,13 +24,11 @@ rest.get('/stories').then(stories => // `[ { id: "...", text: "..." } ]` console.log(stories); }); - ``` Note that this approach requires _n+1_ requests to the server: 1 to fetch the list, and _n_ to fetch each item. With GraphQL we can fetch the same data in a single network request to the server (without creating a custom endpoint that we'd then have to maintain): ```javascript - graphql.get(`query { stories { id, text } }`).then( stories => { // A list of story items: @@ -39,7 +36,6 @@ graphql.get(`query { stories { id, text } }`).then( console.log(stories); } ); - ``` So far we're just using GraphQL as a more efficient version of typical REST approaches. Note two important benefits in the GraphQL version: @@ -56,7 +52,6 @@ Repeatedly refetching information from the server can get quite slow. For exampl In a resource-oriented REST system, we can maintain a **response cache** based on URIs: ```javascript - var _cache = new Map(); rest.get = uri => { if (!_cache.has(uri)) { @@ -64,13 +59,11 @@ rest.get = uri => { } return _cache.get(uri); }; - ``` Response-caching can also be applied to GraphQL. A basic approach would work similarly to the REST version. The text of the query itself can be used as a cache key: ```javascript - var _cache = new Map(); graphql.get = queryText => { if (!_cache.has(queryText)) { @@ -78,7 +71,6 @@ graphql.get = queryText => { } return _cache.get(queryText); }; - ``` Now, requests for previously cached data can be answered immediately without making a network request. This is a practical approach to improving the perceived performance of an application. However, this method of caching can cause problems with data consistency. @@ -90,7 +82,6 @@ With GraphQL it is very common for the results of multiple queries to overlap. H ``` query { stories { id, text, likeCount } } - ``` and then later refetch one of the stories whose `likeCount` has since been incremented: @@ -98,7 +89,6 @@ and then later refetch one of the stories whose `likeCount` has since been incre ``` query { story(id: "123") { id, text, likeCount } } - ``` We'll now see different `likeCount`s depending on how the story is accessed. A view that uses the first query will see an outdated count, while a view using the second query will see the updated count. @@ -119,7 +109,6 @@ query { } } } - ``` And here's a possible response: @@ -134,13 +123,11 @@ query: { } } } - ``` Although the response is hierarchical, we'll cache it by flattening all the records. Here is an example of how Relay would cache this query response: ```javascript - Map { // `story(id: "1")` 1: Map { @@ -152,7 +139,6 @@ Map { name: 'Jan', }, }; - ``` This is only a simple example: in reality the cache must handle one-to-many associations and pagination (among other things). @@ -182,7 +168,6 @@ The first query was for a list of stories: ``` query { stories { id, text, likeCount } } - ``` With a normalized response cache, a record would be created for each story in the list. The `stories` field would store links to each of these records. @@ -192,7 +177,6 @@ The second query refetched the information for one of those stories: ``` query { story(id: "123") { id, text, likeCount } } - ``` When this response is normalized, Relay can detect that this result overlaps with existing data based on its `id`. Rather than create a new record, Relay will update the existing `123` record. The new `likeCount` is therefore available to _both_ queries, as well as any other query that might reference this story. @@ -215,7 +199,6 @@ query { } } } - ``` After initially fetching this story our cache might be as follows. Note that the story and comment both link to the same record as `author`: @@ -242,7 +225,6 @@ Map { author: Link(2), }, } - ``` The author of this story also commented on it — quite common. Now imagine that some other view fetches new information about the author, and her profile photo has changed to a new URI. Here's the _only_ part of our cached data that changes: @@ -256,7 +238,6 @@ Map { photo: 'http://.../photo2.jpg', }, } - ``` The value of the `photo` field has changed; and therefore the record `2` has also changed. And that's it. Nothing else in the _cache_ is affected. But clearly our _view_ needs to reflect the update: both instances of the author in the UI (as story author and comment author) need to show the new photo. @@ -273,7 +254,6 @@ ImmutableMap { }, 3: ImmutableMap // same as before } - ``` If we replace `2` with a new immutable record, we'll also get a new immutable instance of the cache object. However, records `1` and `3` are untouched. Because the data is normalized, we can't tell that `story`'s contents have changed just by looking at the `story` record alone. @@ -299,7 +279,6 @@ mutation StoryLike($storyID: String) { likeCount } } - ``` Notice that we're querying for data that _may_ have changed as a result of the mutation. An obvious question is: why can't the server just tell us what changed? The answer is: it's complicated. GraphQL abstracts over _any_ data storage layer (or an aggregation of multiple sources), and works with any programming language. Furthermore, the goal of GraphQL is to provide data in a form that is useful to product developers building a view. diff --git a/website/versioned_docs/version-v10.1.0/PrinciplesAndArchitecture-ThinkingInRelay.md b/website/versioned_docs/version-v10.1.0/PrinciplesAndArchitecture-ThinkingInRelay.md index e61f3fd21c933..62b1914ef3ff9 100644 --- a/website/versioned_docs/version-v10.1.0/PrinciplesAndArchitecture-ThinkingInRelay.md +++ b/website/versioned_docs/version-v10.1.0/PrinciplesAndArchitecture-ThinkingInRelay.md @@ -30,13 +30,11 @@ fragment Story_story on Story { photo } } - ``` And this fragment can then be used to define the Story container: ```javascript - const {createFragmentContainer, graphql} = require('react-relay'); // Plain React component. @@ -64,7 +62,6 @@ const StoryContainer = createFragmentContainer(Story, { In React, rendering a view requires two inputs: the _component_ to render, and a _root_ DOM (UI) node to render into. Rendering Relay containers is similar: we need a _container_ to render, and a _root_ in the graph from which to start our query. We also must ensure that the queries for the container are executed and may want to show a loading indicator while data is being fetched. Similar to `ReactDOM.render(component, domNode)`, Relay provides `` for this purpose. The `query` and `variables` define what data to fetch and `render` defines what to render. Here's how we might render ``: ```javascript - ReactDOM.render( { ); } } - ``` The above code is doing something very similar to our [previous example](#rendering-graphql-queries). However, we are now passing a `$userID` variable to the GraphQL query via the `variables` prop. This has a couple of important implications: @@ -228,7 +216,6 @@ Now that we know how to define and fetch queries, let's actually start building First, let's start at the bottom. Suppose that we want to render a component that simply displays a given todo item's text and completed state: ```javascript - // Todo.js import React from 'react'; @@ -258,7 +245,6 @@ export default class Todo extends React.Component { ); } } - ``` From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L112), we know that we can query this data on the `Todo` type. However, we don't want to have to send a separate query for each todo item; that would defeat the purpose of using GraphQL over a traditional REST API. We could manually query for these fields directly in our `QueryRenderer` query, but that would hurt re-usability: what if we want to query the same set of fields as part of a different query? Additionally, we wouldn't know which component needs the data we're querying, which is a problem Relay directly tries to address. @@ -266,18 +252,15 @@ From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/dat Instead, we can define a reusable [Fragment](http://graphql.org/learn/queries/#fragments), which allows us to define a set of fields on a type and reuse them within our queries wherever we need to: ```graphql - fragment TodoItemFragment on Todo { complete text } - ``` Our component can then use this fragment to declare its data dependency on the `Todo` GraphQL type: ```javascript - // Todo.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -340,7 +323,6 @@ Before proceeding, don't forget to run the Relay Compiler with `yarn relay`. Given that [Fragment Containers](./fragment-container) are just React components, we can compose them as such. We can even re-use fragment containers within other fragment containers. As an example, let's see how we would define a `TodoList` component that just renders a list of todo items, and whether all have been completed or not: ```javascript - // TodoList.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -401,7 +383,6 @@ export default createFragmentContainer( `, }, ); - ``` As with the first fragment container we defined, `TodoList` declares its data dependencies via a fragment. However, this component additionally re-uses the fragment previously defined by the `Todo` component, and passes the appropriate data when rendering the child `Todo` components (a.k.a. fragment containers). @@ -416,7 +397,6 @@ fragment containers do not directly fetch data. Instead, containers declare a sp A `QueryRenderer` rendering these fragment containers could look like the following: ```javascript - // ViewerTodoList.js import React from 'react'; import {graphql, QueryRenderer} from 'react-relay'; @@ -457,7 +437,6 @@ export default class ViewerTodoList extends React.Component { ); } } - ``` Check out our docs for [Fragment Containers](./fragment-container) for more details, and our guides on [Refetch](./refetch-container) and [Pagination](./pagination-container) for more advanced usage of containers. @@ -469,7 +448,6 @@ Now that we know how to query for and render data, let's move on to changing our From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L35), we know that we have some mutations available to us, so let's start by writing a mutation to change the `complete` status of a given todo item (i.e. mark or unmark it as done): ```graphql - mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { changeTodoStatus(input: $input) { todo { @@ -478,7 +456,6 @@ mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { } } } - ``` This mutation allows us to query back some data as a [result of the mutation](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L18), so we're going to query for the updated `complete` status on the todo item. @@ -486,7 +463,6 @@ This mutation allows us to query back some data as a [result of the mutation](ht In order to execute this mutation in Relay, we're going to write a new mutation using Relay's `commitMutation` api: ```javascript - // ChangeTodoStatusMutation.js import {graphql, commitMutation} from 'react-relay'; @@ -520,7 +496,6 @@ function commit( } export default {commit}; - ``` Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mutation to the server and, in our case, upon receiving a response it will automatically update the local data store with the latest data from the server. This also means that upon receiving the response, Relay will ensure that any components (i.e. containers) that depend on the updated data are re-rendered. @@ -528,7 +503,6 @@ Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mut In order to actually use this mutation in our component, we could update our `Todo` component in the following way: ```javascript - // Todo.js // ... @@ -562,7 +536,6 @@ In order to make the experience better, we can configure our mutation to do an o In Relay, there's a couple of options we can pass to `commitMutation` to enable optimistic updates. Let's see what that would look like in our `ChangeTodoStatusMutation`: ```javascript - // ChangeTodoStatusMutation.js // ... @@ -597,7 +570,6 @@ function commit( } export default {commit}; - ``` In the simplest case above, we just need to pass an `optimisticResponse` option, which should refer to an object having the same shape as the mutation response payload. When we pass this option, Relay will know to immediately update our local data with the optimistic response, and then update it with the actual server response or roll it back if an error occurs. diff --git a/website/versioned_docs/version-v10.1.1/Modern-ConvertingMutations.md b/website/versioned_docs/version-v10.1.1/Modern-ConvertingMutations.md index 08ad2e998cb2d..8f4bdc1d8e0d2 100644 --- a/website/versioned_docs/version-v10.1.1/Modern-ConvertingMutations.md +++ b/website/versioned_docs/version-v10.1.1/Modern-ConvertingMutations.md @@ -12,19 +12,16 @@ FatQueries in Relay Classic mutations was a concept that was confusing for a num Example of existing fat query: ```javascript - RelayClassic.QL` fragment on MarkReadNotificationResponsePayload @relay(pattern: true) { notification } `; - ``` Example of converted mutation query: ```javascript - graphql` mutation MarkReadNotificationMutation( $input: MarkReadNotificationData! @@ -37,7 +34,6 @@ graphql` } } `; - ``` ## Migrating Configs @@ -67,7 +63,6 @@ This is no longer needed in Compatibility Mode for neither environments. Simply Take this example of a simple mutation in Relay Classic: ```javascript - class LikeStoryMutation extends RelayClassic.Mutation { getMutation() { return RelayClassic.QL`mutation {likeStory}`; @@ -106,7 +101,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { `, }; } - ``` ### Converting `getMutation()` and `getFatQuery()` @@ -114,7 +108,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { We combine these two into a regular GraphQL mutation, which list out specific fields that needs to be updated. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story(data: $input) { @@ -126,7 +119,6 @@ const mutation = graphql` } } `; - ``` ### Converting `getConfigs()` @@ -138,13 +130,11 @@ As specified above, `FIELDS_CHANGE` configs can be omitted. To convert `getVariables()`, we take the return value from the original function and wrap it in an object that contains a property that matches the variable name for the mutation. In this case, the mutation has a `input` variable that is of type `LikeStoryData`. ```javascript - const variables = { input: { storyID: args.storyID } } - ``` ### Final Result @@ -152,7 +142,6 @@ const variables = { As you can see, our resulting mutation is a lot simpler and more like regular GraphQL than the Relay Classic version we started out with. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story { @@ -178,7 +167,6 @@ function commit(environment: CompatEnvironment, args) { variables, }); } - ``` See [Mutation](./mutations) for additional options on `commitMutation` for more complex mutations. diff --git a/website/versioned_docs/version-v10.1.1/Modern-FragmentContainer.md b/website/versioned_docs/version-v10.1.1/Modern-FragmentContainer.md index 423f446cbb054..6a40bbcfb5d0a 100644 --- a/website/versioned_docs/version-v10.1.1/Modern-FragmentContainer.md +++ b/website/versioned_docs/version-v10.1.1/Modern-FragmentContainer.md @@ -17,12 +17,10 @@ Table of Contents: `createFragmentContainer` has the following signature: ```javascript - createFragmentContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, ): ReactComponentClass; - ``` ### Arguments @@ -43,7 +41,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -58,7 +55,6 @@ To start, let's build the plain React version of a hypothetical `` c Here's a basic implementation of `` that ignores styling in order to highlight the functionality: ```javascript - // TodoItem.js class TodoItem extends React.Component { render() { @@ -78,7 +74,6 @@ class TodoItem extends React.Component { ); } } - ``` ### Data Dependencies With GraphQL @@ -86,7 +81,6 @@ class TodoItem extends React.Component { In Relay, data dependencies are described using [GraphQL](https://github.com/facebook/graphql). For ``, the dependency can be expressed as follows. Note that this exactly matches the shape that the component expected for the `item` prop. ```javascript - graphql` # This fragment only applies to objects of type 'Todo'. fragment TodoItem_item on Todo { @@ -102,7 +96,6 @@ graphql` Given the plain React component and a GraphQL fragment, we can now define a Fragment Container to specify this component's data requirements. Let's look at the code first and then see what's happening: ```javascript - // TodoItem.js import {createFragmentContainer, graphql} from 'react-relay'; @@ -120,7 +113,6 @@ export default createFragmentContainer(TodoItem, { } `, }); - ``` ## Container Composition @@ -134,7 +126,6 @@ Let's explore how this works via a `` component that composes the `< View composition is _exactly_ what you're used to — Relay containers are just standard React components. Here's the `` component: ```javascript - class TodoList extends React.Component { render() { // Expects a `list` with a string `title`, as well as the information @@ -151,7 +142,6 @@ class TodoList extends React.Component { ); } } - ``` ### Composing Fragments @@ -159,7 +149,6 @@ class TodoList extends React.Component { Fragment composition works similarly — a parent container's fragment composes the fragment for each of its children. In this case, `` needs to fetch information about the `Todo`s that are required by ``. ```javascript - class TodoList extends React.Component // as above export default createFragmentContainer(TodoList, { @@ -176,7 +165,6 @@ export default createFragmentContainer(TodoList, { } `, }); - ``` Note that when composing fragments, the type of the composed fragment must match the field on the parent in which it is embedded. For example, it wouldn't make sense to embed a fragment of type `Story` into a parent's field of type `User`. Relay and GraphQL will provide helpful error messages if you get this wrong (and if they aren't helpful, let us know!). @@ -190,7 +178,6 @@ When defining a fragment, you can use the [`@argumentDefinitions`](./graphql-in- For example, let's redefine our `TodoList_list` fragment to take some arguments using `@argumentDefinitions`: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -200,7 +187,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` Any arguments defined inside `@argumentDefinitions` will be local variables available inside the fragment's scope. However, a fragment can also reference global variables that were defined in the root query. @@ -212,11 +198,9 @@ In order to pass arguments to a fragment that has `@argumentDefinitions`, you ne Following our `TodoList_list` example, we would pass arguments to the fragment like so: ```graphql - query TodoListQuery($count: Int, $userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` ## Rendering Containers diff --git a/website/versioned_docs/version-v10.1.1/Modern-GraphQLInRelay.md b/website/versioned_docs/version-v10.1.1/Modern-GraphQLInRelay.md index c4dc8f3463e53..715b119492cc7 100644 --- a/website/versioned_docs/version-v10.1.1/Modern-GraphQLInRelay.md +++ b/website/versioned_docs/version-v10.1.1/Modern-GraphQLInRelay.md @@ -14,7 +14,6 @@ Table of Contents: The `graphql` template tag provided by Relay serves as the mechanism to write queries, fragments, mutations or subscriptions in the [GraphQL](http://graphql.org/learn/) language. For example: ```javascript - import {graphql} from 'react-relay'; graphql` @@ -24,7 +23,6 @@ graphql` } } `; - ``` The result of using the `graphql` template tag is a `GraphQLTaggedNode`; a runtime representation of the GraphQL document which can be used to define [Query Renderers](./query-renderer), [Fragment Containers](./fragment-container), [Refetch Containers](./refetch-container), [Pagination Containers](./pagination-container), etc. @@ -42,11 +40,9 @@ Relay uses directives to add additional information to GraphQL documents, which `@arguments` is a directive used to pass arguments to a fragment that was defined using [`@argumentDefinitions`](#argumentdefinitions). For example: ```graphql - query TodoListQuery($userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -56,7 +52,6 @@ See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fr `@argumentDefinitions` is a directive used to specify arguments taken by a fragment. For example: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -66,7 +61,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -80,7 +74,6 @@ When using the [Pagination Container](./pagination-container), Relay expects con When defining a fragment for use with a Fragment container, you can use the `@relay(plural: true)` directive to indicate that container expects the prop for that fragment to be a list of items instead of a single item. A query or parent that spreads a `@relay(plural: true)` fragment should do so within a plural field (ie a field backed by a [GraphQL list](http://graphql.org/learn/schema/#lists-and-non-null). For example: ```javascript - // Plural fragment definition graphql` fragment TodoItems_items on TodoItem @relay(plural: true) { @@ -95,7 +88,6 @@ fragment TodoApp_app on App { ...TodoItem_items } } - ``` ### `@inline` @@ -107,7 +99,6 @@ Non-React functions can also take advantage of data masking. A fragment can be d In the example below, the function `processItemData` is called from a React component. It requires an item object with a specific set of fields. All React components that use this function should spread the `processItemData_item` fragment to ensure all of the correct item data is loaded for this function. ```javascript - import {graphql, readInlineData} from 'react-relay'; // non-React function called from React @@ -127,11 +118,9 @@ function processItemData(itemRef) { creatorName: item.creator.name }); } - ``` ```javascript - // React Component function MyComponent({item}) { function handleClick() { @@ -151,7 +140,6 @@ export default createFragmentContainer(MyComponent, { } ` }); - ``` ### `@relay(mask: Boolean)` @@ -169,7 +157,6 @@ Keep in mind that it is typically considered an **anti-pattern** to create a sin In the example below, the `user` prop will include the data for `id` and `name` fields wherever `...Component_internUser` is included, instead of Relay's normal behavior to mask those fields: ```javascript - graphql` fragment Component_internUser on InternUser @relay(mask: false) { id @@ -197,7 +184,6 @@ export default createFragmentContainer( } `, ); - ``` ## Relay Compiler @@ -207,7 +193,6 @@ Relay uses the Relay Compiler to convert [`graphql`](#graphql) literals into gen A query like the following: ```javascript - graphql` fragment MyComponent on Type { field @@ -228,12 +213,10 @@ Relay Compiler supports the use of **persisted queries**, in which each version Persisted queries can be enabled by instructing Relay Compiler to emit metadata about each query, mutation, and subscription into a JSON file. The generated file will contain a mapping of query identifiers to query text, which you can then save to your server. To enable persisted queries, use the `--persist-output` flag to the compiler: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` Relay Compiler will then create the id => query text mapping in the path you specify. You can then use this complete @@ -250,7 +233,6 @@ See our relay-compiler section in our [Installation and Setup guide](./installat To use the Relay Compiler, you need either a .graphql or .json GraphQL schema file, describing your GraphQL server's API. Typically these files are local representations of a server source of truth and are not edited directly. For example, we might have a `schema.graphql` like: ```graphql - schema { query: Root } @@ -268,7 +250,6 @@ type WordDefinition { text: String image: String } - ``` ### Source files @@ -284,7 +265,6 @@ For example, given the two files: - `src/Components/DictionaryComponent.js` ```javascript - const DictionaryWordFragment = graphql` fragment DictionaryComponent_word on Word { id @@ -306,7 +286,6 @@ For example, given the two files: - `src/Queries/DictionaryQuery.js` ```javascript - const DictionaryQuery = graphql` query DictionaryQuery { dictionary { @@ -330,9 +309,7 @@ Typically you will not need to import your generated definitions. The [Relay Bab However the Relay Compiler also automatically generates [Flow](https://flow.org) types as [type comments](https://flow.org/en/docs/types/comments/). For example, you can import the generated Flow types like so: ```javascript - import type {DictionaryComponent_word} from './__generated__/DictionaryComponent_word.graphql'; - ``` ### Client schema extensions @@ -342,7 +319,6 @@ The Relay Compiler fully supports client-side schema extensions, which allows yo For example, assuming the server schema `./schema.graphql`: ```graphql - schema { query: Root } @@ -350,28 +326,23 @@ schema { type Root { title: String! } - ``` We can create a `./src/clientSchema.graphql` and define a new type called `Setting`: ```graphql - type Setting { name: String! active: Boolean! } - ``` We can then extend existing server types in the client schema `./src/clientSchema.graphql` with our new `Setting` type, like so: ```graphql - extend type Root { settings: [Setting] } - ``` Any fields specified in the client schema, can be fetched from the [Relay Store](./relay-store), by selecting it in a query or fragment. diff --git a/website/versioned_docs/version-v10.1.1/Modern-LocalStateManagement.md b/website/versioned_docs/version-v10.1.1/Modern-LocalStateManagement.md index da71a0dd33246..3ecbf6801f91c 100644 --- a/website/versioned_docs/version-v10.1.1/Modern-LocalStateManagement.md +++ b/website/versioned_docs/version-v10.1.1/Modern-LocalStateManagement.md @@ -24,23 +24,19 @@ It can even be used to extend an existing server schema. For example, we can create a new type called `Note`: ```graphql - type Note { id: ID! title: String body: String } - ``` And then extend the server schema type `User`, with a list of `Note`, called `notes`. ```graphql - extend type User { notes: [Note] } - ``` ## Querying local state @@ -51,7 +47,6 @@ The field can be from the server schema, or it can be schema agnostic, like an i Here, we use a [QueryRenderer](./query-renderer) to get the current `User` via the `viewer` field, along with their id, name and the local list of notes. ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -97,7 +92,6 @@ const Example = (props) => { /> ); } - ``` ## Mutating local state @@ -111,7 +105,6 @@ To build upon the previous example, let's try creating, updating and deleting a ### Create ```javascript - import {commitLocalUpdate} from 'react-relay'; let tempID = 0; @@ -131,7 +124,6 @@ function createUserNote() { user.setLinkedRecords([...userNoteRecords, newNoteRecord], 'notes'); }); } - ``` Note that since this record will be rendered by the `ExampleQuery` in our `QueryRenderer`, the QueryRenderer will automatically retain this data so it isn't garbage collected. @@ -139,7 +131,6 @@ Note that since this record will be rendered by the `ExampleQuery` in our `Query If no component is rendering the local data and you want to manually retain it, you can do so by calling `environment.retain()`: ```javascript - import {createOperationDescriptor, getRequest} from 'relay-runtime'; // Create a query that references that record @@ -166,13 +157,11 @@ const disposable = environment.retain(operation); // Whenever you don't need that data anymore and it's okay for Relay to garbage collect it, // you can dispose of the retain disposable.dispose(); - ``` ### Update ```javascript - import {commitLocalUpdate} from 'react-relay'; function updateUserNote(dataID, body, title) { @@ -183,13 +172,11 @@ function updateUserNote(dataID, body, title) { note.setValue(title, 'title') }); } - ``` ### Delete ```javascript - import {commitLocalUpdate} from 'react-relay'; function deleteUserNote(dataID) { @@ -207,7 +194,6 @@ function deleteUserNote(dataID) { user.setLinkedRecords(newUserNoteRecords, 'notes'); }); } - ``` ## Initial local state @@ -216,7 +202,6 @@ All new client-side schema fields default to `undefined` value. Often however, y You can use an updater function via `commitLocalUpdate` to prime local state. ```javascript - import {commitLocalUpdate} from 'react-relay'; commitLocalUpdate(environment, store => { @@ -225,5 +210,4 @@ commitLocalUpdate(environment, store => { // initialize user notes to an empty array. user.setLinkedRecords([], 'notes'); }); - ``` diff --git a/website/versioned_docs/version-v10.1.1/Modern-MigrationSetup.md b/website/versioned_docs/version-v10.1.1/Modern-MigrationSetup.md index 66f1145357e25..a89c0e178e0e5 100644 --- a/website/versioned_docs/version-v10.1.1/Modern-MigrationSetup.md +++ b/website/versioned_docs/version-v10.1.1/Modern-MigrationSetup.md @@ -13,13 +13,11 @@ With some additional configuration, the `"relay"` babel plugin can also translat Relay Classic `Relay.QL` literals. Most importantly, include a reference to your GraphQL Schema as either a json file or graphql schema file. ```javascript - { "plugins": [ ["relay", {"schema": "path/schema.graphql"}] ] } - ``` ## Set up babel-plugin-relay for "[compatibility mode](./relay-compat)" @@ -29,13 +27,11 @@ literals can be translated to be usable by _both_ runtimes if configured to use compatibility mode: ```javascript - { "plugins": [ ["relay", {"compat": true, "schema": "path/schema.graphql"}] ] } - ``` ## Additional Options @@ -47,7 +43,6 @@ thrown at runtime. When compiling code for production deployment, the plugin can be configured to immediately throw upon encountering a validation problem. The plugin can be further customized for different environments with the following options: ```javascript - { "plugins": [ ["relay", { @@ -56,5 +51,4 @@ When compiling code for production deployment, the plugin can be configured to i }] ] } - ``` diff --git a/website/versioned_docs/version-v10.1.1/Modern-Mutations.md b/website/versioned_docs/version-v10.1.1/Modern-Mutations.md index bc7545a967717..412672f0bf588 100644 --- a/website/versioned_docs/version-v10.1.1/Modern-Mutations.md +++ b/website/versioned_docs/version-v10.1.1/Modern-Mutations.md @@ -17,7 +17,6 @@ Table of Contents: Use `commitMutation` to create and execute mutations. `commitMutation` has the following signature: ```javascript - commitMutation( environment: Environment, config: { @@ -32,7 +31,6 @@ commitMutation( cacheConfig?: CacheConfig, }, ); - ``` ### Arguments @@ -60,7 +58,6 @@ commitMutation( Example of a simple mutation: ```javascript - import {commitMutation, graphql} from 'react-relay'; const mutation = graphql` @@ -92,7 +89,6 @@ function markNotificationAsRead(environment, storyID) { }, ); } - ``` ## Optimistic Updates @@ -100,7 +96,6 @@ function markNotificationAsRead(environment, storyID) { To improve perceived responsiveness, you may wish to perform an "optimistic update", in which the client immediately updates to reflect the anticipated new value even before the response from the server has come back. The simplest way to do this is by providing an `optimisticResponse` and adding it to the `config` that we pass into `commitMutation`: ```javascript - const mutation = graphql` mutation MarkReadNotificationMutation( $storyID: ID! @@ -129,7 +124,6 @@ commitMutation( variables, }, ); - ``` Another way to enable optimistic updates is via the `optimisticUpdater`, which can be used for more complicated update scenarios. Using `optimisticUpdater` is covered in the section [below](#using-updater-and-optimisticupdater). @@ -151,7 +145,6 @@ Given a `deletedIDFieldName`, Relay will remove the node(s) from the store. #### Example ```javascript - const mutation = graphql` mutation DestroyShipMutation($target: ID!) { destroyShip(target: $target) { @@ -169,7 +162,6 @@ const configs = [{ type: 'NODE_DELETE', deletedIDFieldName: 'destroyedShipId', }]; - ``` ### RANGE_ADD @@ -189,7 +181,6 @@ Given a parent, information about the connection, and the name of the newly crea #### Example ```javascript - const mutation = graphql` mutation AddShipMutation($factionID: ID!, $name: String!) { addShip(factionID: $factionID, name: $name) { @@ -220,7 +211,6 @@ function commit(environment, factionID, name) { }], }); } - ``` ### RANGE_DELETE @@ -242,7 +232,6 @@ from the connection but leave the associated record(s) in the store. #### Example ```javascript - const mutation = graphql` mutation RemoveTagMutation($todoID: ID!, $tagID: ID!) { removeTag(todo: $todoID, tag: $tagID) { @@ -269,7 +258,6 @@ function commit(environment, todoID, tagID) { }], }); } - ``` ## Using updater and optimisticUpdater @@ -287,7 +275,6 @@ When you provide these functions, this is roughly what happens during the mutati Here are a quick example of adding a todo item to a Todo list using this [example schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L36): ```javascript - // AddTodoMutation.js import {commitMutation, graphql} from 'react-relay'; import {ConnectionHandler} from 'relay-runtime'; @@ -371,7 +358,6 @@ function commit(environment, text, user) { }, }); } - ``` For details on how to interact with the Relay Store, please refer to our Relay Store [docs](./relay-store). diff --git a/website/versioned_docs/version-v10.1.1/Modern-NetworkLayer.md b/website/versioned_docs/version-v10.1.1/Modern-NetworkLayer.md index 9dddd36d6c235..c9e069b812b01 100644 --- a/website/versioned_docs/version-v10.1.1/Modern-NetworkLayer.md +++ b/website/versioned_docs/version-v10.1.1/Modern-NetworkLayer.md @@ -8,7 +8,6 @@ In order to know how to access your GraphQL server, Relay Modern requires develo Currently the easiest way to create a network layer is via a helper from the `relay-runtime` package: ```javascript - import { Environment, Network, @@ -50,7 +49,6 @@ const environment = new Environment({ }); export default environment; - ``` Note that this is a basic example to help you get started. This example could be extended with additional features such as request/response caching (enabled e.g. when `cacheConfig.force` is false) and uploading form data for mutations (the `uploadables` parameter). @@ -62,7 +60,6 @@ Relay modern makes no assumptions about what to cache and will garbage collect a You have to implement your own cache strategy. A simple solution is to use `QueryResponseCache` (an in-memory cache): ```javascript - import { Environment, Network, @@ -126,7 +123,6 @@ const environment = new Environment({ }); export default environment; - ``` ## Custom open-source implementations diff --git a/website/versioned_docs/version-v10.1.1/Modern-PaginationContainer.md b/website/versioned_docs/version-v10.1.1/Modern-PaginationContainer.md index 6ac3aac8cfb8e..57980d553af9b 100644 --- a/website/versioned_docs/version-v10.1.1/Modern-PaginationContainer.md +++ b/website/versioned_docs/version-v10.1.1/Modern-PaginationContainer.md @@ -24,7 +24,6 @@ However, when [specifying connection fragments](#createpaginationcontainer) for The purpose of the `@connection` directive is to allow Relay to uniquely identify different connections under a parent type. The `@connection` directive takes 2 arguments that help identify the connection: ```graphql - @connection(key: String!, filters: [String]) ``` @@ -37,7 +36,6 @@ The purpose of the `@connection` directive is to allow Relay to uniquely identif Specifying just the `key`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and the value of `$orderBy` (given that no `filters` were provided) @@ -53,13 +51,11 @@ fragment Feed_user on User { } } } - ``` Specifying `key` and `filters`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and /only/ the value of `$searchTerm`, i.e. @@ -77,7 +73,6 @@ fragment Feed_user on User { } } } - ``` ## `createPaginationContainer` @@ -85,7 +80,6 @@ fragment Feed_user on User { `createPaginationContainer` has the following signature: ```javascript - createPaginationContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, @@ -113,7 +107,6 @@ type ConnectionData = { startCursor: ?string, }, }; - ``` ### Arguments @@ -134,7 +127,6 @@ type ConnectionData = { The Component resulting from `createPaginationContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -145,7 +137,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -160,7 +151,6 @@ type Props = { `hasMore` is a function available on the `relay` [prop](#available-props). This function indicates whether there are more pages to fetch from the server or not. ```javascript - hasMore: () => boolean, ``` @@ -170,7 +160,6 @@ hasMore: () => boolean, `isLoading` is a function available on the `relay` [prop](#available-props). This function indicates if a previous call to [`loadMore()`](#loadmore) is still pending. This is convenient for avoiding duplicate load calls. ```javascript - isLoading: () => boolean, ``` @@ -180,7 +169,6 @@ isLoading: () => boolean, `loadMore` is a function available on the `relay` [prop](#available-props). You can call `loadMore()` to fetch more items from the server based on the `connectionConfig` provided to the container. This will return null if there are no more items to fetch, otherwise it will fetch more items and return a Disposable that can be used to cancel the fetch. ```javascript - loadMore( pageSize: number, callback: ?(error: ?Error) => void, @@ -201,7 +189,6 @@ loadMore( `refetchConnection` is a function available on the `relay` [prop](#available-props). You can call `refetchConnection` to restart pagination on a connection from scratch, with optionally a completely new set of variables to pass to the pagination `query`. This is useful for example if you are paginating over a collection based on a userID and the userID changes, you'd want to start paginating over the new collection for the new user. ```javascript - refetchConnection:( totalCount: number, callback: (error: ?Error) => void, @@ -219,7 +206,6 @@ refetchConnection:( ## Pagination Example ```javascript - // Feed.js import {createPaginationContainer, graphql} from 'react-relay'; @@ -314,5 +300,4 @@ module.exports = createPaginationContainer( ` } ); - ``` diff --git a/website/versioned_docs/version-v10.1.1/Modern-PersistedQueries.md b/website/versioned_docs/version-v10.1.1/Modern-PersistedQueries.md index 137cc2e23220c..ec03b69ba09c3 100644 --- a/website/versioned_docs/version-v10.1.1/Modern-PersistedQueries.md +++ b/website/versioned_docs/version-v10.1.1/Modern-PersistedQueries.md @@ -17,12 +17,10 @@ The relay compiler supports persisted queries which is useful because: In your `npm` script in `package.json`, run the relay compiler using the `--persist-output` flag: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` The `--persist-ouput` flag does 3 things: @@ -31,8 +29,7 @@ The `--persist-ouput` flag does 3 things: For example without `--persist-output`, a generated `ConcreteRequest` might look like below: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -49,8 +46,7 @@ The `--persist-ouput` flag does 3 things: With `--persist-output ` this becomes: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -68,12 +64,10 @@ The `--persist-ouput` flag does 3 things: 2. It generates a JSON file at the `` you specify containing a mapping from query ids to the corresponding operation texts. -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./src/queryMaps/queryMap.json" } - ``` The example above writes the complete query map file to `./src/queryMaps/queryMap.json`. You need to ensure all the directories @@ -83,8 +77,7 @@ leading to the `queryMap.json` file exist. You'll need to modify your network layer fetch implementation to pass a documentId parameter in the POST body instead of a query parameter: -```js - +```javascript function fetchQuery(operation, variables,) { return fetch('/graphql', { method: 'POST', @@ -100,7 +93,6 @@ function fetchQuery(operation, variables,) { return response.json(); }); } - ``` ## Executing Persisted Queries on the Server @@ -116,13 +108,11 @@ the query map file in a common location accessible to both the client and the se For applications where the client and server projects are separate, one option is to have an additional npm run script to push the query map at compile time to a location accessible by your server: -```js - +```javascript "scripts": { "push-queries": "node ./pushQueries.js", "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-ouput && npm run push-queries" } - ``` Some possibilities of what you can do in `./pushQueries.js`: @@ -146,8 +136,7 @@ database technologies you use, so we'll just cover the most common and basic exa If you use `express-graphql` and have access to the query map file, you can import the `--persist-output` JSON file directly and perform the matching using the `matchQueryMiddleware` from [relay-compiler-plus](https://github.com/yusinto/relay-compiler-plus). -```js - +```javascript import Express from 'express'; import expressGraphql from 'express-graphql'; import {matchQueryMiddleware} from 'relay-compiler-plus'; @@ -158,7 +147,6 @@ const app = Express(); app.use('/graphql', matchQueryMiddleware(queryMapJson), expressGraphql({schema})); - ``` ## Using `--persist-output` and `--watch` diff --git a/website/versioned_docs/version-v10.1.1/Modern-QueryRenderer.md b/website/versioned_docs/version-v10.1.1/Modern-QueryRenderer.md index cf6c37f3d9a4d..b621ef9986bf1 100644 --- a/website/versioned_docs/version-v10.1.1/Modern-QueryRenderer.md +++ b/website/versioned_docs/version-v10.1.1/Modern-QueryRenderer.md @@ -24,7 +24,6 @@ However, a `QueryRenderer` will not start loading its data until it is mounted, ## Example ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -56,5 +55,4 @@ const Example = (props) => { /> ); } - ``` diff --git a/website/versioned_docs/version-v10.1.1/Modern-RefetchContainer.md b/website/versioned_docs/version-v10.1.1/Modern-RefetchContainer.md index 7ce0d14e45417..51c2c44db8941 100644 --- a/website/versioned_docs/version-v10.1.1/Modern-RefetchContainer.md +++ b/website/versioned_docs/version-v10.1.1/Modern-RefetchContainer.md @@ -16,13 +16,11 @@ Table of Contents: `createRefetchContainer` has the following signature: ```javascript - createRefetchContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, refetchQuery: GraphQLTaggedNode, ): ReactComponentClass; - ``` ### Arguments @@ -37,7 +35,6 @@ createRefetchContainer( The Component resulting from `createRefetchContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -45,7 +42,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -61,7 +57,6 @@ type Props = { `refetch` has the following signature: ```javascript - type RefetchOptions = { force?: boolean, }; @@ -102,7 +97,6 @@ Returns a `Disposable` on which you could call `dispose()` to cancel the refetch In this simple example, let's assume we want to fetch the latest data for a `TodoItem` from the server: ```javascript - // TodoItem.js import {createRefetchContainer, graphql} from 'react-relay'; @@ -148,7 +142,6 @@ export default createRefetchContainer( } ` ); - ``` ### Loading more data @@ -156,7 +149,6 @@ export default createRefetchContainer( In this example we are using a Refetch Container to fetch more stories in a story feed component. ```javascript - import {createRefetchContainer, graphql} from 'react-relay'; class FeedStories extends React.Component { @@ -212,5 +204,4 @@ export default createRefetchContainer( } `, ); - ``` diff --git a/website/versioned_docs/version-v10.1.1/Modern-RelayCompat.md b/website/versioned_docs/version-v10.1.1/Modern-RelayCompat.md index 36632d3a8f1a1..f47dbd845ba3e 100644 --- a/website/versioned_docs/version-v10.1.1/Modern-RelayCompat.md +++ b/website/versioned_docs/version-v10.1.1/Modern-RelayCompat.md @@ -31,7 +31,6 @@ Relay Modern. The components using Relay Compat can be referred to by both other Relay Modern and Relay Classic components. ```javascript - const {createFragmentContainer, graphql} = require('react-relay/compat'); class TodoItem extends React.Component { @@ -47,5 +46,4 @@ module.exports = createFragmentContainer(TodoItem, graphql` isComplete } `); - ``` diff --git a/website/versioned_docs/version-v10.1.1/Modern-RelayEnvironment.md b/website/versioned_docs/version-v10.1.1/Modern-RelayEnvironment.md index 27d90b2fc4fe1..99e728bce740d 100644 --- a/website/versioned_docs/version-v10.1.1/Modern-RelayEnvironment.md +++ b/website/versioned_docs/version-v10.1.1/Modern-RelayEnvironment.md @@ -12,7 +12,6 @@ Most applications will create a single Environment instance and use it throughou To create an environment instance in Relay Modern, use the `RelayModernEnvironment` class: ```javascript - const { Environment, Network, @@ -30,7 +29,6 @@ const environment = new Environment({ network, store, }); - ``` For more details on creating a Network, see the [NetworkLayer guide](./network-layer). @@ -44,7 +42,6 @@ The example above did not configure a `handlerProvider`, which means that a defa If you wish to provide your own `handlerProvider`, you can do so: ```javascript - const { ConnectionHandler, } = require('relay-runtime'); @@ -58,5 +55,4 @@ function handlerProvider(handle) { `handlerProvider: No handler provided for ${handle}` ); } - ``` diff --git a/website/versioned_docs/version-v10.1.1/Modern-RelayStore.md b/website/versioned_docs/version-v10.1.1/Modern-RelayStore.md index 6bb2e3744d55b..38f88c7f69edb 100644 --- a/website/versioned_docs/version-v10.1.1/Modern-RelayStore.md +++ b/website/versioned_docs/version-v10.1.1/Modern-RelayStore.md @@ -16,7 +16,6 @@ Table of Contents: The `RecordSourceSelectorProxy` is the type of the `store` that [`updater` functions](./mutations#using-updater-and-optimisticupdater) receive as an argument. The following is the `RecordSourceSelectorProxy` interface: ```javascript - interface RecordSourceSelectorProxy { create(dataID: string, typeName: string): RecordProxy; delete(dataID: string): void; @@ -26,7 +25,6 @@ interface RecordSourceSelectorProxy { getPluralRootField(fieldName: string): ?Array; invalidateStore(): void; } - ``` ### `create(dataID: string, typeName: string): RecordProxy` @@ -36,9 +34,7 @@ Creates a new record in the store given a `dataID` and the `typeName` as defined #### Example ```javascript - const record = store.create(dataID, 'Todo'); - ``` ### `delete(dataID: string): void` @@ -48,9 +44,7 @@ Deletes a record from the store given its `dataID`. #### Example ```javascript - store.delete(dataID); - ``` ### `get(dataID: string): ?RecordProxy` @@ -60,9 +54,7 @@ Retrieves a record from the store given its `dataID`. Returns a [`RecordProxy`]( #### Example ```javascript - const record = store.get(dataID); - ``` ### `getRoot(): RecordProxy` @@ -74,20 +66,16 @@ Returns the [`RecordProxy`](#recordproxy) representing the root of the GraphQL d Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - // Represents root query const root = store.getRoot(); - ``` ### `getRootField(fieldName: string): ?RecordProxy` @@ -99,19 +87,15 @@ Retrieves a root field from the store given the `fieldName`, as defined by the G Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - const viewer = store.getRootField('viewer'); - ``` ### `getPluralRootField(fieldName: string): ?Array` @@ -123,19 +107,15 @@ Retrieves a root field that represents a collection from the store given the `fi Given the GraphQL document: ```graphql - nodes(first: 10) { # ... } - ``` Usage: ```javascript - const nodes = store.getPluralRootField('nodes'); - ``` ### `invalidateStore(): void` @@ -145,15 +125,12 @@ Globally invalidates the Relay store. This will cause any data that was written #### Example ```javascript - store.invalidateStore(); - ``` After global invalidation, any query that is checked before refetching it will be considered stale: ```javascript - environment.check(query) === 'stale' ``` @@ -163,7 +140,6 @@ environment.check(query) === 'stale' The `RecordProxy` serves as an interface to mutate records: ```javascript - interface RecordProxy { copyFieldsFrom(sourceRecord: RecordProxy): void; getDataID(): string; @@ -189,7 +165,6 @@ interface RecordProxy { setValue(value: mixed, name: string, arguments?: ?Object): RecordProxy; invalidateRecord(): void; } - ``` ### `getDataID(): string` @@ -199,9 +174,7 @@ Returns the dataID of the current record. #### Example ```javascript - const id = record.getDataID(); - ``` ### `getType(): string` @@ -211,7 +184,6 @@ Gets the type of the current record, as defined by the GraphQL schema. #### Example ```javascript - const type = user.getType(); // User ``` @@ -225,20 +197,16 @@ Gets the value of a field in the current record given the field name. Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - const name = viewer.getValue('name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. @@ -248,20 +216,16 @@ Optionally, if the field takes arguments, you can pass a bag of `variables`. Given the GraphQL document: ```graphql - viewer { id name(arg: $arg) } - ``` Usage: ```javascript - const name = viewer.getValue('name', {arg: 'value'}); - ``` ### `getLinkedRecord(name: string, arguments?: ?Object): ?RecordProxy` @@ -273,23 +237,19 @@ Retrieves a record associated with the current record given the field name, as d Given the GraphQL document: ```graphql - rootField { viewer { id name } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -299,22 +259,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { viewer(arg: $arg) { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {arg: 'value'}); - ``` ### `getLinkedRecords(name: string, arguments?: ?Object): ?Array` @@ -326,22 +282,18 @@ Retrieves the set of records associated with the current record given the field Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const nodes = rootField.getLinkedRecords('nodes'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -351,22 +303,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { nodes(first: $count) { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {count: 10}); - ``` ### `getOrCreateLinkedRecord(name: string, typeName: string, arguments?: ?Object)` @@ -378,19 +326,16 @@ Retrieves the a record associated with the current record given the field name, Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = rootField.getOrCreateLinkedRecord('viewer', 'User'); // Will create if it doesn't exist @@ -405,28 +350,22 @@ Mutates the current record by setting a new value on the specified field. Return Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - viewer.setValue('New Name', 'name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. ```javascript - viewer.setValue('New Name', 'name', {arg: 'value'}); - ``` ### `copyFieldsFrom(sourceRecord: RecordProxy): void` @@ -436,7 +375,6 @@ Mutates the current record by copying the fields over from the passed in record #### Example ```javascript - const record = store.get(id1); const otherRecord = store.get(id2); record.copyFieldsFrom(otherRecord); // Mutates `record` @@ -452,19 +390,16 @@ Mutates the current record by setting a new linked record on the given the field Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = store.create(/* ... */)'' rootField.setLinkedRecord(newViewer, 'viewer'); // @@ -482,19 +417,16 @@ Mutates the current record by setting a new set of linked records on the given t Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newNode = store.create(/* ... */); const newNodes = [...rootField.getLinkedRecords('nodes'), newNode]; @@ -511,16 +443,13 @@ Invalidates the record. This will cause any query that references this record to #### Example ```javascript - const record = store.get('4'); record.invalidateRecord(); - ``` After invalidating a record, any query that references the invalidated record and that is checked before refetching it will be considered stale: ```javascript - environment.check(query) === 'stale' ``` @@ -530,7 +459,6 @@ environment.check(query) === 'stale' `ConnectionHandler` is a utility module exposed by `relay-runtime` that aids in the manipulation of connections. `ConnectionHandler` exposes the following interface: ```javascript - interface ConnectionHandler { getConnection( record: RecordProxy, @@ -555,7 +483,6 @@ interface ConnectionHandler { ): void, deleteNode(connection: RecordProxy, nodeID: string): void } - ``` ### `getConnection(record: RecordProxy, key: string, filters?: ?Object)` @@ -565,7 +492,6 @@ Given a record and a connection key, and optionally a set of filters, `getConnec First, let's take a look at a plain connection: ```graphql - fragment FriendsFragment on User { friends(first: 10) { edges { @@ -575,26 +501,22 @@ fragment FriendsFragment on User { } } } - ``` Accessing a plain connection field like this is the same as other regular field: ```javascript - // The `friends` connection record can be accessed with: const user = store.get(userID); const friends = user && user.getLinkedRecord('friends'); // Access fields on the connection: const edges = friends && friends.getLinkedRecords('edges'); - ``` In a [pagination container](./pagination-container), we usually annotate the actual connection field with `@connection` to tell Relay which part needs to be paginated: ```graphql - fragment FriendsFragment on User { friends(first: 10, orderby: "firstname") @connection( key: "FriendsFragment_friends", @@ -606,7 +528,6 @@ fragment FriendsFragment on User { } } } - ``` For connections like the above, `ConnectionHandler` helps us find the record: @@ -624,7 +545,6 @@ const friends = ConnectionHandler.getConnection( ); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` ### Edge creation and insertion @@ -654,7 +574,6 @@ ConnectionHandler.insertEdgeAfter(friends, edge); // No cursor provided, Insert the edge at the front: ConnectionHandler.insertEdgeBefore(friends, edge); - ``` ### `deleteNode(connection: RecordProxy, nodeID: string): void` @@ -668,5 +587,4 @@ Given a connection, deletes any edges whose id matches the given id. const user = store.get(userID); const friends = ConnectionHandler.getConnection(user, 'friends'); ConnectionHandler.deleteNode(friends, idToDelete); - ``` diff --git a/website/versioned_docs/version-v10.1.1/Modern-Subscriptions.md b/website/versioned_docs/version-v10.1.1/Modern-Subscriptions.md index 671b28f684403..85ade0f34c511 100644 --- a/website/versioned_docs/version-v10.1.1/Modern-Subscriptions.md +++ b/website/versioned_docs/version-v10.1.1/Modern-Subscriptions.md @@ -6,7 +6,6 @@ original_id: subscriptions Relay exposes the following APIs to create subscriptions. ```javascript - import { requestSubscription } from 'react-relay'; type Variables = {[name: string]: any}; @@ -28,7 +27,6 @@ requestSubscription( cacheConfig?: CacheConfig, }, ) => Disposable; - ``` The function returns a `Disposable` on which you could call `dispose()` to cancel the refetch. @@ -55,7 +53,6 @@ appropriate when you are only changing the properties of existing records that can be identified by their `id`: ```javascript - import { requestSubscription, graphql, @@ -89,7 +86,6 @@ requestSubscription( onError: error => console.error(error), } ); - ``` # Configure Network @@ -97,7 +93,6 @@ requestSubscription( You will need to Configure your [Network](./network-layer) to handle subscriptions. The below example uses [subscriptions-transport-ws](https://github.com/apollographql/subscriptions-transport-ws): ```javascript - import { ... Network, @@ -134,7 +129,6 @@ Relay's in-memory cache when each subscription response is received. To do so, pass an `updater` function: ```javascript - import { ConnectionHandler } from 'relay-runtime'; requestSubscription( @@ -160,5 +154,4 @@ requestSubscription( }, }, ); - ``` diff --git a/website/versioned_docs/version-v10.1.1/Modern-TestingRelayComponents.md b/website/versioned_docs/version-v10.1.1/Modern-TestingRelayComponents.md index da8f520bd7917..91003cab931f2 100644 --- a/website/versioned_docs/version-v10.1.1/Modern-TestingRelayComponents.md +++ b/website/versioned_docs/version-v10.1.1/Modern-TestingRelayComponents.md @@ -65,7 +65,6 @@ MockPayloadGenerator may drastically simplify the process of creating and mainta Example of a simple Mock Resolver: ```javascript - { ID() { // Return mock value for a scalar filed with type ID @@ -76,13 +75,11 @@ Example of a simple Mock Resolver: return "Lorem Ipsum" } } - ``` It is possible to define more resolvers for Object types ```javascript - { // This will be the default values for User object in the query response User() { @@ -95,7 +92,6 @@ It is possible to define more resolvers for Object types }; }, } - ``` ### Mock Resolver Context @@ -103,7 +99,6 @@ It is possible to define more resolvers for Object types The first argument of the MockResolver is the object that contains Mock Resolver Context. It is possible to return dynamic values from mock resolvers based on the context - for instance, name or alias of the field, a path in the selection, arguments, or parent type. ```javascript - { String(context) { if (context.name === 'zip') { @@ -117,7 +112,6 @@ The first argument of the MockResolver is the object that contains Mock Resolver } } } - ``` ### ID Generation @@ -125,14 +119,12 @@ The first argument of the MockResolver is the object that contains Mock Resolver The second argument of the Mock Resolver its a function that will generate a sequence of integers, useful to generate unique ids in the tests ```javascript - { // will generate strings "my-id-1", "my-id-2", etc. ID(_, generateId) { return `my-id-${generateId()}`; }, } - ``` ### @relay_test_operation @@ -142,7 +134,6 @@ Most of GraphQL type information for a specific field in the selection is not av Operation with the @relay_test_operation directive will have additional metadata that will contain GraphQL type info for fields in the operation's selection. And it will improve the quality of the generated data. You also will be able to define Mock resolvers for Scalar (not only ID and String) and Abstract types: ```javascript - { Float() { return 123.456; @@ -160,7 +151,6 @@ Operation with the @relay_test_operation directive will have additional metadata }; } } - ``` ## Examples @@ -170,7 +160,6 @@ Operation with the @relay_test_operation directive will have additional metadata Using `createMockEnvironment` and `MockPayloadGenerator` allows writing concise tests for components that are using Relay Containers and Renderers. Both those modules can be imported from `relay-test-utils` ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { @@ -223,7 +212,6 @@ test('Error State', () => { renderer.root.find(item => (item.props.testID = 'errorMessage')), ).toBeDefined(); }); - ``` ### Fragment Container Tests @@ -231,7 +219,6 @@ test('Error State', () => { Essentially, in the example above will `resolveMostRecentOperation` will generate data for all child fragment containers (pagination, refetch). But, usually the Root Components container may have many child fragment components and you may want to exercise a specific Fragment Container. The solution for that would be to wrap your fragment container with the QueryRenderer that renders a Query that's spreads fragments from your fragment container. ```javascript - test('Fragment Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -262,7 +249,6 @@ test('Fragment Container', () => { expect(renderer).toMatchSnapshot(); }); - ``` ### Pagination Container Test @@ -270,7 +256,6 @@ test('Fragment Container', () => { Essentially, tests for Pagination container are not different from Fragment Container tests. But we can do more here, we can actually see how the pagination works - we can assert the behavior of our components when performing pagination (load more, refetch). ```javascript - // Pagination Example test('Pagination Container', () => { const environment = createMockEnvironment(); @@ -344,7 +329,6 @@ test('Pagination Container', () => { We can use similar approach here with wrapping container with Query Renderer. And for the sake of completeness, we will add example here: ```javascript - test('Refetch Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -386,7 +370,6 @@ test('Refetch Container', () => { ); // expect(renderer).toMatchSnapshot(); }); - ``` ### Mutations @@ -394,7 +377,6 @@ test('Refetch Container', () => { Mutations itself are operations so we can test them independently (unit-test) for specific mutation, or in combination with the view from which this mutation is called. ```javascript - // Say, you have a mutation function function sendMutation(environment, onCompleted, onError, variables) commitMutation(environment, { @@ -417,7 +399,6 @@ test('it should send mutation', () => { ); expect(onCompleted).toBeCalled(); }); - ``` ### Subscription @@ -425,7 +406,6 @@ test('it should send mutation', () => { We can test subscription in a similar way we test mutations ```javascript - // Example subscribe function function subscribe(environment, onNext, onError, variables) requestSubscription(environment, { @@ -448,7 +428,6 @@ test('it should subscribe', () => { ); expect(onNext).toBeCalled(); }); - ``` ### Example with `queueOperationResolver` @@ -456,7 +435,6 @@ test('it should subscribe', () => { With `queueOpeararionResolver` it possible to define responses for operations that will be executed on the environment ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { diff --git a/website/versioned_docs/version-v10.1.1/Modern-TypeEmission.md b/website/versioned_docs/version-v10.1.1/Modern-TypeEmission.md index 63614b869a322..4ff63e4a7d81b 100644 --- a/website/versioned_docs/version-v10.1.1/Modern-TypeEmission.md +++ b/website/versioned_docs/version-v10.1.1/Modern-TypeEmission.md @@ -16,7 +16,6 @@ In this example the emitted type-information would require the variables object #### Flow ```javascript - /** * export type ExampleQueryVariables = {| * +artistID: string @@ -44,7 +43,6 @@ const variables: ExampleQueryVariables = { #### TypeScript ```javascript - /** * export type ExampleQueryVariables = { * readonly artistID: string @@ -79,7 +77,6 @@ In this example the emitted type-information describes the response data availab #### Flow ```javascript - /** * export type ExampleQueryResponse = {| * +artist: ?{| @@ -110,7 +107,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * export type ExampleQueryResponse = { * readonly artist?: { @@ -146,7 +142,6 @@ Similarly, in this example the emitted type-information describes the prop data #### Flow ```javascript - /** * export type ExampleFragment_artist = {| * +name: string @@ -172,7 +167,6 @@ export const ExampleFragment = createFragmentContainer( #### TypeScript ```javascript - /** * export type ExampleFragment_artist = { * readonly name: string @@ -206,7 +200,6 @@ Consider a component that composes the above fragment container example. In this #### Flow ```javascript - /** * import type { FragmentReference } from "relay-runtime"; * declare export opaque type ExampleFragment_artist$ref: FragmentReference; @@ -250,7 +243,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * declare const _ExampleFragment_artist$ref: unique symbol; * export type ExampleFragment_artist$ref = typeof _ExampleFragment_artist$ref; @@ -315,7 +307,6 @@ $ relay-compiler --artifactDirectory ./src/__generated__ […] ["relay", { "artifactDirectory": "./src/__generated__" }] ] } - ``` It is recommended to alias this directory in your module resolution configuration such that you don’t need to specify relative paths in your source files. This is what is also done in the above examples, where artifacts are imported from a `__generated__` alias, rather than relative paths like `../../../../__generated__`. diff --git a/website/versioned_docs/version-v10.1.1/Modern-UpgradingSetVariables.md b/website/versioned_docs/version-v10.1.1/Modern-UpgradingSetVariables.md index d5b086fafce20..ff73feec04f8b 100644 --- a/website/versioned_docs/version-v10.1.1/Modern-UpgradingSetVariables.md +++ b/website/versioned_docs/version-v10.1.1/Modern-UpgradingSetVariables.md @@ -36,7 +36,6 @@ fragment on User { # ... } } - ``` This should be upgraded to use a [`PaginationContainer`](./pagination-container). @@ -61,7 +60,6 @@ fragment on User { # ... } } - ``` This can be upgraded by using a [`RefetchContainer`](./refetch-container) which allows you to specify the exact query to use to fetch the new data. @@ -86,7 +84,6 @@ fragment on FeedbackTarget { # ... } } - ``` This can be upgraded by conditionally rendering a [`QueryRenderer`](./query-renderer) which will load the data once it is rendered. The code overhead of doing this is dramatically reduced with the new API. diff --git a/website/versioned_docs/version-v10.1.1/Modern-fetchQuery.md b/website/versioned_docs/version-v10.1.1/Modern-fetchQuery.md index 2e9461ad527bd..c1a06ab7d2493 100644 --- a/website/versioned_docs/version-v10.1.1/Modern-fetchQuery.md +++ b/website/versioned_docs/version-v10.1.1/Modern-fetchQuery.md @@ -6,7 +6,6 @@ original_id: fetch-query You can use the `fetchQuery` function to imperatively make GraphQL Requests. This is useful for cases where you want to make requests outside of React but still utilize the Relay store and network layer. ```javascript - import {fetchQuery, graphql} from 'relay-runtime'; const query = graphql` @@ -25,7 +24,6 @@ fetchQuery(environment, query, variables) .then(data => { // access the graphql response }); - ``` ## Arguments diff --git a/website/versioned_docs/version-v10.1.1/PrinciplesAndArchitecture-Compiler.md b/website/versioned_docs/version-v10.1.1/PrinciplesAndArchitecture-Compiler.md index c195491682b1f..fcd0490cb724f 100644 --- a/website/versioned_docs/version-v10.1.1/PrinciplesAndArchitecture-Compiler.md +++ b/website/versioned_docs/version-v10.1.1/PrinciplesAndArchitecture-Compiler.md @@ -74,7 +74,6 @@ foo { # type FooType foo { id } - ``` - `SkipRedundantNodeTransform`: A more advanced version of flattening, this eliminates more complex cases of field duplication such as when a field is fetched both unconditionally and conditionally, or is fetched by two different sub-fragments. For example: @@ -97,7 +96,6 @@ foo { id } } - ``` - `GenerateRequisiteFieldTransform`: This optional, Relay-specific transform inserts `id` fields for globally identifiable objects and `__typename` fields wherever the type cannot be statically determined (e.g. for unions). diff --git a/website/versioned_docs/version-v10.1.1/PrinciplesAndArchitecture-Runtime.md b/website/versioned_docs/version-v10.1.1/PrinciplesAndArchitecture-Runtime.md index 9491d290c146f..e9221631a701d 100644 --- a/website/versioned_docs/version-v10.1.1/PrinciplesAndArchitecture-Runtime.md +++ b/website/versioned_docs/version-v10.1.1/PrinciplesAndArchitecture-Runtime.md @@ -77,7 +77,6 @@ RecordSource { city: 'Seattle', } } - ``` [1] Note that GraphQL itself does not impose this constraint, and Relay Runtime may also be used for schemas that do not conform to it. For example, both systems can be used to query a single denormalized table. However, many of the features that Relay Runtime provides, such as caching and normalization, work best when the data is represented as a normalized graph with stable identities for discrete pieces of information. diff --git a/website/versioned_docs/version-v10.1.1/PrinciplesAndArchitecture-ThinkingInGraphQL.md b/website/versioned_docs/version-v10.1.1/PrinciplesAndArchitecture-ThinkingInGraphQL.md index a8842ae084922..9ff8a7840df90 100644 --- a/website/versioned_docs/version-v10.1.1/PrinciplesAndArchitecture-ThinkingInGraphQL.md +++ b/website/versioned_docs/version-v10.1.1/PrinciplesAndArchitecture-ThinkingInGraphQL.md @@ -12,7 +12,6 @@ In this article we'll explore what it means to build a GraphQL client framework Imagine we have a simple application that fetches a list of stories, and some details about each one. Here's how that might look in resource-oriented REST: ```javascript - // Fetch the list of story IDs but not their details: rest.get('/stories').then(stories => // This resolves to a list of items with linked resources: @@ -25,13 +24,11 @@ rest.get('/stories').then(stories => // `[ { id: "...", text: "..." } ]` console.log(stories); }); - ``` Note that this approach requires _n+1_ requests to the server: 1 to fetch the list, and _n_ to fetch each item. With GraphQL we can fetch the same data in a single network request to the server (without creating a custom endpoint that we'd then have to maintain): ```javascript - graphql.get(`query { stories { id, text } }`).then( stories => { // A list of story items: @@ -39,7 +36,6 @@ graphql.get(`query { stories { id, text } }`).then( console.log(stories); } ); - ``` So far we're just using GraphQL as a more efficient version of typical REST approaches. Note two important benefits in the GraphQL version: @@ -56,7 +52,6 @@ Repeatedly refetching information from the server can get quite slow. For exampl In a resource-oriented REST system, we can maintain a **response cache** based on URIs: ```javascript - var _cache = new Map(); rest.get = uri => { if (!_cache.has(uri)) { @@ -64,13 +59,11 @@ rest.get = uri => { } return _cache.get(uri); }; - ``` Response-caching can also be applied to GraphQL. A basic approach would work similarly to the REST version. The text of the query itself can be used as a cache key: ```javascript - var _cache = new Map(); graphql.get = queryText => { if (!_cache.has(queryText)) { @@ -78,7 +71,6 @@ graphql.get = queryText => { } return _cache.get(queryText); }; - ``` Now, requests for previously cached data can be answered immediately without making a network request. This is a practical approach to improving the perceived performance of an application. However, this method of caching can cause problems with data consistency. @@ -90,7 +82,6 @@ With GraphQL it is very common for the results of multiple queries to overlap. H ``` query { stories { id, text, likeCount } } - ``` and then later refetch one of the stories whose `likeCount` has since been incremented: @@ -98,7 +89,6 @@ and then later refetch one of the stories whose `likeCount` has since been incre ``` query { story(id: "123") { id, text, likeCount } } - ``` We'll now see different `likeCount`s depending on how the story is accessed. A view that uses the first query will see an outdated count, while a view using the second query will see the updated count. @@ -119,7 +109,6 @@ query { } } } - ``` And here's a possible response: @@ -134,13 +123,11 @@ query: { } } } - ``` Although the response is hierarchical, we'll cache it by flattening all the records. Here is an example of how Relay would cache this query response: ```javascript - Map { // `story(id: "1")` 1: Map { @@ -152,7 +139,6 @@ Map { name: 'Jan', }, }; - ``` This is only a simple example: in reality the cache must handle one-to-many associations and pagination (among other things). @@ -182,7 +168,6 @@ The first query was for a list of stories: ``` query { stories { id, text, likeCount } } - ``` With a normalized response cache, a record would be created for each story in the list. The `stories` field would store links to each of these records. @@ -192,7 +177,6 @@ The second query refetched the information for one of those stories: ``` query { story(id: "123") { id, text, likeCount } } - ``` When this response is normalized, Relay can detect that this result overlaps with existing data based on its `id`. Rather than create a new record, Relay will update the existing `123` record. The new `likeCount` is therefore available to _both_ queries, as well as any other query that might reference this story. @@ -215,7 +199,6 @@ query { } } } - ``` After initially fetching this story our cache might be as follows. Note that the story and comment both link to the same record as `author`: @@ -242,7 +225,6 @@ Map { author: Link(2), }, } - ``` The author of this story also commented on it — quite common. Now imagine that some other view fetches new information about the author, and her profile photo has changed to a new URI. Here's the _only_ part of our cached data that changes: @@ -256,7 +238,6 @@ Map { photo: 'http://.../photo2.jpg', }, } - ``` The value of the `photo` field has changed; and therefore the record `2` has also changed. And that's it. Nothing else in the _cache_ is affected. But clearly our _view_ needs to reflect the update: both instances of the author in the UI (as story author and comment author) need to show the new photo. @@ -273,7 +254,6 @@ ImmutableMap { }, 3: ImmutableMap // same as before } - ``` If we replace `2` with a new immutable record, we'll also get a new immutable instance of the cache object. However, records `1` and `3` are untouched. Because the data is normalized, we can't tell that `story`'s contents have changed just by looking at the `story` record alone. @@ -299,7 +279,6 @@ mutation StoryLike($storyID: String) { likeCount } } - ``` Notice that we're querying for data that _may_ have changed as a result of the mutation. An obvious question is: why can't the server just tell us what changed? The answer is: it's complicated. GraphQL abstracts over _any_ data storage layer (or an aggregation of multiple sources), and works with any programming language. Furthermore, the goal of GraphQL is to provide data in a form that is useful to product developers building a view. diff --git a/website/versioned_docs/version-v10.1.1/PrinciplesAndArchitecture-ThinkingInRelay.md b/website/versioned_docs/version-v10.1.1/PrinciplesAndArchitecture-ThinkingInRelay.md index e61f3fd21c933..62b1914ef3ff9 100644 --- a/website/versioned_docs/version-v10.1.1/PrinciplesAndArchitecture-ThinkingInRelay.md +++ b/website/versioned_docs/version-v10.1.1/PrinciplesAndArchitecture-ThinkingInRelay.md @@ -30,13 +30,11 @@ fragment Story_story on Story { photo } } - ``` And this fragment can then be used to define the Story container: ```javascript - const {createFragmentContainer, graphql} = require('react-relay'); // Plain React component. @@ -64,7 +62,6 @@ const StoryContainer = createFragmentContainer(Story, { In React, rendering a view requires two inputs: the _component_ to render, and a _root_ DOM (UI) node to render into. Rendering Relay containers is similar: we need a _container_ to render, and a _root_ in the graph from which to start our query. We also must ensure that the queries for the container are executed and may want to show a loading indicator while data is being fetched. Similar to `ReactDOM.render(component, domNode)`, Relay provides `` for this purpose. The `query` and `variables` define what data to fetch and `render` defines what to render. Here's how we might render ``: ```javascript - ReactDOM.render( { ); } } - ``` The above code is doing something very similar to our [previous example](#rendering-graphql-queries). However, we are now passing a `$userID` variable to the GraphQL query via the `variables` prop. This has a couple of important implications: @@ -228,7 +216,6 @@ Now that we know how to define and fetch queries, let's actually start building First, let's start at the bottom. Suppose that we want to render a component that simply displays a given todo item's text and completed state: ```javascript - // Todo.js import React from 'react'; @@ -258,7 +245,6 @@ export default class Todo extends React.Component { ); } } - ``` From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L112), we know that we can query this data on the `Todo` type. However, we don't want to have to send a separate query for each todo item; that would defeat the purpose of using GraphQL over a traditional REST API. We could manually query for these fields directly in our `QueryRenderer` query, but that would hurt re-usability: what if we want to query the same set of fields as part of a different query? Additionally, we wouldn't know which component needs the data we're querying, which is a problem Relay directly tries to address. @@ -266,18 +252,15 @@ From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/dat Instead, we can define a reusable [Fragment](http://graphql.org/learn/queries/#fragments), which allows us to define a set of fields on a type and reuse them within our queries wherever we need to: ```graphql - fragment TodoItemFragment on Todo { complete text } - ``` Our component can then use this fragment to declare its data dependency on the `Todo` GraphQL type: ```javascript - // Todo.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -340,7 +323,6 @@ Before proceeding, don't forget to run the Relay Compiler with `yarn relay`. Given that [Fragment Containers](./fragment-container) are just React components, we can compose them as such. We can even re-use fragment containers within other fragment containers. As an example, let's see how we would define a `TodoList` component that just renders a list of todo items, and whether all have been completed or not: ```javascript - // TodoList.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -401,7 +383,6 @@ export default createFragmentContainer( `, }, ); - ``` As with the first fragment container we defined, `TodoList` declares its data dependencies via a fragment. However, this component additionally re-uses the fragment previously defined by the `Todo` component, and passes the appropriate data when rendering the child `Todo` components (a.k.a. fragment containers). @@ -416,7 +397,6 @@ fragment containers do not directly fetch data. Instead, containers declare a sp A `QueryRenderer` rendering these fragment containers could look like the following: ```javascript - // ViewerTodoList.js import React from 'react'; import {graphql, QueryRenderer} from 'react-relay'; @@ -457,7 +437,6 @@ export default class ViewerTodoList extends React.Component { ); } } - ``` Check out our docs for [Fragment Containers](./fragment-container) for more details, and our guides on [Refetch](./refetch-container) and [Pagination](./pagination-container) for more advanced usage of containers. @@ -469,7 +448,6 @@ Now that we know how to query for and render data, let's move on to changing our From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L35), we know that we have some mutations available to us, so let's start by writing a mutation to change the `complete` status of a given todo item (i.e. mark or unmark it as done): ```graphql - mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { changeTodoStatus(input: $input) { todo { @@ -478,7 +456,6 @@ mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { } } } - ``` This mutation allows us to query back some data as a [result of the mutation](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L18), so we're going to query for the updated `complete` status on the todo item. @@ -486,7 +463,6 @@ This mutation allows us to query back some data as a [result of the mutation](ht In order to execute this mutation in Relay, we're going to write a new mutation using Relay's `commitMutation` api: ```javascript - // ChangeTodoStatusMutation.js import {graphql, commitMutation} from 'react-relay'; @@ -520,7 +496,6 @@ function commit( } export default {commit}; - ``` Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mutation to the server and, in our case, upon receiving a response it will automatically update the local data store with the latest data from the server. This also means that upon receiving the response, Relay will ensure that any components (i.e. containers) that depend on the updated data are re-rendered. @@ -528,7 +503,6 @@ Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mut In order to actually use this mutation in our component, we could update our `Todo` component in the following way: ```javascript - // Todo.js // ... @@ -562,7 +536,6 @@ In order to make the experience better, we can configure our mutation to do an o In Relay, there's a couple of options we can pass to `commitMutation` to enable optimistic updates. Let's see what that would look like in our `ChangeTodoStatusMutation`: ```javascript - // ChangeTodoStatusMutation.js // ... @@ -597,7 +570,6 @@ function commit( } export default {commit}; - ``` In the simplest case above, we just need to pass an `optimisticResponse` option, which should refer to an object having the same shape as the mutation response payload. When we pass this option, Relay will know to immediately update our local data with the optimistic response, and then update it with the actual server response or roll it back if an error occurs. diff --git a/website/versioned_docs/version-v10.1.2/Modern-ConvertingMutations.md b/website/versioned_docs/version-v10.1.2/Modern-ConvertingMutations.md index 08ad2e998cb2d..8f4bdc1d8e0d2 100644 --- a/website/versioned_docs/version-v10.1.2/Modern-ConvertingMutations.md +++ b/website/versioned_docs/version-v10.1.2/Modern-ConvertingMutations.md @@ -12,19 +12,16 @@ FatQueries in Relay Classic mutations was a concept that was confusing for a num Example of existing fat query: ```javascript - RelayClassic.QL` fragment on MarkReadNotificationResponsePayload @relay(pattern: true) { notification } `; - ``` Example of converted mutation query: ```javascript - graphql` mutation MarkReadNotificationMutation( $input: MarkReadNotificationData! @@ -37,7 +34,6 @@ graphql` } } `; - ``` ## Migrating Configs @@ -67,7 +63,6 @@ This is no longer needed in Compatibility Mode for neither environments. Simply Take this example of a simple mutation in Relay Classic: ```javascript - class LikeStoryMutation extends RelayClassic.Mutation { getMutation() { return RelayClassic.QL`mutation {likeStory}`; @@ -106,7 +101,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { `, }; } - ``` ### Converting `getMutation()` and `getFatQuery()` @@ -114,7 +108,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { We combine these two into a regular GraphQL mutation, which list out specific fields that needs to be updated. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story(data: $input) { @@ -126,7 +119,6 @@ const mutation = graphql` } } `; - ``` ### Converting `getConfigs()` @@ -138,13 +130,11 @@ As specified above, `FIELDS_CHANGE` configs can be omitted. To convert `getVariables()`, we take the return value from the original function and wrap it in an object that contains a property that matches the variable name for the mutation. In this case, the mutation has a `input` variable that is of type `LikeStoryData`. ```javascript - const variables = { input: { storyID: args.storyID } } - ``` ### Final Result @@ -152,7 +142,6 @@ const variables = { As you can see, our resulting mutation is a lot simpler and more like regular GraphQL than the Relay Classic version we started out with. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story { @@ -178,7 +167,6 @@ function commit(environment: CompatEnvironment, args) { variables, }); } - ``` See [Mutation](./mutations) for additional options on `commitMutation` for more complex mutations. diff --git a/website/versioned_docs/version-v10.1.2/Modern-FragmentContainer.md b/website/versioned_docs/version-v10.1.2/Modern-FragmentContainer.md index 423f446cbb054..6a40bbcfb5d0a 100644 --- a/website/versioned_docs/version-v10.1.2/Modern-FragmentContainer.md +++ b/website/versioned_docs/version-v10.1.2/Modern-FragmentContainer.md @@ -17,12 +17,10 @@ Table of Contents: `createFragmentContainer` has the following signature: ```javascript - createFragmentContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, ): ReactComponentClass; - ``` ### Arguments @@ -43,7 +41,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -58,7 +55,6 @@ To start, let's build the plain React version of a hypothetical `` c Here's a basic implementation of `` that ignores styling in order to highlight the functionality: ```javascript - // TodoItem.js class TodoItem extends React.Component { render() { @@ -78,7 +74,6 @@ class TodoItem extends React.Component { ); } } - ``` ### Data Dependencies With GraphQL @@ -86,7 +81,6 @@ class TodoItem extends React.Component { In Relay, data dependencies are described using [GraphQL](https://github.com/facebook/graphql). For ``, the dependency can be expressed as follows. Note that this exactly matches the shape that the component expected for the `item` prop. ```javascript - graphql` # This fragment only applies to objects of type 'Todo'. fragment TodoItem_item on Todo { @@ -102,7 +96,6 @@ graphql` Given the plain React component and a GraphQL fragment, we can now define a Fragment Container to specify this component's data requirements. Let's look at the code first and then see what's happening: ```javascript - // TodoItem.js import {createFragmentContainer, graphql} from 'react-relay'; @@ -120,7 +113,6 @@ export default createFragmentContainer(TodoItem, { } `, }); - ``` ## Container Composition @@ -134,7 +126,6 @@ Let's explore how this works via a `` component that composes the `< View composition is _exactly_ what you're used to — Relay containers are just standard React components. Here's the `` component: ```javascript - class TodoList extends React.Component { render() { // Expects a `list` with a string `title`, as well as the information @@ -151,7 +142,6 @@ class TodoList extends React.Component { ); } } - ``` ### Composing Fragments @@ -159,7 +149,6 @@ class TodoList extends React.Component { Fragment composition works similarly — a parent container's fragment composes the fragment for each of its children. In this case, `` needs to fetch information about the `Todo`s that are required by ``. ```javascript - class TodoList extends React.Component // as above export default createFragmentContainer(TodoList, { @@ -176,7 +165,6 @@ export default createFragmentContainer(TodoList, { } `, }); - ``` Note that when composing fragments, the type of the composed fragment must match the field on the parent in which it is embedded. For example, it wouldn't make sense to embed a fragment of type `Story` into a parent's field of type `User`. Relay and GraphQL will provide helpful error messages if you get this wrong (and if they aren't helpful, let us know!). @@ -190,7 +178,6 @@ When defining a fragment, you can use the [`@argumentDefinitions`](./graphql-in- For example, let's redefine our `TodoList_list` fragment to take some arguments using `@argumentDefinitions`: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -200,7 +187,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` Any arguments defined inside `@argumentDefinitions` will be local variables available inside the fragment's scope. However, a fragment can also reference global variables that were defined in the root query. @@ -212,11 +198,9 @@ In order to pass arguments to a fragment that has `@argumentDefinitions`, you ne Following our `TodoList_list` example, we would pass arguments to the fragment like so: ```graphql - query TodoListQuery($count: Int, $userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` ## Rendering Containers diff --git a/website/versioned_docs/version-v10.1.2/Modern-GraphQLInRelay.md b/website/versioned_docs/version-v10.1.2/Modern-GraphQLInRelay.md index c4dc8f3463e53..715b119492cc7 100644 --- a/website/versioned_docs/version-v10.1.2/Modern-GraphQLInRelay.md +++ b/website/versioned_docs/version-v10.1.2/Modern-GraphQLInRelay.md @@ -14,7 +14,6 @@ Table of Contents: The `graphql` template tag provided by Relay serves as the mechanism to write queries, fragments, mutations or subscriptions in the [GraphQL](http://graphql.org/learn/) language. For example: ```javascript - import {graphql} from 'react-relay'; graphql` @@ -24,7 +23,6 @@ graphql` } } `; - ``` The result of using the `graphql` template tag is a `GraphQLTaggedNode`; a runtime representation of the GraphQL document which can be used to define [Query Renderers](./query-renderer), [Fragment Containers](./fragment-container), [Refetch Containers](./refetch-container), [Pagination Containers](./pagination-container), etc. @@ -42,11 +40,9 @@ Relay uses directives to add additional information to GraphQL documents, which `@arguments` is a directive used to pass arguments to a fragment that was defined using [`@argumentDefinitions`](#argumentdefinitions). For example: ```graphql - query TodoListQuery($userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -56,7 +52,6 @@ See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fr `@argumentDefinitions` is a directive used to specify arguments taken by a fragment. For example: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -66,7 +61,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -80,7 +74,6 @@ When using the [Pagination Container](./pagination-container), Relay expects con When defining a fragment for use with a Fragment container, you can use the `@relay(plural: true)` directive to indicate that container expects the prop for that fragment to be a list of items instead of a single item. A query or parent that spreads a `@relay(plural: true)` fragment should do so within a plural field (ie a field backed by a [GraphQL list](http://graphql.org/learn/schema/#lists-and-non-null). For example: ```javascript - // Plural fragment definition graphql` fragment TodoItems_items on TodoItem @relay(plural: true) { @@ -95,7 +88,6 @@ fragment TodoApp_app on App { ...TodoItem_items } } - ``` ### `@inline` @@ -107,7 +99,6 @@ Non-React functions can also take advantage of data masking. A fragment can be d In the example below, the function `processItemData` is called from a React component. It requires an item object with a specific set of fields. All React components that use this function should spread the `processItemData_item` fragment to ensure all of the correct item data is loaded for this function. ```javascript - import {graphql, readInlineData} from 'react-relay'; // non-React function called from React @@ -127,11 +118,9 @@ function processItemData(itemRef) { creatorName: item.creator.name }); } - ``` ```javascript - // React Component function MyComponent({item}) { function handleClick() { @@ -151,7 +140,6 @@ export default createFragmentContainer(MyComponent, { } ` }); - ``` ### `@relay(mask: Boolean)` @@ -169,7 +157,6 @@ Keep in mind that it is typically considered an **anti-pattern** to create a sin In the example below, the `user` prop will include the data for `id` and `name` fields wherever `...Component_internUser` is included, instead of Relay's normal behavior to mask those fields: ```javascript - graphql` fragment Component_internUser on InternUser @relay(mask: false) { id @@ -197,7 +184,6 @@ export default createFragmentContainer( } `, ); - ``` ## Relay Compiler @@ -207,7 +193,6 @@ Relay uses the Relay Compiler to convert [`graphql`](#graphql) literals into gen A query like the following: ```javascript - graphql` fragment MyComponent on Type { field @@ -228,12 +213,10 @@ Relay Compiler supports the use of **persisted queries**, in which each version Persisted queries can be enabled by instructing Relay Compiler to emit metadata about each query, mutation, and subscription into a JSON file. The generated file will contain a mapping of query identifiers to query text, which you can then save to your server. To enable persisted queries, use the `--persist-output` flag to the compiler: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` Relay Compiler will then create the id => query text mapping in the path you specify. You can then use this complete @@ -250,7 +233,6 @@ See our relay-compiler section in our [Installation and Setup guide](./installat To use the Relay Compiler, you need either a .graphql or .json GraphQL schema file, describing your GraphQL server's API. Typically these files are local representations of a server source of truth and are not edited directly. For example, we might have a `schema.graphql` like: ```graphql - schema { query: Root } @@ -268,7 +250,6 @@ type WordDefinition { text: String image: String } - ``` ### Source files @@ -284,7 +265,6 @@ For example, given the two files: - `src/Components/DictionaryComponent.js` ```javascript - const DictionaryWordFragment = graphql` fragment DictionaryComponent_word on Word { id @@ -306,7 +286,6 @@ For example, given the two files: - `src/Queries/DictionaryQuery.js` ```javascript - const DictionaryQuery = graphql` query DictionaryQuery { dictionary { @@ -330,9 +309,7 @@ Typically you will not need to import your generated definitions. The [Relay Bab However the Relay Compiler also automatically generates [Flow](https://flow.org) types as [type comments](https://flow.org/en/docs/types/comments/). For example, you can import the generated Flow types like so: ```javascript - import type {DictionaryComponent_word} from './__generated__/DictionaryComponent_word.graphql'; - ``` ### Client schema extensions @@ -342,7 +319,6 @@ The Relay Compiler fully supports client-side schema extensions, which allows yo For example, assuming the server schema `./schema.graphql`: ```graphql - schema { query: Root } @@ -350,28 +326,23 @@ schema { type Root { title: String! } - ``` We can create a `./src/clientSchema.graphql` and define a new type called `Setting`: ```graphql - type Setting { name: String! active: Boolean! } - ``` We can then extend existing server types in the client schema `./src/clientSchema.graphql` with our new `Setting` type, like so: ```graphql - extend type Root { settings: [Setting] } - ``` Any fields specified in the client schema, can be fetched from the [Relay Store](./relay-store), by selecting it in a query or fragment. diff --git a/website/versioned_docs/version-v10.1.2/Modern-LocalStateManagement.md b/website/versioned_docs/version-v10.1.2/Modern-LocalStateManagement.md index da71a0dd33246..3ecbf6801f91c 100644 --- a/website/versioned_docs/version-v10.1.2/Modern-LocalStateManagement.md +++ b/website/versioned_docs/version-v10.1.2/Modern-LocalStateManagement.md @@ -24,23 +24,19 @@ It can even be used to extend an existing server schema. For example, we can create a new type called `Note`: ```graphql - type Note { id: ID! title: String body: String } - ``` And then extend the server schema type `User`, with a list of `Note`, called `notes`. ```graphql - extend type User { notes: [Note] } - ``` ## Querying local state @@ -51,7 +47,6 @@ The field can be from the server schema, or it can be schema agnostic, like an i Here, we use a [QueryRenderer](./query-renderer) to get the current `User` via the `viewer` field, along with their id, name and the local list of notes. ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -97,7 +92,6 @@ const Example = (props) => { /> ); } - ``` ## Mutating local state @@ -111,7 +105,6 @@ To build upon the previous example, let's try creating, updating and deleting a ### Create ```javascript - import {commitLocalUpdate} from 'react-relay'; let tempID = 0; @@ -131,7 +124,6 @@ function createUserNote() { user.setLinkedRecords([...userNoteRecords, newNoteRecord], 'notes'); }); } - ``` Note that since this record will be rendered by the `ExampleQuery` in our `QueryRenderer`, the QueryRenderer will automatically retain this data so it isn't garbage collected. @@ -139,7 +131,6 @@ Note that since this record will be rendered by the `ExampleQuery` in our `Query If no component is rendering the local data and you want to manually retain it, you can do so by calling `environment.retain()`: ```javascript - import {createOperationDescriptor, getRequest} from 'relay-runtime'; // Create a query that references that record @@ -166,13 +157,11 @@ const disposable = environment.retain(operation); // Whenever you don't need that data anymore and it's okay for Relay to garbage collect it, // you can dispose of the retain disposable.dispose(); - ``` ### Update ```javascript - import {commitLocalUpdate} from 'react-relay'; function updateUserNote(dataID, body, title) { @@ -183,13 +172,11 @@ function updateUserNote(dataID, body, title) { note.setValue(title, 'title') }); } - ``` ### Delete ```javascript - import {commitLocalUpdate} from 'react-relay'; function deleteUserNote(dataID) { @@ -207,7 +194,6 @@ function deleteUserNote(dataID) { user.setLinkedRecords(newUserNoteRecords, 'notes'); }); } - ``` ## Initial local state @@ -216,7 +202,6 @@ All new client-side schema fields default to `undefined` value. Often however, y You can use an updater function via `commitLocalUpdate` to prime local state. ```javascript - import {commitLocalUpdate} from 'react-relay'; commitLocalUpdate(environment, store => { @@ -225,5 +210,4 @@ commitLocalUpdate(environment, store => { // initialize user notes to an empty array. user.setLinkedRecords([], 'notes'); }); - ``` diff --git a/website/versioned_docs/version-v10.1.2/Modern-MigrationSetup.md b/website/versioned_docs/version-v10.1.2/Modern-MigrationSetup.md index 66f1145357e25..a89c0e178e0e5 100644 --- a/website/versioned_docs/version-v10.1.2/Modern-MigrationSetup.md +++ b/website/versioned_docs/version-v10.1.2/Modern-MigrationSetup.md @@ -13,13 +13,11 @@ With some additional configuration, the `"relay"` babel plugin can also translat Relay Classic `Relay.QL` literals. Most importantly, include a reference to your GraphQL Schema as either a json file or graphql schema file. ```javascript - { "plugins": [ ["relay", {"schema": "path/schema.graphql"}] ] } - ``` ## Set up babel-plugin-relay for "[compatibility mode](./relay-compat)" @@ -29,13 +27,11 @@ literals can be translated to be usable by _both_ runtimes if configured to use compatibility mode: ```javascript - { "plugins": [ ["relay", {"compat": true, "schema": "path/schema.graphql"}] ] } - ``` ## Additional Options @@ -47,7 +43,6 @@ thrown at runtime. When compiling code for production deployment, the plugin can be configured to immediately throw upon encountering a validation problem. The plugin can be further customized for different environments with the following options: ```javascript - { "plugins": [ ["relay", { @@ -56,5 +51,4 @@ When compiling code for production deployment, the plugin can be configured to i }] ] } - ``` diff --git a/website/versioned_docs/version-v10.1.2/Modern-Mutations.md b/website/versioned_docs/version-v10.1.2/Modern-Mutations.md index bc7545a967717..412672f0bf588 100644 --- a/website/versioned_docs/version-v10.1.2/Modern-Mutations.md +++ b/website/versioned_docs/version-v10.1.2/Modern-Mutations.md @@ -17,7 +17,6 @@ Table of Contents: Use `commitMutation` to create and execute mutations. `commitMutation` has the following signature: ```javascript - commitMutation( environment: Environment, config: { @@ -32,7 +31,6 @@ commitMutation( cacheConfig?: CacheConfig, }, ); - ``` ### Arguments @@ -60,7 +58,6 @@ commitMutation( Example of a simple mutation: ```javascript - import {commitMutation, graphql} from 'react-relay'; const mutation = graphql` @@ -92,7 +89,6 @@ function markNotificationAsRead(environment, storyID) { }, ); } - ``` ## Optimistic Updates @@ -100,7 +96,6 @@ function markNotificationAsRead(environment, storyID) { To improve perceived responsiveness, you may wish to perform an "optimistic update", in which the client immediately updates to reflect the anticipated new value even before the response from the server has come back. The simplest way to do this is by providing an `optimisticResponse` and adding it to the `config` that we pass into `commitMutation`: ```javascript - const mutation = graphql` mutation MarkReadNotificationMutation( $storyID: ID! @@ -129,7 +124,6 @@ commitMutation( variables, }, ); - ``` Another way to enable optimistic updates is via the `optimisticUpdater`, which can be used for more complicated update scenarios. Using `optimisticUpdater` is covered in the section [below](#using-updater-and-optimisticupdater). @@ -151,7 +145,6 @@ Given a `deletedIDFieldName`, Relay will remove the node(s) from the store. #### Example ```javascript - const mutation = graphql` mutation DestroyShipMutation($target: ID!) { destroyShip(target: $target) { @@ -169,7 +162,6 @@ const configs = [{ type: 'NODE_DELETE', deletedIDFieldName: 'destroyedShipId', }]; - ``` ### RANGE_ADD @@ -189,7 +181,6 @@ Given a parent, information about the connection, and the name of the newly crea #### Example ```javascript - const mutation = graphql` mutation AddShipMutation($factionID: ID!, $name: String!) { addShip(factionID: $factionID, name: $name) { @@ -220,7 +211,6 @@ function commit(environment, factionID, name) { }], }); } - ``` ### RANGE_DELETE @@ -242,7 +232,6 @@ from the connection but leave the associated record(s) in the store. #### Example ```javascript - const mutation = graphql` mutation RemoveTagMutation($todoID: ID!, $tagID: ID!) { removeTag(todo: $todoID, tag: $tagID) { @@ -269,7 +258,6 @@ function commit(environment, todoID, tagID) { }], }); } - ``` ## Using updater and optimisticUpdater @@ -287,7 +275,6 @@ When you provide these functions, this is roughly what happens during the mutati Here are a quick example of adding a todo item to a Todo list using this [example schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L36): ```javascript - // AddTodoMutation.js import {commitMutation, graphql} from 'react-relay'; import {ConnectionHandler} from 'relay-runtime'; @@ -371,7 +358,6 @@ function commit(environment, text, user) { }, }); } - ``` For details on how to interact with the Relay Store, please refer to our Relay Store [docs](./relay-store). diff --git a/website/versioned_docs/version-v10.1.2/Modern-NetworkLayer.md b/website/versioned_docs/version-v10.1.2/Modern-NetworkLayer.md index 9dddd36d6c235..c9e069b812b01 100644 --- a/website/versioned_docs/version-v10.1.2/Modern-NetworkLayer.md +++ b/website/versioned_docs/version-v10.1.2/Modern-NetworkLayer.md @@ -8,7 +8,6 @@ In order to know how to access your GraphQL server, Relay Modern requires develo Currently the easiest way to create a network layer is via a helper from the `relay-runtime` package: ```javascript - import { Environment, Network, @@ -50,7 +49,6 @@ const environment = new Environment({ }); export default environment; - ``` Note that this is a basic example to help you get started. This example could be extended with additional features such as request/response caching (enabled e.g. when `cacheConfig.force` is false) and uploading form data for mutations (the `uploadables` parameter). @@ -62,7 +60,6 @@ Relay modern makes no assumptions about what to cache and will garbage collect a You have to implement your own cache strategy. A simple solution is to use `QueryResponseCache` (an in-memory cache): ```javascript - import { Environment, Network, @@ -126,7 +123,6 @@ const environment = new Environment({ }); export default environment; - ``` ## Custom open-source implementations diff --git a/website/versioned_docs/version-v10.1.2/Modern-PaginationContainer.md b/website/versioned_docs/version-v10.1.2/Modern-PaginationContainer.md index 6ac3aac8cfb8e..57980d553af9b 100644 --- a/website/versioned_docs/version-v10.1.2/Modern-PaginationContainer.md +++ b/website/versioned_docs/version-v10.1.2/Modern-PaginationContainer.md @@ -24,7 +24,6 @@ However, when [specifying connection fragments](#createpaginationcontainer) for The purpose of the `@connection` directive is to allow Relay to uniquely identify different connections under a parent type. The `@connection` directive takes 2 arguments that help identify the connection: ```graphql - @connection(key: String!, filters: [String]) ``` @@ -37,7 +36,6 @@ The purpose of the `@connection` directive is to allow Relay to uniquely identif Specifying just the `key`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and the value of `$orderBy` (given that no `filters` were provided) @@ -53,13 +51,11 @@ fragment Feed_user on User { } } } - ``` Specifying `key` and `filters`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and /only/ the value of `$searchTerm`, i.e. @@ -77,7 +73,6 @@ fragment Feed_user on User { } } } - ``` ## `createPaginationContainer` @@ -85,7 +80,6 @@ fragment Feed_user on User { `createPaginationContainer` has the following signature: ```javascript - createPaginationContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, @@ -113,7 +107,6 @@ type ConnectionData = { startCursor: ?string, }, }; - ``` ### Arguments @@ -134,7 +127,6 @@ type ConnectionData = { The Component resulting from `createPaginationContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -145,7 +137,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -160,7 +151,6 @@ type Props = { `hasMore` is a function available on the `relay` [prop](#available-props). This function indicates whether there are more pages to fetch from the server or not. ```javascript - hasMore: () => boolean, ``` @@ -170,7 +160,6 @@ hasMore: () => boolean, `isLoading` is a function available on the `relay` [prop](#available-props). This function indicates if a previous call to [`loadMore()`](#loadmore) is still pending. This is convenient for avoiding duplicate load calls. ```javascript - isLoading: () => boolean, ``` @@ -180,7 +169,6 @@ isLoading: () => boolean, `loadMore` is a function available on the `relay` [prop](#available-props). You can call `loadMore()` to fetch more items from the server based on the `connectionConfig` provided to the container. This will return null if there are no more items to fetch, otherwise it will fetch more items and return a Disposable that can be used to cancel the fetch. ```javascript - loadMore( pageSize: number, callback: ?(error: ?Error) => void, @@ -201,7 +189,6 @@ loadMore( `refetchConnection` is a function available on the `relay` [prop](#available-props). You can call `refetchConnection` to restart pagination on a connection from scratch, with optionally a completely new set of variables to pass to the pagination `query`. This is useful for example if you are paginating over a collection based on a userID and the userID changes, you'd want to start paginating over the new collection for the new user. ```javascript - refetchConnection:( totalCount: number, callback: (error: ?Error) => void, @@ -219,7 +206,6 @@ refetchConnection:( ## Pagination Example ```javascript - // Feed.js import {createPaginationContainer, graphql} from 'react-relay'; @@ -314,5 +300,4 @@ module.exports = createPaginationContainer( ` } ); - ``` diff --git a/website/versioned_docs/version-v10.1.2/Modern-PersistedQueries.md b/website/versioned_docs/version-v10.1.2/Modern-PersistedQueries.md index 137cc2e23220c..ec03b69ba09c3 100644 --- a/website/versioned_docs/version-v10.1.2/Modern-PersistedQueries.md +++ b/website/versioned_docs/version-v10.1.2/Modern-PersistedQueries.md @@ -17,12 +17,10 @@ The relay compiler supports persisted queries which is useful because: In your `npm` script in `package.json`, run the relay compiler using the `--persist-output` flag: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` The `--persist-ouput` flag does 3 things: @@ -31,8 +29,7 @@ The `--persist-ouput` flag does 3 things: For example without `--persist-output`, a generated `ConcreteRequest` might look like below: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -49,8 +46,7 @@ The `--persist-ouput` flag does 3 things: With `--persist-output ` this becomes: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -68,12 +64,10 @@ The `--persist-ouput` flag does 3 things: 2. It generates a JSON file at the `` you specify containing a mapping from query ids to the corresponding operation texts. -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./src/queryMaps/queryMap.json" } - ``` The example above writes the complete query map file to `./src/queryMaps/queryMap.json`. You need to ensure all the directories @@ -83,8 +77,7 @@ leading to the `queryMap.json` file exist. You'll need to modify your network layer fetch implementation to pass a documentId parameter in the POST body instead of a query parameter: -```js - +```javascript function fetchQuery(operation, variables,) { return fetch('/graphql', { method: 'POST', @@ -100,7 +93,6 @@ function fetchQuery(operation, variables,) { return response.json(); }); } - ``` ## Executing Persisted Queries on the Server @@ -116,13 +108,11 @@ the query map file in a common location accessible to both the client and the se For applications where the client and server projects are separate, one option is to have an additional npm run script to push the query map at compile time to a location accessible by your server: -```js - +```javascript "scripts": { "push-queries": "node ./pushQueries.js", "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-ouput && npm run push-queries" } - ``` Some possibilities of what you can do in `./pushQueries.js`: @@ -146,8 +136,7 @@ database technologies you use, so we'll just cover the most common and basic exa If you use `express-graphql` and have access to the query map file, you can import the `--persist-output` JSON file directly and perform the matching using the `matchQueryMiddleware` from [relay-compiler-plus](https://github.com/yusinto/relay-compiler-plus). -```js - +```javascript import Express from 'express'; import expressGraphql from 'express-graphql'; import {matchQueryMiddleware} from 'relay-compiler-plus'; @@ -158,7 +147,6 @@ const app = Express(); app.use('/graphql', matchQueryMiddleware(queryMapJson), expressGraphql({schema})); - ``` ## Using `--persist-output` and `--watch` diff --git a/website/versioned_docs/version-v10.1.2/Modern-QueryRenderer.md b/website/versioned_docs/version-v10.1.2/Modern-QueryRenderer.md index cf6c37f3d9a4d..b621ef9986bf1 100644 --- a/website/versioned_docs/version-v10.1.2/Modern-QueryRenderer.md +++ b/website/versioned_docs/version-v10.1.2/Modern-QueryRenderer.md @@ -24,7 +24,6 @@ However, a `QueryRenderer` will not start loading its data until it is mounted, ## Example ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -56,5 +55,4 @@ const Example = (props) => { /> ); } - ``` diff --git a/website/versioned_docs/version-v10.1.2/Modern-RefetchContainer.md b/website/versioned_docs/version-v10.1.2/Modern-RefetchContainer.md index 7ce0d14e45417..51c2c44db8941 100644 --- a/website/versioned_docs/version-v10.1.2/Modern-RefetchContainer.md +++ b/website/versioned_docs/version-v10.1.2/Modern-RefetchContainer.md @@ -16,13 +16,11 @@ Table of Contents: `createRefetchContainer` has the following signature: ```javascript - createRefetchContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, refetchQuery: GraphQLTaggedNode, ): ReactComponentClass; - ``` ### Arguments @@ -37,7 +35,6 @@ createRefetchContainer( The Component resulting from `createRefetchContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -45,7 +42,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -61,7 +57,6 @@ type Props = { `refetch` has the following signature: ```javascript - type RefetchOptions = { force?: boolean, }; @@ -102,7 +97,6 @@ Returns a `Disposable` on which you could call `dispose()` to cancel the refetch In this simple example, let's assume we want to fetch the latest data for a `TodoItem` from the server: ```javascript - // TodoItem.js import {createRefetchContainer, graphql} from 'react-relay'; @@ -148,7 +142,6 @@ export default createRefetchContainer( } ` ); - ``` ### Loading more data @@ -156,7 +149,6 @@ export default createRefetchContainer( In this example we are using a Refetch Container to fetch more stories in a story feed component. ```javascript - import {createRefetchContainer, graphql} from 'react-relay'; class FeedStories extends React.Component { @@ -212,5 +204,4 @@ export default createRefetchContainer( } `, ); - ``` diff --git a/website/versioned_docs/version-v10.1.2/Modern-RelayCompat.md b/website/versioned_docs/version-v10.1.2/Modern-RelayCompat.md index 36632d3a8f1a1..f47dbd845ba3e 100644 --- a/website/versioned_docs/version-v10.1.2/Modern-RelayCompat.md +++ b/website/versioned_docs/version-v10.1.2/Modern-RelayCompat.md @@ -31,7 +31,6 @@ Relay Modern. The components using Relay Compat can be referred to by both other Relay Modern and Relay Classic components. ```javascript - const {createFragmentContainer, graphql} = require('react-relay/compat'); class TodoItem extends React.Component { @@ -47,5 +46,4 @@ module.exports = createFragmentContainer(TodoItem, graphql` isComplete } `); - ``` diff --git a/website/versioned_docs/version-v10.1.2/Modern-RelayEnvironment.md b/website/versioned_docs/version-v10.1.2/Modern-RelayEnvironment.md index 27d90b2fc4fe1..99e728bce740d 100644 --- a/website/versioned_docs/version-v10.1.2/Modern-RelayEnvironment.md +++ b/website/versioned_docs/version-v10.1.2/Modern-RelayEnvironment.md @@ -12,7 +12,6 @@ Most applications will create a single Environment instance and use it throughou To create an environment instance in Relay Modern, use the `RelayModernEnvironment` class: ```javascript - const { Environment, Network, @@ -30,7 +29,6 @@ const environment = new Environment({ network, store, }); - ``` For more details on creating a Network, see the [NetworkLayer guide](./network-layer). @@ -44,7 +42,6 @@ The example above did not configure a `handlerProvider`, which means that a defa If you wish to provide your own `handlerProvider`, you can do so: ```javascript - const { ConnectionHandler, } = require('relay-runtime'); @@ -58,5 +55,4 @@ function handlerProvider(handle) { `handlerProvider: No handler provided for ${handle}` ); } - ``` diff --git a/website/versioned_docs/version-v10.1.2/Modern-RelayStore.md b/website/versioned_docs/version-v10.1.2/Modern-RelayStore.md index 6bb2e3744d55b..38f88c7f69edb 100644 --- a/website/versioned_docs/version-v10.1.2/Modern-RelayStore.md +++ b/website/versioned_docs/version-v10.1.2/Modern-RelayStore.md @@ -16,7 +16,6 @@ Table of Contents: The `RecordSourceSelectorProxy` is the type of the `store` that [`updater` functions](./mutations#using-updater-and-optimisticupdater) receive as an argument. The following is the `RecordSourceSelectorProxy` interface: ```javascript - interface RecordSourceSelectorProxy { create(dataID: string, typeName: string): RecordProxy; delete(dataID: string): void; @@ -26,7 +25,6 @@ interface RecordSourceSelectorProxy { getPluralRootField(fieldName: string): ?Array; invalidateStore(): void; } - ``` ### `create(dataID: string, typeName: string): RecordProxy` @@ -36,9 +34,7 @@ Creates a new record in the store given a `dataID` and the `typeName` as defined #### Example ```javascript - const record = store.create(dataID, 'Todo'); - ``` ### `delete(dataID: string): void` @@ -48,9 +44,7 @@ Deletes a record from the store given its `dataID`. #### Example ```javascript - store.delete(dataID); - ``` ### `get(dataID: string): ?RecordProxy` @@ -60,9 +54,7 @@ Retrieves a record from the store given its `dataID`. Returns a [`RecordProxy`]( #### Example ```javascript - const record = store.get(dataID); - ``` ### `getRoot(): RecordProxy` @@ -74,20 +66,16 @@ Returns the [`RecordProxy`](#recordproxy) representing the root of the GraphQL d Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - // Represents root query const root = store.getRoot(); - ``` ### `getRootField(fieldName: string): ?RecordProxy` @@ -99,19 +87,15 @@ Retrieves a root field from the store given the `fieldName`, as defined by the G Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - const viewer = store.getRootField('viewer'); - ``` ### `getPluralRootField(fieldName: string): ?Array` @@ -123,19 +107,15 @@ Retrieves a root field that represents a collection from the store given the `fi Given the GraphQL document: ```graphql - nodes(first: 10) { # ... } - ``` Usage: ```javascript - const nodes = store.getPluralRootField('nodes'); - ``` ### `invalidateStore(): void` @@ -145,15 +125,12 @@ Globally invalidates the Relay store. This will cause any data that was written #### Example ```javascript - store.invalidateStore(); - ``` After global invalidation, any query that is checked before refetching it will be considered stale: ```javascript - environment.check(query) === 'stale' ``` @@ -163,7 +140,6 @@ environment.check(query) === 'stale' The `RecordProxy` serves as an interface to mutate records: ```javascript - interface RecordProxy { copyFieldsFrom(sourceRecord: RecordProxy): void; getDataID(): string; @@ -189,7 +165,6 @@ interface RecordProxy { setValue(value: mixed, name: string, arguments?: ?Object): RecordProxy; invalidateRecord(): void; } - ``` ### `getDataID(): string` @@ -199,9 +174,7 @@ Returns the dataID of the current record. #### Example ```javascript - const id = record.getDataID(); - ``` ### `getType(): string` @@ -211,7 +184,6 @@ Gets the type of the current record, as defined by the GraphQL schema. #### Example ```javascript - const type = user.getType(); // User ``` @@ -225,20 +197,16 @@ Gets the value of a field in the current record given the field name. Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - const name = viewer.getValue('name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. @@ -248,20 +216,16 @@ Optionally, if the field takes arguments, you can pass a bag of `variables`. Given the GraphQL document: ```graphql - viewer { id name(arg: $arg) } - ``` Usage: ```javascript - const name = viewer.getValue('name', {arg: 'value'}); - ``` ### `getLinkedRecord(name: string, arguments?: ?Object): ?RecordProxy` @@ -273,23 +237,19 @@ Retrieves a record associated with the current record given the field name, as d Given the GraphQL document: ```graphql - rootField { viewer { id name } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -299,22 +259,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { viewer(arg: $arg) { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {arg: 'value'}); - ``` ### `getLinkedRecords(name: string, arguments?: ?Object): ?Array` @@ -326,22 +282,18 @@ Retrieves the set of records associated with the current record given the field Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const nodes = rootField.getLinkedRecords('nodes'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -351,22 +303,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { nodes(first: $count) { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {count: 10}); - ``` ### `getOrCreateLinkedRecord(name: string, typeName: string, arguments?: ?Object)` @@ -378,19 +326,16 @@ Retrieves the a record associated with the current record given the field name, Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = rootField.getOrCreateLinkedRecord('viewer', 'User'); // Will create if it doesn't exist @@ -405,28 +350,22 @@ Mutates the current record by setting a new value on the specified field. Return Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - viewer.setValue('New Name', 'name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. ```javascript - viewer.setValue('New Name', 'name', {arg: 'value'}); - ``` ### `copyFieldsFrom(sourceRecord: RecordProxy): void` @@ -436,7 +375,6 @@ Mutates the current record by copying the fields over from the passed in record #### Example ```javascript - const record = store.get(id1); const otherRecord = store.get(id2); record.copyFieldsFrom(otherRecord); // Mutates `record` @@ -452,19 +390,16 @@ Mutates the current record by setting a new linked record on the given the field Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = store.create(/* ... */)'' rootField.setLinkedRecord(newViewer, 'viewer'); // @@ -482,19 +417,16 @@ Mutates the current record by setting a new set of linked records on the given t Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newNode = store.create(/* ... */); const newNodes = [...rootField.getLinkedRecords('nodes'), newNode]; @@ -511,16 +443,13 @@ Invalidates the record. This will cause any query that references this record to #### Example ```javascript - const record = store.get('4'); record.invalidateRecord(); - ``` After invalidating a record, any query that references the invalidated record and that is checked before refetching it will be considered stale: ```javascript - environment.check(query) === 'stale' ``` @@ -530,7 +459,6 @@ environment.check(query) === 'stale' `ConnectionHandler` is a utility module exposed by `relay-runtime` that aids in the manipulation of connections. `ConnectionHandler` exposes the following interface: ```javascript - interface ConnectionHandler { getConnection( record: RecordProxy, @@ -555,7 +483,6 @@ interface ConnectionHandler { ): void, deleteNode(connection: RecordProxy, nodeID: string): void } - ``` ### `getConnection(record: RecordProxy, key: string, filters?: ?Object)` @@ -565,7 +492,6 @@ Given a record and a connection key, and optionally a set of filters, `getConnec First, let's take a look at a plain connection: ```graphql - fragment FriendsFragment on User { friends(first: 10) { edges { @@ -575,26 +501,22 @@ fragment FriendsFragment on User { } } } - ``` Accessing a plain connection field like this is the same as other regular field: ```javascript - // The `friends` connection record can be accessed with: const user = store.get(userID); const friends = user && user.getLinkedRecord('friends'); // Access fields on the connection: const edges = friends && friends.getLinkedRecords('edges'); - ``` In a [pagination container](./pagination-container), we usually annotate the actual connection field with `@connection` to tell Relay which part needs to be paginated: ```graphql - fragment FriendsFragment on User { friends(first: 10, orderby: "firstname") @connection( key: "FriendsFragment_friends", @@ -606,7 +528,6 @@ fragment FriendsFragment on User { } } } - ``` For connections like the above, `ConnectionHandler` helps us find the record: @@ -624,7 +545,6 @@ const friends = ConnectionHandler.getConnection( ); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` ### Edge creation and insertion @@ -654,7 +574,6 @@ ConnectionHandler.insertEdgeAfter(friends, edge); // No cursor provided, Insert the edge at the front: ConnectionHandler.insertEdgeBefore(friends, edge); - ``` ### `deleteNode(connection: RecordProxy, nodeID: string): void` @@ -668,5 +587,4 @@ Given a connection, deletes any edges whose id matches the given id. const user = store.get(userID); const friends = ConnectionHandler.getConnection(user, 'friends'); ConnectionHandler.deleteNode(friends, idToDelete); - ``` diff --git a/website/versioned_docs/version-v10.1.2/Modern-Subscriptions.md b/website/versioned_docs/version-v10.1.2/Modern-Subscriptions.md index 671b28f684403..85ade0f34c511 100644 --- a/website/versioned_docs/version-v10.1.2/Modern-Subscriptions.md +++ b/website/versioned_docs/version-v10.1.2/Modern-Subscriptions.md @@ -6,7 +6,6 @@ original_id: subscriptions Relay exposes the following APIs to create subscriptions. ```javascript - import { requestSubscription } from 'react-relay'; type Variables = {[name: string]: any}; @@ -28,7 +27,6 @@ requestSubscription( cacheConfig?: CacheConfig, }, ) => Disposable; - ``` The function returns a `Disposable` on which you could call `dispose()` to cancel the refetch. @@ -55,7 +53,6 @@ appropriate when you are only changing the properties of existing records that can be identified by their `id`: ```javascript - import { requestSubscription, graphql, @@ -89,7 +86,6 @@ requestSubscription( onError: error => console.error(error), } ); - ``` # Configure Network @@ -97,7 +93,6 @@ requestSubscription( You will need to Configure your [Network](./network-layer) to handle subscriptions. The below example uses [subscriptions-transport-ws](https://github.com/apollographql/subscriptions-transport-ws): ```javascript - import { ... Network, @@ -134,7 +129,6 @@ Relay's in-memory cache when each subscription response is received. To do so, pass an `updater` function: ```javascript - import { ConnectionHandler } from 'relay-runtime'; requestSubscription( @@ -160,5 +154,4 @@ requestSubscription( }, }, ); - ``` diff --git a/website/versioned_docs/version-v10.1.2/Modern-TestingRelayComponents.md b/website/versioned_docs/version-v10.1.2/Modern-TestingRelayComponents.md index da8f520bd7917..91003cab931f2 100644 --- a/website/versioned_docs/version-v10.1.2/Modern-TestingRelayComponents.md +++ b/website/versioned_docs/version-v10.1.2/Modern-TestingRelayComponents.md @@ -65,7 +65,6 @@ MockPayloadGenerator may drastically simplify the process of creating and mainta Example of a simple Mock Resolver: ```javascript - { ID() { // Return mock value for a scalar filed with type ID @@ -76,13 +75,11 @@ Example of a simple Mock Resolver: return "Lorem Ipsum" } } - ``` It is possible to define more resolvers for Object types ```javascript - { // This will be the default values for User object in the query response User() { @@ -95,7 +92,6 @@ It is possible to define more resolvers for Object types }; }, } - ``` ### Mock Resolver Context @@ -103,7 +99,6 @@ It is possible to define more resolvers for Object types The first argument of the MockResolver is the object that contains Mock Resolver Context. It is possible to return dynamic values from mock resolvers based on the context - for instance, name or alias of the field, a path in the selection, arguments, or parent type. ```javascript - { String(context) { if (context.name === 'zip') { @@ -117,7 +112,6 @@ The first argument of the MockResolver is the object that contains Mock Resolver } } } - ``` ### ID Generation @@ -125,14 +119,12 @@ The first argument of the MockResolver is the object that contains Mock Resolver The second argument of the Mock Resolver its a function that will generate a sequence of integers, useful to generate unique ids in the tests ```javascript - { // will generate strings "my-id-1", "my-id-2", etc. ID(_, generateId) { return `my-id-${generateId()}`; }, } - ``` ### @relay_test_operation @@ -142,7 +134,6 @@ Most of GraphQL type information for a specific field in the selection is not av Operation with the @relay_test_operation directive will have additional metadata that will contain GraphQL type info for fields in the operation's selection. And it will improve the quality of the generated data. You also will be able to define Mock resolvers for Scalar (not only ID and String) and Abstract types: ```javascript - { Float() { return 123.456; @@ -160,7 +151,6 @@ Operation with the @relay_test_operation directive will have additional metadata }; } } - ``` ## Examples @@ -170,7 +160,6 @@ Operation with the @relay_test_operation directive will have additional metadata Using `createMockEnvironment` and `MockPayloadGenerator` allows writing concise tests for components that are using Relay Containers and Renderers. Both those modules can be imported from `relay-test-utils` ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { @@ -223,7 +212,6 @@ test('Error State', () => { renderer.root.find(item => (item.props.testID = 'errorMessage')), ).toBeDefined(); }); - ``` ### Fragment Container Tests @@ -231,7 +219,6 @@ test('Error State', () => { Essentially, in the example above will `resolveMostRecentOperation` will generate data for all child fragment containers (pagination, refetch). But, usually the Root Components container may have many child fragment components and you may want to exercise a specific Fragment Container. The solution for that would be to wrap your fragment container with the QueryRenderer that renders a Query that's spreads fragments from your fragment container. ```javascript - test('Fragment Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -262,7 +249,6 @@ test('Fragment Container', () => { expect(renderer).toMatchSnapshot(); }); - ``` ### Pagination Container Test @@ -270,7 +256,6 @@ test('Fragment Container', () => { Essentially, tests for Pagination container are not different from Fragment Container tests. But we can do more here, we can actually see how the pagination works - we can assert the behavior of our components when performing pagination (load more, refetch). ```javascript - // Pagination Example test('Pagination Container', () => { const environment = createMockEnvironment(); @@ -344,7 +329,6 @@ test('Pagination Container', () => { We can use similar approach here with wrapping container with Query Renderer. And for the sake of completeness, we will add example here: ```javascript - test('Refetch Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -386,7 +370,6 @@ test('Refetch Container', () => { ); // expect(renderer).toMatchSnapshot(); }); - ``` ### Mutations @@ -394,7 +377,6 @@ test('Refetch Container', () => { Mutations itself are operations so we can test them independently (unit-test) for specific mutation, or in combination with the view from which this mutation is called. ```javascript - // Say, you have a mutation function function sendMutation(environment, onCompleted, onError, variables) commitMutation(environment, { @@ -417,7 +399,6 @@ test('it should send mutation', () => { ); expect(onCompleted).toBeCalled(); }); - ``` ### Subscription @@ -425,7 +406,6 @@ test('it should send mutation', () => { We can test subscription in a similar way we test mutations ```javascript - // Example subscribe function function subscribe(environment, onNext, onError, variables) requestSubscription(environment, { @@ -448,7 +428,6 @@ test('it should subscribe', () => { ); expect(onNext).toBeCalled(); }); - ``` ### Example with `queueOperationResolver` @@ -456,7 +435,6 @@ test('it should subscribe', () => { With `queueOpeararionResolver` it possible to define responses for operations that will be executed on the environment ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { diff --git a/website/versioned_docs/version-v10.1.2/Modern-TypeEmission.md b/website/versioned_docs/version-v10.1.2/Modern-TypeEmission.md index 63614b869a322..4ff63e4a7d81b 100644 --- a/website/versioned_docs/version-v10.1.2/Modern-TypeEmission.md +++ b/website/versioned_docs/version-v10.1.2/Modern-TypeEmission.md @@ -16,7 +16,6 @@ In this example the emitted type-information would require the variables object #### Flow ```javascript - /** * export type ExampleQueryVariables = {| * +artistID: string @@ -44,7 +43,6 @@ const variables: ExampleQueryVariables = { #### TypeScript ```javascript - /** * export type ExampleQueryVariables = { * readonly artistID: string @@ -79,7 +77,6 @@ In this example the emitted type-information describes the response data availab #### Flow ```javascript - /** * export type ExampleQueryResponse = {| * +artist: ?{| @@ -110,7 +107,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * export type ExampleQueryResponse = { * readonly artist?: { @@ -146,7 +142,6 @@ Similarly, in this example the emitted type-information describes the prop data #### Flow ```javascript - /** * export type ExampleFragment_artist = {| * +name: string @@ -172,7 +167,6 @@ export const ExampleFragment = createFragmentContainer( #### TypeScript ```javascript - /** * export type ExampleFragment_artist = { * readonly name: string @@ -206,7 +200,6 @@ Consider a component that composes the above fragment container example. In this #### Flow ```javascript - /** * import type { FragmentReference } from "relay-runtime"; * declare export opaque type ExampleFragment_artist$ref: FragmentReference; @@ -250,7 +243,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * declare const _ExampleFragment_artist$ref: unique symbol; * export type ExampleFragment_artist$ref = typeof _ExampleFragment_artist$ref; @@ -315,7 +307,6 @@ $ relay-compiler --artifactDirectory ./src/__generated__ […] ["relay", { "artifactDirectory": "./src/__generated__" }] ] } - ``` It is recommended to alias this directory in your module resolution configuration such that you don’t need to specify relative paths in your source files. This is what is also done in the above examples, where artifacts are imported from a `__generated__` alias, rather than relative paths like `../../../../__generated__`. diff --git a/website/versioned_docs/version-v10.1.2/Modern-UpgradingSetVariables.md b/website/versioned_docs/version-v10.1.2/Modern-UpgradingSetVariables.md index d5b086fafce20..ff73feec04f8b 100644 --- a/website/versioned_docs/version-v10.1.2/Modern-UpgradingSetVariables.md +++ b/website/versioned_docs/version-v10.1.2/Modern-UpgradingSetVariables.md @@ -36,7 +36,6 @@ fragment on User { # ... } } - ``` This should be upgraded to use a [`PaginationContainer`](./pagination-container). @@ -61,7 +60,6 @@ fragment on User { # ... } } - ``` This can be upgraded by using a [`RefetchContainer`](./refetch-container) which allows you to specify the exact query to use to fetch the new data. @@ -86,7 +84,6 @@ fragment on FeedbackTarget { # ... } } - ``` This can be upgraded by conditionally rendering a [`QueryRenderer`](./query-renderer) which will load the data once it is rendered. The code overhead of doing this is dramatically reduced with the new API. diff --git a/website/versioned_docs/version-v10.1.2/Modern-fetchQuery.md b/website/versioned_docs/version-v10.1.2/Modern-fetchQuery.md index 2e9461ad527bd..c1a06ab7d2493 100644 --- a/website/versioned_docs/version-v10.1.2/Modern-fetchQuery.md +++ b/website/versioned_docs/version-v10.1.2/Modern-fetchQuery.md @@ -6,7 +6,6 @@ original_id: fetch-query You can use the `fetchQuery` function to imperatively make GraphQL Requests. This is useful for cases where you want to make requests outside of React but still utilize the Relay store and network layer. ```javascript - import {fetchQuery, graphql} from 'relay-runtime'; const query = graphql` @@ -25,7 +24,6 @@ fetchQuery(environment, query, variables) .then(data => { // access the graphql response }); - ``` ## Arguments diff --git a/website/versioned_docs/version-v10.1.2/PrinciplesAndArchitecture-Compiler.md b/website/versioned_docs/version-v10.1.2/PrinciplesAndArchitecture-Compiler.md index c195491682b1f..fcd0490cb724f 100644 --- a/website/versioned_docs/version-v10.1.2/PrinciplesAndArchitecture-Compiler.md +++ b/website/versioned_docs/version-v10.1.2/PrinciplesAndArchitecture-Compiler.md @@ -74,7 +74,6 @@ foo { # type FooType foo { id } - ``` - `SkipRedundantNodeTransform`: A more advanced version of flattening, this eliminates more complex cases of field duplication such as when a field is fetched both unconditionally and conditionally, or is fetched by two different sub-fragments. For example: @@ -97,7 +96,6 @@ foo { id } } - ``` - `GenerateRequisiteFieldTransform`: This optional, Relay-specific transform inserts `id` fields for globally identifiable objects and `__typename` fields wherever the type cannot be statically determined (e.g. for unions). diff --git a/website/versioned_docs/version-v10.1.2/PrinciplesAndArchitecture-Runtime.md b/website/versioned_docs/version-v10.1.2/PrinciplesAndArchitecture-Runtime.md index 9491d290c146f..e9221631a701d 100644 --- a/website/versioned_docs/version-v10.1.2/PrinciplesAndArchitecture-Runtime.md +++ b/website/versioned_docs/version-v10.1.2/PrinciplesAndArchitecture-Runtime.md @@ -77,7 +77,6 @@ RecordSource { city: 'Seattle', } } - ``` [1] Note that GraphQL itself does not impose this constraint, and Relay Runtime may also be used for schemas that do not conform to it. For example, both systems can be used to query a single denormalized table. However, many of the features that Relay Runtime provides, such as caching and normalization, work best when the data is represented as a normalized graph with stable identities for discrete pieces of information. diff --git a/website/versioned_docs/version-v10.1.2/PrinciplesAndArchitecture-ThinkingInGraphQL.md b/website/versioned_docs/version-v10.1.2/PrinciplesAndArchitecture-ThinkingInGraphQL.md index a8842ae084922..9ff8a7840df90 100644 --- a/website/versioned_docs/version-v10.1.2/PrinciplesAndArchitecture-ThinkingInGraphQL.md +++ b/website/versioned_docs/version-v10.1.2/PrinciplesAndArchitecture-ThinkingInGraphQL.md @@ -12,7 +12,6 @@ In this article we'll explore what it means to build a GraphQL client framework Imagine we have a simple application that fetches a list of stories, and some details about each one. Here's how that might look in resource-oriented REST: ```javascript - // Fetch the list of story IDs but not their details: rest.get('/stories').then(stories => // This resolves to a list of items with linked resources: @@ -25,13 +24,11 @@ rest.get('/stories').then(stories => // `[ { id: "...", text: "..." } ]` console.log(stories); }); - ``` Note that this approach requires _n+1_ requests to the server: 1 to fetch the list, and _n_ to fetch each item. With GraphQL we can fetch the same data in a single network request to the server (without creating a custom endpoint that we'd then have to maintain): ```javascript - graphql.get(`query { stories { id, text } }`).then( stories => { // A list of story items: @@ -39,7 +36,6 @@ graphql.get(`query { stories { id, text } }`).then( console.log(stories); } ); - ``` So far we're just using GraphQL as a more efficient version of typical REST approaches. Note two important benefits in the GraphQL version: @@ -56,7 +52,6 @@ Repeatedly refetching information from the server can get quite slow. For exampl In a resource-oriented REST system, we can maintain a **response cache** based on URIs: ```javascript - var _cache = new Map(); rest.get = uri => { if (!_cache.has(uri)) { @@ -64,13 +59,11 @@ rest.get = uri => { } return _cache.get(uri); }; - ``` Response-caching can also be applied to GraphQL. A basic approach would work similarly to the REST version. The text of the query itself can be used as a cache key: ```javascript - var _cache = new Map(); graphql.get = queryText => { if (!_cache.has(queryText)) { @@ -78,7 +71,6 @@ graphql.get = queryText => { } return _cache.get(queryText); }; - ``` Now, requests for previously cached data can be answered immediately without making a network request. This is a practical approach to improving the perceived performance of an application. However, this method of caching can cause problems with data consistency. @@ -90,7 +82,6 @@ With GraphQL it is very common for the results of multiple queries to overlap. H ``` query { stories { id, text, likeCount } } - ``` and then later refetch one of the stories whose `likeCount` has since been incremented: @@ -98,7 +89,6 @@ and then later refetch one of the stories whose `likeCount` has since been incre ``` query { story(id: "123") { id, text, likeCount } } - ``` We'll now see different `likeCount`s depending on how the story is accessed. A view that uses the first query will see an outdated count, while a view using the second query will see the updated count. @@ -119,7 +109,6 @@ query { } } } - ``` And here's a possible response: @@ -134,13 +123,11 @@ query: { } } } - ``` Although the response is hierarchical, we'll cache it by flattening all the records. Here is an example of how Relay would cache this query response: ```javascript - Map { // `story(id: "1")` 1: Map { @@ -152,7 +139,6 @@ Map { name: 'Jan', }, }; - ``` This is only a simple example: in reality the cache must handle one-to-many associations and pagination (among other things). @@ -182,7 +168,6 @@ The first query was for a list of stories: ``` query { stories { id, text, likeCount } } - ``` With a normalized response cache, a record would be created for each story in the list. The `stories` field would store links to each of these records. @@ -192,7 +177,6 @@ The second query refetched the information for one of those stories: ``` query { story(id: "123") { id, text, likeCount } } - ``` When this response is normalized, Relay can detect that this result overlaps with existing data based on its `id`. Rather than create a new record, Relay will update the existing `123` record. The new `likeCount` is therefore available to _both_ queries, as well as any other query that might reference this story. @@ -215,7 +199,6 @@ query { } } } - ``` After initially fetching this story our cache might be as follows. Note that the story and comment both link to the same record as `author`: @@ -242,7 +225,6 @@ Map { author: Link(2), }, } - ``` The author of this story also commented on it — quite common. Now imagine that some other view fetches new information about the author, and her profile photo has changed to a new URI. Here's the _only_ part of our cached data that changes: @@ -256,7 +238,6 @@ Map { photo: 'http://.../photo2.jpg', }, } - ``` The value of the `photo` field has changed; and therefore the record `2` has also changed. And that's it. Nothing else in the _cache_ is affected. But clearly our _view_ needs to reflect the update: both instances of the author in the UI (as story author and comment author) need to show the new photo. @@ -273,7 +254,6 @@ ImmutableMap { }, 3: ImmutableMap // same as before } - ``` If we replace `2` with a new immutable record, we'll also get a new immutable instance of the cache object. However, records `1` and `3` are untouched. Because the data is normalized, we can't tell that `story`'s contents have changed just by looking at the `story` record alone. @@ -299,7 +279,6 @@ mutation StoryLike($storyID: String) { likeCount } } - ``` Notice that we're querying for data that _may_ have changed as a result of the mutation. An obvious question is: why can't the server just tell us what changed? The answer is: it's complicated. GraphQL abstracts over _any_ data storage layer (or an aggregation of multiple sources), and works with any programming language. Furthermore, the goal of GraphQL is to provide data in a form that is useful to product developers building a view. diff --git a/website/versioned_docs/version-v10.1.2/PrinciplesAndArchitecture-ThinkingInRelay.md b/website/versioned_docs/version-v10.1.2/PrinciplesAndArchitecture-ThinkingInRelay.md index e61f3fd21c933..62b1914ef3ff9 100644 --- a/website/versioned_docs/version-v10.1.2/PrinciplesAndArchitecture-ThinkingInRelay.md +++ b/website/versioned_docs/version-v10.1.2/PrinciplesAndArchitecture-ThinkingInRelay.md @@ -30,13 +30,11 @@ fragment Story_story on Story { photo } } - ``` And this fragment can then be used to define the Story container: ```javascript - const {createFragmentContainer, graphql} = require('react-relay'); // Plain React component. @@ -64,7 +62,6 @@ const StoryContainer = createFragmentContainer(Story, { In React, rendering a view requires two inputs: the _component_ to render, and a _root_ DOM (UI) node to render into. Rendering Relay containers is similar: we need a _container_ to render, and a _root_ in the graph from which to start our query. We also must ensure that the queries for the container are executed and may want to show a loading indicator while data is being fetched. Similar to `ReactDOM.render(component, domNode)`, Relay provides `` for this purpose. The `query` and `variables` define what data to fetch and `render` defines what to render. Here's how we might render ``: ```javascript - ReactDOM.render( { ); } } - ``` The above code is doing something very similar to our [previous example](#rendering-graphql-queries). However, we are now passing a `$userID` variable to the GraphQL query via the `variables` prop. This has a couple of important implications: @@ -228,7 +216,6 @@ Now that we know how to define and fetch queries, let's actually start building First, let's start at the bottom. Suppose that we want to render a component that simply displays a given todo item's text and completed state: ```javascript - // Todo.js import React from 'react'; @@ -258,7 +245,6 @@ export default class Todo extends React.Component { ); } } - ``` From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L112), we know that we can query this data on the `Todo` type. However, we don't want to have to send a separate query for each todo item; that would defeat the purpose of using GraphQL over a traditional REST API. We could manually query for these fields directly in our `QueryRenderer` query, but that would hurt re-usability: what if we want to query the same set of fields as part of a different query? Additionally, we wouldn't know which component needs the data we're querying, which is a problem Relay directly tries to address. @@ -266,18 +252,15 @@ From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/dat Instead, we can define a reusable [Fragment](http://graphql.org/learn/queries/#fragments), which allows us to define a set of fields on a type and reuse them within our queries wherever we need to: ```graphql - fragment TodoItemFragment on Todo { complete text } - ``` Our component can then use this fragment to declare its data dependency on the `Todo` GraphQL type: ```javascript - // Todo.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -340,7 +323,6 @@ Before proceeding, don't forget to run the Relay Compiler with `yarn relay`. Given that [Fragment Containers](./fragment-container) are just React components, we can compose them as such. We can even re-use fragment containers within other fragment containers. As an example, let's see how we would define a `TodoList` component that just renders a list of todo items, and whether all have been completed or not: ```javascript - // TodoList.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -401,7 +383,6 @@ export default createFragmentContainer( `, }, ); - ``` As with the first fragment container we defined, `TodoList` declares its data dependencies via a fragment. However, this component additionally re-uses the fragment previously defined by the `Todo` component, and passes the appropriate data when rendering the child `Todo` components (a.k.a. fragment containers). @@ -416,7 +397,6 @@ fragment containers do not directly fetch data. Instead, containers declare a sp A `QueryRenderer` rendering these fragment containers could look like the following: ```javascript - // ViewerTodoList.js import React from 'react'; import {graphql, QueryRenderer} from 'react-relay'; @@ -457,7 +437,6 @@ export default class ViewerTodoList extends React.Component { ); } } - ``` Check out our docs for [Fragment Containers](./fragment-container) for more details, and our guides on [Refetch](./refetch-container) and [Pagination](./pagination-container) for more advanced usage of containers. @@ -469,7 +448,6 @@ Now that we know how to query for and render data, let's move on to changing our From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L35), we know that we have some mutations available to us, so let's start by writing a mutation to change the `complete` status of a given todo item (i.e. mark or unmark it as done): ```graphql - mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { changeTodoStatus(input: $input) { todo { @@ -478,7 +456,6 @@ mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { } } } - ``` This mutation allows us to query back some data as a [result of the mutation](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L18), so we're going to query for the updated `complete` status on the todo item. @@ -486,7 +463,6 @@ This mutation allows us to query back some data as a [result of the mutation](ht In order to execute this mutation in Relay, we're going to write a new mutation using Relay's `commitMutation` api: ```javascript - // ChangeTodoStatusMutation.js import {graphql, commitMutation} from 'react-relay'; @@ -520,7 +496,6 @@ function commit( } export default {commit}; - ``` Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mutation to the server and, in our case, upon receiving a response it will automatically update the local data store with the latest data from the server. This also means that upon receiving the response, Relay will ensure that any components (i.e. containers) that depend on the updated data are re-rendered. @@ -528,7 +503,6 @@ Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mut In order to actually use this mutation in our component, we could update our `Todo` component in the following way: ```javascript - // Todo.js // ... @@ -562,7 +536,6 @@ In order to make the experience better, we can configure our mutation to do an o In Relay, there's a couple of options we can pass to `commitMutation` to enable optimistic updates. Let's see what that would look like in our `ChangeTodoStatusMutation`: ```javascript - // ChangeTodoStatusMutation.js // ... @@ -597,7 +570,6 @@ function commit( } export default {commit}; - ``` In the simplest case above, we just need to pass an `optimisticResponse` option, which should refer to an object having the same shape as the mutation response payload. When we pass this option, Relay will know to immediately update our local data with the optimistic response, and then update it with the actual server response or roll it back if an error occurs. diff --git a/website/versioned_docs/version-v10.1.3/Modern-ConvertingMutations.md b/website/versioned_docs/version-v10.1.3/Modern-ConvertingMutations.md index 08ad2e998cb2d..8f4bdc1d8e0d2 100644 --- a/website/versioned_docs/version-v10.1.3/Modern-ConvertingMutations.md +++ b/website/versioned_docs/version-v10.1.3/Modern-ConvertingMutations.md @@ -12,19 +12,16 @@ FatQueries in Relay Classic mutations was a concept that was confusing for a num Example of existing fat query: ```javascript - RelayClassic.QL` fragment on MarkReadNotificationResponsePayload @relay(pattern: true) { notification } `; - ``` Example of converted mutation query: ```javascript - graphql` mutation MarkReadNotificationMutation( $input: MarkReadNotificationData! @@ -37,7 +34,6 @@ graphql` } } `; - ``` ## Migrating Configs @@ -67,7 +63,6 @@ This is no longer needed in Compatibility Mode for neither environments. Simply Take this example of a simple mutation in Relay Classic: ```javascript - class LikeStoryMutation extends RelayClassic.Mutation { getMutation() { return RelayClassic.QL`mutation {likeStory}`; @@ -106,7 +101,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { `, }; } - ``` ### Converting `getMutation()` and `getFatQuery()` @@ -114,7 +108,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { We combine these two into a regular GraphQL mutation, which list out specific fields that needs to be updated. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story(data: $input) { @@ -126,7 +119,6 @@ const mutation = graphql` } } `; - ``` ### Converting `getConfigs()` @@ -138,13 +130,11 @@ As specified above, `FIELDS_CHANGE` configs can be omitted. To convert `getVariables()`, we take the return value from the original function and wrap it in an object that contains a property that matches the variable name for the mutation. In this case, the mutation has a `input` variable that is of type `LikeStoryData`. ```javascript - const variables = { input: { storyID: args.storyID } } - ``` ### Final Result @@ -152,7 +142,6 @@ const variables = { As you can see, our resulting mutation is a lot simpler and more like regular GraphQL than the Relay Classic version we started out with. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story { @@ -178,7 +167,6 @@ function commit(environment: CompatEnvironment, args) { variables, }); } - ``` See [Mutation](./mutations) for additional options on `commitMutation` for more complex mutations. diff --git a/website/versioned_docs/version-v10.1.3/Modern-FragmentContainer.md b/website/versioned_docs/version-v10.1.3/Modern-FragmentContainer.md index 423f446cbb054..6a40bbcfb5d0a 100644 --- a/website/versioned_docs/version-v10.1.3/Modern-FragmentContainer.md +++ b/website/versioned_docs/version-v10.1.3/Modern-FragmentContainer.md @@ -17,12 +17,10 @@ Table of Contents: `createFragmentContainer` has the following signature: ```javascript - createFragmentContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, ): ReactComponentClass; - ``` ### Arguments @@ -43,7 +41,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -58,7 +55,6 @@ To start, let's build the plain React version of a hypothetical `` c Here's a basic implementation of `` that ignores styling in order to highlight the functionality: ```javascript - // TodoItem.js class TodoItem extends React.Component { render() { @@ -78,7 +74,6 @@ class TodoItem extends React.Component { ); } } - ``` ### Data Dependencies With GraphQL @@ -86,7 +81,6 @@ class TodoItem extends React.Component { In Relay, data dependencies are described using [GraphQL](https://github.com/facebook/graphql). For ``, the dependency can be expressed as follows. Note that this exactly matches the shape that the component expected for the `item` prop. ```javascript - graphql` # This fragment only applies to objects of type 'Todo'. fragment TodoItem_item on Todo { @@ -102,7 +96,6 @@ graphql` Given the plain React component and a GraphQL fragment, we can now define a Fragment Container to specify this component's data requirements. Let's look at the code first and then see what's happening: ```javascript - // TodoItem.js import {createFragmentContainer, graphql} from 'react-relay'; @@ -120,7 +113,6 @@ export default createFragmentContainer(TodoItem, { } `, }); - ``` ## Container Composition @@ -134,7 +126,6 @@ Let's explore how this works via a `` component that composes the `< View composition is _exactly_ what you're used to — Relay containers are just standard React components. Here's the `` component: ```javascript - class TodoList extends React.Component { render() { // Expects a `list` with a string `title`, as well as the information @@ -151,7 +142,6 @@ class TodoList extends React.Component { ); } } - ``` ### Composing Fragments @@ -159,7 +149,6 @@ class TodoList extends React.Component { Fragment composition works similarly — a parent container's fragment composes the fragment for each of its children. In this case, `` needs to fetch information about the `Todo`s that are required by ``. ```javascript - class TodoList extends React.Component // as above export default createFragmentContainer(TodoList, { @@ -176,7 +165,6 @@ export default createFragmentContainer(TodoList, { } `, }); - ``` Note that when composing fragments, the type of the composed fragment must match the field on the parent in which it is embedded. For example, it wouldn't make sense to embed a fragment of type `Story` into a parent's field of type `User`. Relay and GraphQL will provide helpful error messages if you get this wrong (and if they aren't helpful, let us know!). @@ -190,7 +178,6 @@ When defining a fragment, you can use the [`@argumentDefinitions`](./graphql-in- For example, let's redefine our `TodoList_list` fragment to take some arguments using `@argumentDefinitions`: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -200,7 +187,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` Any arguments defined inside `@argumentDefinitions` will be local variables available inside the fragment's scope. However, a fragment can also reference global variables that were defined in the root query. @@ -212,11 +198,9 @@ In order to pass arguments to a fragment that has `@argumentDefinitions`, you ne Following our `TodoList_list` example, we would pass arguments to the fragment like so: ```graphql - query TodoListQuery($count: Int, $userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` ## Rendering Containers diff --git a/website/versioned_docs/version-v10.1.3/Modern-GraphQLInRelay.md b/website/versioned_docs/version-v10.1.3/Modern-GraphQLInRelay.md index c4dc8f3463e53..715b119492cc7 100644 --- a/website/versioned_docs/version-v10.1.3/Modern-GraphQLInRelay.md +++ b/website/versioned_docs/version-v10.1.3/Modern-GraphQLInRelay.md @@ -14,7 +14,6 @@ Table of Contents: The `graphql` template tag provided by Relay serves as the mechanism to write queries, fragments, mutations or subscriptions in the [GraphQL](http://graphql.org/learn/) language. For example: ```javascript - import {graphql} from 'react-relay'; graphql` @@ -24,7 +23,6 @@ graphql` } } `; - ``` The result of using the `graphql` template tag is a `GraphQLTaggedNode`; a runtime representation of the GraphQL document which can be used to define [Query Renderers](./query-renderer), [Fragment Containers](./fragment-container), [Refetch Containers](./refetch-container), [Pagination Containers](./pagination-container), etc. @@ -42,11 +40,9 @@ Relay uses directives to add additional information to GraphQL documents, which `@arguments` is a directive used to pass arguments to a fragment that was defined using [`@argumentDefinitions`](#argumentdefinitions). For example: ```graphql - query TodoListQuery($userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -56,7 +52,6 @@ See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fr `@argumentDefinitions` is a directive used to specify arguments taken by a fragment. For example: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -66,7 +61,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -80,7 +74,6 @@ When using the [Pagination Container](./pagination-container), Relay expects con When defining a fragment for use with a Fragment container, you can use the `@relay(plural: true)` directive to indicate that container expects the prop for that fragment to be a list of items instead of a single item. A query or parent that spreads a `@relay(plural: true)` fragment should do so within a plural field (ie a field backed by a [GraphQL list](http://graphql.org/learn/schema/#lists-and-non-null). For example: ```javascript - // Plural fragment definition graphql` fragment TodoItems_items on TodoItem @relay(plural: true) { @@ -95,7 +88,6 @@ fragment TodoApp_app on App { ...TodoItem_items } } - ``` ### `@inline` @@ -107,7 +99,6 @@ Non-React functions can also take advantage of data masking. A fragment can be d In the example below, the function `processItemData` is called from a React component. It requires an item object with a specific set of fields. All React components that use this function should spread the `processItemData_item` fragment to ensure all of the correct item data is loaded for this function. ```javascript - import {graphql, readInlineData} from 'react-relay'; // non-React function called from React @@ -127,11 +118,9 @@ function processItemData(itemRef) { creatorName: item.creator.name }); } - ``` ```javascript - // React Component function MyComponent({item}) { function handleClick() { @@ -151,7 +140,6 @@ export default createFragmentContainer(MyComponent, { } ` }); - ``` ### `@relay(mask: Boolean)` @@ -169,7 +157,6 @@ Keep in mind that it is typically considered an **anti-pattern** to create a sin In the example below, the `user` prop will include the data for `id` and `name` fields wherever `...Component_internUser` is included, instead of Relay's normal behavior to mask those fields: ```javascript - graphql` fragment Component_internUser on InternUser @relay(mask: false) { id @@ -197,7 +184,6 @@ export default createFragmentContainer( } `, ); - ``` ## Relay Compiler @@ -207,7 +193,6 @@ Relay uses the Relay Compiler to convert [`graphql`](#graphql) literals into gen A query like the following: ```javascript - graphql` fragment MyComponent on Type { field @@ -228,12 +213,10 @@ Relay Compiler supports the use of **persisted queries**, in which each version Persisted queries can be enabled by instructing Relay Compiler to emit metadata about each query, mutation, and subscription into a JSON file. The generated file will contain a mapping of query identifiers to query text, which you can then save to your server. To enable persisted queries, use the `--persist-output` flag to the compiler: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` Relay Compiler will then create the id => query text mapping in the path you specify. You can then use this complete @@ -250,7 +233,6 @@ See our relay-compiler section in our [Installation and Setup guide](./installat To use the Relay Compiler, you need either a .graphql or .json GraphQL schema file, describing your GraphQL server's API. Typically these files are local representations of a server source of truth and are not edited directly. For example, we might have a `schema.graphql` like: ```graphql - schema { query: Root } @@ -268,7 +250,6 @@ type WordDefinition { text: String image: String } - ``` ### Source files @@ -284,7 +265,6 @@ For example, given the two files: - `src/Components/DictionaryComponent.js` ```javascript - const DictionaryWordFragment = graphql` fragment DictionaryComponent_word on Word { id @@ -306,7 +286,6 @@ For example, given the two files: - `src/Queries/DictionaryQuery.js` ```javascript - const DictionaryQuery = graphql` query DictionaryQuery { dictionary { @@ -330,9 +309,7 @@ Typically you will not need to import your generated definitions. The [Relay Bab However the Relay Compiler also automatically generates [Flow](https://flow.org) types as [type comments](https://flow.org/en/docs/types/comments/). For example, you can import the generated Flow types like so: ```javascript - import type {DictionaryComponent_word} from './__generated__/DictionaryComponent_word.graphql'; - ``` ### Client schema extensions @@ -342,7 +319,6 @@ The Relay Compiler fully supports client-side schema extensions, which allows yo For example, assuming the server schema `./schema.graphql`: ```graphql - schema { query: Root } @@ -350,28 +326,23 @@ schema { type Root { title: String! } - ``` We can create a `./src/clientSchema.graphql` and define a new type called `Setting`: ```graphql - type Setting { name: String! active: Boolean! } - ``` We can then extend existing server types in the client schema `./src/clientSchema.graphql` with our new `Setting` type, like so: ```graphql - extend type Root { settings: [Setting] } - ``` Any fields specified in the client schema, can be fetched from the [Relay Store](./relay-store), by selecting it in a query or fragment. diff --git a/website/versioned_docs/version-v10.1.3/Modern-LocalStateManagement.md b/website/versioned_docs/version-v10.1.3/Modern-LocalStateManagement.md index da71a0dd33246..3ecbf6801f91c 100644 --- a/website/versioned_docs/version-v10.1.3/Modern-LocalStateManagement.md +++ b/website/versioned_docs/version-v10.1.3/Modern-LocalStateManagement.md @@ -24,23 +24,19 @@ It can even be used to extend an existing server schema. For example, we can create a new type called `Note`: ```graphql - type Note { id: ID! title: String body: String } - ``` And then extend the server schema type `User`, with a list of `Note`, called `notes`. ```graphql - extend type User { notes: [Note] } - ``` ## Querying local state @@ -51,7 +47,6 @@ The field can be from the server schema, or it can be schema agnostic, like an i Here, we use a [QueryRenderer](./query-renderer) to get the current `User` via the `viewer` field, along with their id, name and the local list of notes. ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -97,7 +92,6 @@ const Example = (props) => { /> ); } - ``` ## Mutating local state @@ -111,7 +105,6 @@ To build upon the previous example, let's try creating, updating and deleting a ### Create ```javascript - import {commitLocalUpdate} from 'react-relay'; let tempID = 0; @@ -131,7 +124,6 @@ function createUserNote() { user.setLinkedRecords([...userNoteRecords, newNoteRecord], 'notes'); }); } - ``` Note that since this record will be rendered by the `ExampleQuery` in our `QueryRenderer`, the QueryRenderer will automatically retain this data so it isn't garbage collected. @@ -139,7 +131,6 @@ Note that since this record will be rendered by the `ExampleQuery` in our `Query If no component is rendering the local data and you want to manually retain it, you can do so by calling `environment.retain()`: ```javascript - import {createOperationDescriptor, getRequest} from 'relay-runtime'; // Create a query that references that record @@ -166,13 +157,11 @@ const disposable = environment.retain(operation); // Whenever you don't need that data anymore and it's okay for Relay to garbage collect it, // you can dispose of the retain disposable.dispose(); - ``` ### Update ```javascript - import {commitLocalUpdate} from 'react-relay'; function updateUserNote(dataID, body, title) { @@ -183,13 +172,11 @@ function updateUserNote(dataID, body, title) { note.setValue(title, 'title') }); } - ``` ### Delete ```javascript - import {commitLocalUpdate} from 'react-relay'; function deleteUserNote(dataID) { @@ -207,7 +194,6 @@ function deleteUserNote(dataID) { user.setLinkedRecords(newUserNoteRecords, 'notes'); }); } - ``` ## Initial local state @@ -216,7 +202,6 @@ All new client-side schema fields default to `undefined` value. Often however, y You can use an updater function via `commitLocalUpdate` to prime local state. ```javascript - import {commitLocalUpdate} from 'react-relay'; commitLocalUpdate(environment, store => { @@ -225,5 +210,4 @@ commitLocalUpdate(environment, store => { // initialize user notes to an empty array. user.setLinkedRecords([], 'notes'); }); - ``` diff --git a/website/versioned_docs/version-v10.1.3/Modern-MigrationSetup.md b/website/versioned_docs/version-v10.1.3/Modern-MigrationSetup.md index 66f1145357e25..a89c0e178e0e5 100644 --- a/website/versioned_docs/version-v10.1.3/Modern-MigrationSetup.md +++ b/website/versioned_docs/version-v10.1.3/Modern-MigrationSetup.md @@ -13,13 +13,11 @@ With some additional configuration, the `"relay"` babel plugin can also translat Relay Classic `Relay.QL` literals. Most importantly, include a reference to your GraphQL Schema as either a json file or graphql schema file. ```javascript - { "plugins": [ ["relay", {"schema": "path/schema.graphql"}] ] } - ``` ## Set up babel-plugin-relay for "[compatibility mode](./relay-compat)" @@ -29,13 +27,11 @@ literals can be translated to be usable by _both_ runtimes if configured to use compatibility mode: ```javascript - { "plugins": [ ["relay", {"compat": true, "schema": "path/schema.graphql"}] ] } - ``` ## Additional Options @@ -47,7 +43,6 @@ thrown at runtime. When compiling code for production deployment, the plugin can be configured to immediately throw upon encountering a validation problem. The plugin can be further customized for different environments with the following options: ```javascript - { "plugins": [ ["relay", { @@ -56,5 +51,4 @@ When compiling code for production deployment, the plugin can be configured to i }] ] } - ``` diff --git a/website/versioned_docs/version-v10.1.3/Modern-Mutations.md b/website/versioned_docs/version-v10.1.3/Modern-Mutations.md index 58ec471bdaf33..fab109335dd2f 100644 --- a/website/versioned_docs/version-v10.1.3/Modern-Mutations.md +++ b/website/versioned_docs/version-v10.1.3/Modern-Mutations.md @@ -17,7 +17,6 @@ Table of Contents: Use `commitMutation` to create and execute mutations. `commitMutation` has the following signature: ```javascript - commitMutation( environment: Environment, config: { @@ -32,7 +31,6 @@ commitMutation( cacheConfig?: CacheConfig, }, ); - ``` ### Arguments @@ -60,7 +58,6 @@ commitMutation( Example of a simple mutation: ```javascript - import {commitMutation, graphql} from 'react-relay'; const mutation = graphql` @@ -92,7 +89,6 @@ function markNotificationAsRead(environment, storyID) { }, ); } - ``` ## Optimistic Updates @@ -100,7 +96,6 @@ function markNotificationAsRead(environment, storyID) { To improve perceived responsiveness, you may wish to perform an "optimistic update", in which the client immediately updates to reflect the anticipated new value even before the response from the server has come back. The simplest way to do this is by providing an `optimisticResponse` and adding it to the `config` that we pass into `commitMutation`: ```javascript - const mutation = graphql` mutation MarkReadNotificationMutation( $storyID: ID! @@ -129,7 +124,6 @@ commitMutation( variables, }, ); - ``` Another way to enable optimistic updates is via the `optimisticUpdater`, which can be used for more complicated update scenarios. Using `optimisticUpdater` is covered in the section [below](#using-updater-and-optimisticupdater). @@ -151,7 +145,6 @@ Given a `deletedIDFieldName`, Relay will remove the node(s) from the store. #### Example ```javascript - const mutation = graphql` mutation DestroyShipMutation($target: ID!) { destroyShip(target: $target) { @@ -169,7 +162,6 @@ const configs = [{ type: 'NODE_DELETE', deletedIDFieldName: 'destroyedShipId', }]; - ``` ### RANGE_ADD @@ -189,7 +181,6 @@ Given a parent, information about the connection, and the name of the newly crea #### Example ```javascript - const mutation = graphql` mutation AddShipMutation($factionID: ID!, $name: String!) { addShip(factionID: $factionID, name: $name) { @@ -220,7 +211,6 @@ function commit(environment, factionID, name) { }], }); } - ``` ### RANGE_DELETE @@ -242,7 +232,6 @@ from the connection but leave the associated record(s) in the store. #### Example ```javascript - const mutation = graphql` mutation RemoveTagMutation($todoID: ID!, $tagID: ID!) { removeTag(todo: $todoID, tag: $tagID) { @@ -269,7 +258,6 @@ function commit(environment, todoID, tagID) { }], }); } - ``` ## Using updater and optimisticUpdater @@ -287,7 +275,6 @@ When you provide these functions, this is roughly what happens during the mutati Here's a quick example of adding a todo item to a Todo list using this [example schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L36): ```javascript - // AddTodoMutation.js import {commitMutation, graphql} from 'react-relay'; import {ConnectionHandler} from 'relay-runtime'; @@ -371,7 +358,6 @@ function commit(environment, text, user) { }, }); } - ``` For details on how to interact with the Relay Store, please refer to our Relay Store [docs](./relay-store). diff --git a/website/versioned_docs/version-v10.1.3/Modern-NetworkLayer.md b/website/versioned_docs/version-v10.1.3/Modern-NetworkLayer.md index 9dddd36d6c235..c9e069b812b01 100644 --- a/website/versioned_docs/version-v10.1.3/Modern-NetworkLayer.md +++ b/website/versioned_docs/version-v10.1.3/Modern-NetworkLayer.md @@ -8,7 +8,6 @@ In order to know how to access your GraphQL server, Relay Modern requires develo Currently the easiest way to create a network layer is via a helper from the `relay-runtime` package: ```javascript - import { Environment, Network, @@ -50,7 +49,6 @@ const environment = new Environment({ }); export default environment; - ``` Note that this is a basic example to help you get started. This example could be extended with additional features such as request/response caching (enabled e.g. when `cacheConfig.force` is false) and uploading form data for mutations (the `uploadables` parameter). @@ -62,7 +60,6 @@ Relay modern makes no assumptions about what to cache and will garbage collect a You have to implement your own cache strategy. A simple solution is to use `QueryResponseCache` (an in-memory cache): ```javascript - import { Environment, Network, @@ -126,7 +123,6 @@ const environment = new Environment({ }); export default environment; - ``` ## Custom open-source implementations diff --git a/website/versioned_docs/version-v10.1.3/Modern-PaginationContainer.md b/website/versioned_docs/version-v10.1.3/Modern-PaginationContainer.md index 6ac3aac8cfb8e..57980d553af9b 100644 --- a/website/versioned_docs/version-v10.1.3/Modern-PaginationContainer.md +++ b/website/versioned_docs/version-v10.1.3/Modern-PaginationContainer.md @@ -24,7 +24,6 @@ However, when [specifying connection fragments](#createpaginationcontainer) for The purpose of the `@connection` directive is to allow Relay to uniquely identify different connections under a parent type. The `@connection` directive takes 2 arguments that help identify the connection: ```graphql - @connection(key: String!, filters: [String]) ``` @@ -37,7 +36,6 @@ The purpose of the `@connection` directive is to allow Relay to uniquely identif Specifying just the `key`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and the value of `$orderBy` (given that no `filters` were provided) @@ -53,13 +51,11 @@ fragment Feed_user on User { } } } - ``` Specifying `key` and `filters`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and /only/ the value of `$searchTerm`, i.e. @@ -77,7 +73,6 @@ fragment Feed_user on User { } } } - ``` ## `createPaginationContainer` @@ -85,7 +80,6 @@ fragment Feed_user on User { `createPaginationContainer` has the following signature: ```javascript - createPaginationContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, @@ -113,7 +107,6 @@ type ConnectionData = { startCursor: ?string, }, }; - ``` ### Arguments @@ -134,7 +127,6 @@ type ConnectionData = { The Component resulting from `createPaginationContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -145,7 +137,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -160,7 +151,6 @@ type Props = { `hasMore` is a function available on the `relay` [prop](#available-props). This function indicates whether there are more pages to fetch from the server or not. ```javascript - hasMore: () => boolean, ``` @@ -170,7 +160,6 @@ hasMore: () => boolean, `isLoading` is a function available on the `relay` [prop](#available-props). This function indicates if a previous call to [`loadMore()`](#loadmore) is still pending. This is convenient for avoiding duplicate load calls. ```javascript - isLoading: () => boolean, ``` @@ -180,7 +169,6 @@ isLoading: () => boolean, `loadMore` is a function available on the `relay` [prop](#available-props). You can call `loadMore()` to fetch more items from the server based on the `connectionConfig` provided to the container. This will return null if there are no more items to fetch, otherwise it will fetch more items and return a Disposable that can be used to cancel the fetch. ```javascript - loadMore( pageSize: number, callback: ?(error: ?Error) => void, @@ -201,7 +189,6 @@ loadMore( `refetchConnection` is a function available on the `relay` [prop](#available-props). You can call `refetchConnection` to restart pagination on a connection from scratch, with optionally a completely new set of variables to pass to the pagination `query`. This is useful for example if you are paginating over a collection based on a userID and the userID changes, you'd want to start paginating over the new collection for the new user. ```javascript - refetchConnection:( totalCount: number, callback: (error: ?Error) => void, @@ -219,7 +206,6 @@ refetchConnection:( ## Pagination Example ```javascript - // Feed.js import {createPaginationContainer, graphql} from 'react-relay'; @@ -314,5 +300,4 @@ module.exports = createPaginationContainer( ` } ); - ``` diff --git a/website/versioned_docs/version-v10.1.3/Modern-PersistedQueries.md b/website/versioned_docs/version-v10.1.3/Modern-PersistedQueries.md index a0316f4fc42cd..f87bf7b146ca7 100644 --- a/website/versioned_docs/version-v10.1.3/Modern-PersistedQueries.md +++ b/website/versioned_docs/version-v10.1.3/Modern-PersistedQueries.md @@ -17,12 +17,10 @@ The relay compiler supports persisted queries which is useful because: In your `npm` script in `package.json`, run the relay compiler using the `--persist-output` flag: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` The `--persist-ouput` flag does 2 things: @@ -31,8 +29,7 @@ The `--persist-ouput` flag does 2 things: For example without `--persist-output`, a generated `ConcreteRequest` might look like below: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -49,8 +46,7 @@ The `--persist-ouput` flag does 2 things: With `--persist-output ` this becomes: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -68,12 +64,10 @@ The `--persist-ouput` flag does 2 things: 2. It generates a JSON file at the `` you specify containing a mapping from query ids to the corresponding operation texts. -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./src/queryMaps/queryMap.json" } - ``` The example above writes the complete query map file to `./src/queryMaps/queryMap.json`. You need to ensure all the directories @@ -83,8 +77,7 @@ leading to the `queryMap.json` file exist. You'll need to modify your network layer fetch implementation to pass a documentId parameter in the POST body instead of a query parameter: -```js - +```javascript function fetchQuery(operation, variables,) { return fetch('/graphql', { method: 'POST', @@ -100,7 +93,6 @@ function fetchQuery(operation, variables,) { return response.json(); }); } - ``` ## Executing Persisted Queries on the Server @@ -116,13 +108,11 @@ the query map file in a common location accessible to both the client and the se For applications where the client and server projects are separate, one option is to have an additional npm run script to push the query map at compile time to a location accessible by your server: -```js - +```javascript "scripts": { "push-queries": "node ./pushQueries.js", "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-ouput && npm run push-queries" } - ``` Some possibilities of what you can do in `./pushQueries.js`: @@ -146,8 +136,7 @@ database technologies you use, so we'll just cover the most common and basic exa If you use `express-graphql` and have access to the query map file, you can import the `--persist-output` JSON file directly and perform the matching using the `matchQueryMiddleware` from [relay-compiler-plus](https://github.com/yusinto/relay-compiler-plus). -```js - +```javascript import Express from 'express'; import expressGraphql from 'express-graphql'; import {matchQueryMiddleware} from 'relay-compiler-plus'; @@ -158,7 +147,6 @@ const app = Express(); app.use('/graphql', matchQueryMiddleware(queryMapJson), expressGraphql({schema})); - ``` ## Using `--persist-output` and `--watch` diff --git a/website/versioned_docs/version-v10.1.3/Modern-QueryRenderer.md b/website/versioned_docs/version-v10.1.3/Modern-QueryRenderer.md index cf6c37f3d9a4d..b621ef9986bf1 100644 --- a/website/versioned_docs/version-v10.1.3/Modern-QueryRenderer.md +++ b/website/versioned_docs/version-v10.1.3/Modern-QueryRenderer.md @@ -24,7 +24,6 @@ However, a `QueryRenderer` will not start loading its data until it is mounted, ## Example ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -56,5 +55,4 @@ const Example = (props) => { /> ); } - ``` diff --git a/website/versioned_docs/version-v10.1.3/Modern-RefetchContainer.md b/website/versioned_docs/version-v10.1.3/Modern-RefetchContainer.md index 7ce0d14e45417..51c2c44db8941 100644 --- a/website/versioned_docs/version-v10.1.3/Modern-RefetchContainer.md +++ b/website/versioned_docs/version-v10.1.3/Modern-RefetchContainer.md @@ -16,13 +16,11 @@ Table of Contents: `createRefetchContainer` has the following signature: ```javascript - createRefetchContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, refetchQuery: GraphQLTaggedNode, ): ReactComponentClass; - ``` ### Arguments @@ -37,7 +35,6 @@ createRefetchContainer( The Component resulting from `createRefetchContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -45,7 +42,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -61,7 +57,6 @@ type Props = { `refetch` has the following signature: ```javascript - type RefetchOptions = { force?: boolean, }; @@ -102,7 +97,6 @@ Returns a `Disposable` on which you could call `dispose()` to cancel the refetch In this simple example, let's assume we want to fetch the latest data for a `TodoItem` from the server: ```javascript - // TodoItem.js import {createRefetchContainer, graphql} from 'react-relay'; @@ -148,7 +142,6 @@ export default createRefetchContainer( } ` ); - ``` ### Loading more data @@ -156,7 +149,6 @@ export default createRefetchContainer( In this example we are using a Refetch Container to fetch more stories in a story feed component. ```javascript - import {createRefetchContainer, graphql} from 'react-relay'; class FeedStories extends React.Component { @@ -212,5 +204,4 @@ export default createRefetchContainer( } `, ); - ``` diff --git a/website/versioned_docs/version-v10.1.3/Modern-RelayCompat.md b/website/versioned_docs/version-v10.1.3/Modern-RelayCompat.md index 36632d3a8f1a1..f47dbd845ba3e 100644 --- a/website/versioned_docs/version-v10.1.3/Modern-RelayCompat.md +++ b/website/versioned_docs/version-v10.1.3/Modern-RelayCompat.md @@ -31,7 +31,6 @@ Relay Modern. The components using Relay Compat can be referred to by both other Relay Modern and Relay Classic components. ```javascript - const {createFragmentContainer, graphql} = require('react-relay/compat'); class TodoItem extends React.Component { @@ -47,5 +46,4 @@ module.exports = createFragmentContainer(TodoItem, graphql` isComplete } `); - ``` diff --git a/website/versioned_docs/version-v10.1.3/Modern-RelayEnvironment.md b/website/versioned_docs/version-v10.1.3/Modern-RelayEnvironment.md index 27d90b2fc4fe1..99e728bce740d 100644 --- a/website/versioned_docs/version-v10.1.3/Modern-RelayEnvironment.md +++ b/website/versioned_docs/version-v10.1.3/Modern-RelayEnvironment.md @@ -12,7 +12,6 @@ Most applications will create a single Environment instance and use it throughou To create an environment instance in Relay Modern, use the `RelayModernEnvironment` class: ```javascript - const { Environment, Network, @@ -30,7 +29,6 @@ const environment = new Environment({ network, store, }); - ``` For more details on creating a Network, see the [NetworkLayer guide](./network-layer). @@ -44,7 +42,6 @@ The example above did not configure a `handlerProvider`, which means that a defa If you wish to provide your own `handlerProvider`, you can do so: ```javascript - const { ConnectionHandler, } = require('relay-runtime'); @@ -58,5 +55,4 @@ function handlerProvider(handle) { `handlerProvider: No handler provided for ${handle}` ); } - ``` diff --git a/website/versioned_docs/version-v10.1.3/Modern-RelayStore.md b/website/versioned_docs/version-v10.1.3/Modern-RelayStore.md index 82fdee3b3555d..e096947a2cf66 100644 --- a/website/versioned_docs/version-v10.1.3/Modern-RelayStore.md +++ b/website/versioned_docs/version-v10.1.3/Modern-RelayStore.md @@ -16,7 +16,6 @@ Table of Contents: The `RecordSourceSelectorProxy` is the type of the `store` that [`updater` functions](./mutations#using-updater-and-optimisticupdater) receive as an argument. The following is the `RecordSourceSelectorProxy` interface: ```javascript - interface RecordSourceSelectorProxy { create(dataID: string, typeName: string): RecordProxy; delete(dataID: string): void; @@ -26,7 +25,6 @@ interface RecordSourceSelectorProxy { getPluralRootField(fieldName: string): ?Array; invalidateStore(): void; } - ``` ### `create(dataID: string, typeName: string): RecordProxy` @@ -36,9 +34,7 @@ Creates a new record in the store given a `dataID` and the `typeName` as defined #### Example ```javascript - const record = store.create(dataID, 'Todo'); - ``` ### `delete(dataID: string): void` @@ -48,9 +44,7 @@ Deletes a record from the store given its `dataID`. #### Example ```javascript - store.delete(dataID); - ``` ### `get(dataID: string): ?RecordProxy` @@ -60,9 +54,7 @@ Retrieves a record from the store given its `dataID`. Returns a [`RecordProxy`]( #### Example ```javascript - const record = store.get(dataID); - ``` ### `getRoot(): RecordProxy` @@ -74,20 +66,16 @@ Returns the [`RecordProxy`](#recordproxy) representing the root of the GraphQL d Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - // Represents root query const root = store.getRoot(); - ``` ### `getRootField(fieldName: string): ?RecordProxy` @@ -99,19 +87,15 @@ Retrieves a root field from the store given the `fieldName`, as defined by the G Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - const viewer = store.getRootField('viewer'); - ``` ### `getPluralRootField(fieldName: string): ?Array` @@ -123,19 +107,15 @@ Retrieves a root field that represents a collection from the store given the `fi Given the GraphQL document: ```graphql - nodes(first: 10) { # ... } - ``` Usage: ```javascript - const nodes = store.getPluralRootField('nodes'); - ``` ### `invalidateStore(): void` @@ -145,15 +125,12 @@ Globally invalidates the Relay store. This will cause any data that was written #### Example ```javascript - store.invalidateStore(); - ``` After global invalidation, any query that is checked before refetching it will be considered stale: ```javascript - environment.check(query) === 'stale' ``` @@ -163,7 +140,6 @@ environment.check(query) === 'stale' The `RecordProxy` serves as an interface to mutate records: ```javascript - interface RecordProxy { copyFieldsFrom(sourceRecord: RecordProxy): void; getDataID(): string; @@ -189,7 +165,6 @@ interface RecordProxy { setValue(value: mixed, name: string, arguments?: ?Object): RecordProxy; invalidateRecord(): void; } - ``` ### `getDataID(): string` @@ -199,9 +174,7 @@ Returns the `dataID` of the current record. #### Example ```javascript - const id = record.getDataID(); - ``` ### `getType(): string` @@ -211,7 +184,6 @@ Gets the type of the current record, as defined by the GraphQL schema. #### Example ```javascript - const type = user.getType(); // User ``` @@ -225,20 +197,16 @@ Gets the value of a field in the current record given the field name. Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - const name = viewer.getValue('name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. @@ -248,20 +216,16 @@ Optionally, if the field takes arguments, you can pass a bag of `variables`. Given the GraphQL document: ```graphql - viewer { id name(arg: $arg) } - ``` Usage: ```javascript - const name = viewer.getValue('name', {arg: 'value'}); - ``` ### `getLinkedRecord(name: string, arguments?: ?Object): ?RecordProxy` @@ -273,23 +237,19 @@ Retrieves a record associated with the current record given the field name, as d Given the GraphQL document: ```graphql - rootField { viewer { id name } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -299,22 +259,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { viewer(arg: $arg) { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {arg: 'value'}); - ``` ### `getLinkedRecords(name: string, arguments?: ?Object): ?Array` @@ -326,22 +282,18 @@ Retrieves the set of records associated with the current record given the field Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const nodes = rootField.getLinkedRecords('nodes'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -351,22 +303,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { nodes(first: $count) { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const nodes = rootField.getLinkedRecords('nodes', {count: 10}); - ``` ### `getOrCreateLinkedRecord(name: string, typeName: string, arguments?: ?Object)` @@ -378,19 +326,16 @@ Retrieves a record associated with the current record given the field name, as d Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = rootField.getOrCreateLinkedRecord('viewer', 'User'); // Will create if it doesn't exist @@ -405,28 +350,22 @@ Mutates the current record by setting a new value on the specified field. Return Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - viewer.setValue('New Name', 'name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. ```javascript - viewer.setValue('New Name', 'name', {arg: 'value'}); - ``` ### `copyFieldsFrom(sourceRecord: RecordProxy): void` @@ -436,7 +375,6 @@ Mutates the current record by copying the fields over from the passed in record #### Example ```javascript - const record = store.get(id1); const otherRecord = store.get(id2); record.copyFieldsFrom(otherRecord); // Mutates `record` @@ -452,23 +390,19 @@ Mutates the current record by setting a new linked record on the given field nam Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = store.create(/* ... */); rootField.setLinkedRecord(newViewer, 'viewer'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -482,24 +416,20 @@ Mutates the current record by setting a new set of linked records on the given f Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newNode = store.create(/* ... */); const newNodes = [...rootField.getLinkedRecords('nodes'), newNode]; rootField.setLinkedRecords(newNodes, 'nodes'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -511,16 +441,13 @@ Invalidates the record. This will cause any query that references this record to #### Example ```javascript - const record = store.get('4'); record.invalidateRecord(); - ``` After invalidating a record, any query that references the invalidated record and that is checked before refetching it will be considered stale: ```javascript - environment.check(query) === 'stale' ``` @@ -530,7 +457,6 @@ environment.check(query) === 'stale' `ConnectionHandler` is a utility module exposed by `relay-runtime` that aids in the manipulation of connections. `ConnectionHandler` exposes the following interface: ```javascript - interface ConnectionHandler { getConnection( record: RecordProxy, @@ -555,7 +481,6 @@ interface ConnectionHandler { ): void, deleteNode(connection: RecordProxy, nodeID: string): void } - ``` ### `getConnection(record: RecordProxy, key: string, filters?: ?Object)` @@ -565,7 +490,6 @@ Given a record and a connection key, and optionally a set of filters, `getConnec First, let's take a look at a plain connection: ```graphql - fragment FriendsFragment on User { friends(first: 10) { edges { @@ -575,26 +499,22 @@ fragment FriendsFragment on User { } } } - ``` Accessing a plain connection field like this is the same as other regular fields: ```javascript - // The `friends` connection record can be accessed with: const user = store.get(userID); const friends = user && user.getLinkedRecord('friends'); // Access fields on the connection: const edges = friends && friends.getLinkedRecords('edges'); - ``` In a [pagination container](./pagination-container), we usually annotate the actual connection field with `@connection` to tell Relay which part needs to be paginated: ```graphql - fragment FriendsFragment on User { friends(first: 10, orderby: "firstname") @connection( key: "FriendsFragment_friends", @@ -606,13 +526,11 @@ fragment FriendsFragment on User { } } } - ``` For connections like the above, `ConnectionHandler` helps us find the record: ```javascript - import {ConnectionHandler} from 'relay-runtime'; // The `friends` connection record can be accessed with: @@ -624,7 +542,6 @@ const friends = ConnectionHandler.getConnection( ); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` ### Edge creation and insertion @@ -644,7 +561,6 @@ Given a connection, inserts the edge at the end of the connection, or after the #### Example ```javascript - const user = store.get(userID); const friends = ConnectionHandler.getConnection(user, 'FriendsFragment_friends'); const newFriend = store.get(newFriendId); @@ -655,7 +571,6 @@ ConnectionHandler.insertEdgeAfter(friends, edge); // No cursor provided, insert the edge at the front: ConnectionHandler.insertEdgeBefore(friends, edge); - ``` ### `deleteNode(connection: RecordProxy, nodeID: string): void` @@ -665,9 +580,7 @@ Given a connection, deletes any edges whose node id matches the given id. #### Example ```javascript - const user = store.get(userID); const friends = ConnectionHandler.getConnection(user, 'FriendsFragment_friends'); ConnectionHandler.deleteNode(friends, idToDelete); - ``` diff --git a/website/versioned_docs/version-v10.1.3/Modern-Subscriptions.md b/website/versioned_docs/version-v10.1.3/Modern-Subscriptions.md index 671b28f684403..85ade0f34c511 100644 --- a/website/versioned_docs/version-v10.1.3/Modern-Subscriptions.md +++ b/website/versioned_docs/version-v10.1.3/Modern-Subscriptions.md @@ -6,7 +6,6 @@ original_id: subscriptions Relay exposes the following APIs to create subscriptions. ```javascript - import { requestSubscription } from 'react-relay'; type Variables = {[name: string]: any}; @@ -28,7 +27,6 @@ requestSubscription( cacheConfig?: CacheConfig, }, ) => Disposable; - ``` The function returns a `Disposable` on which you could call `dispose()` to cancel the refetch. @@ -55,7 +53,6 @@ appropriate when you are only changing the properties of existing records that can be identified by their `id`: ```javascript - import { requestSubscription, graphql, @@ -89,7 +86,6 @@ requestSubscription( onError: error => console.error(error), } ); - ``` # Configure Network @@ -97,7 +93,6 @@ requestSubscription( You will need to Configure your [Network](./network-layer) to handle subscriptions. The below example uses [subscriptions-transport-ws](https://github.com/apollographql/subscriptions-transport-ws): ```javascript - import { ... Network, @@ -134,7 +129,6 @@ Relay's in-memory cache when each subscription response is received. To do so, pass an `updater` function: ```javascript - import { ConnectionHandler } from 'relay-runtime'; requestSubscription( @@ -160,5 +154,4 @@ requestSubscription( }, }, ); - ``` diff --git a/website/versioned_docs/version-v10.1.3/Modern-TestingRelayComponents.md b/website/versioned_docs/version-v10.1.3/Modern-TestingRelayComponents.md index 94cb9ee91d36a..711bc65c92dec 100644 --- a/website/versioned_docs/version-v10.1.3/Modern-TestingRelayComponents.md +++ b/website/versioned_docs/version-v10.1.3/Modern-TestingRelayComponents.md @@ -65,7 +65,6 @@ With the `MockPayloadGenerator` and `@relay_test_operation`, we want to get rid Example of a simple Mock Resolver: ```javascript - { ID() { // Return mock value for a scalar filed with type ID @@ -76,13 +75,11 @@ Example of a simple Mock Resolver: return "Lorem Ipsum" } } - ``` It is possible to define more resolvers for Object types: ```javascript - { // This will be the default values for User object in the query response User() { @@ -95,7 +92,6 @@ It is possible to define more resolvers for Object types: }; }, } - ``` ### Mock Resolver Context @@ -103,7 +99,6 @@ It is possible to define more resolvers for Object types: The first argument of the MockResolver is the object that contains Mock Resolver Context. It is possible to return dynamic values from mock resolvers based on the context - for instance, name or alias of the field, a path in the selection, arguments, or parent type. ```javascript - { String(context) { if (context.name === 'zip') { @@ -117,7 +112,6 @@ The first argument of the MockResolver is the object that contains Mock Resolver } } } - ``` ### ID Generation @@ -125,14 +119,12 @@ The first argument of the MockResolver is the object that contains Mock Resolver The second argument of the Mock Resolver its a function that will generate a sequence of integers, useful to generate unique IDs in the tests: ```javascript - { // will generate strings "my-id-1", "my-id-2", etc. ID(_, generateId) { return `my-id-${generateId()}`; }, } - ``` ### `@relay_test_operation` @@ -142,7 +134,6 @@ Most of GraphQL type information for a specific field in the selection is not av Operations with the `@relay_test_operation` directive will have additional metadata that will contain GraphQL type info for fields in the operation's selection. And it will improve the quality of the generated data. You also will be able to define Mock resolvers for Scalar (not only ID and String) and Abstract types: ```javascript - { Float() { return 123.456; @@ -160,7 +151,6 @@ Operations with the `@relay_test_operation` directive will have additional metad }; } } - ``` ## Examples @@ -170,7 +160,6 @@ Operations with the `@relay_test_operation` directive will have additional metad Using `createMockEnvironment` and `MockPayloadGenerator` allows writing concise tests for components that are using Relay Containers and Renderers. Both those modules can be imported from `relay-test-utils`. ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { @@ -223,7 +212,6 @@ test('Error State', () => { renderer.root.find(item => (item.props.testID = 'errorMessage')), ).toBeDefined(); }); - ``` ### Fragment Container Tests @@ -231,7 +219,6 @@ test('Error State', () => { Essentially, in the example above, `resolveMostRecentOperation` will generate data for all child fragment containers (pagination, refetch). Usually, the Root Components container may have many child fragment components and you may want to exercise a specific Fragment Container. The solution for that would be to wrap your fragment container with the QueryRenderer that renders a Query that's spreads fragments from your fragment container. ```javascript - test('Fragment Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -262,7 +249,6 @@ test('Fragment Container', () => { expect(renderer).toMatchSnapshot(); }); - ``` ### Pagination Container Test @@ -270,7 +256,6 @@ test('Fragment Container', () => { Essentially, tests for Pagination container are not different from Fragment Container tests. We can also do more here. We can actually see how the pagination works by asserting the behavior of our components when performing pagination (load more, refetch). ```javascript - // Pagination Example test('Pagination Container', () => { const environment = createMockEnvironment(); @@ -344,7 +329,6 @@ test('Pagination Container', () => { We can use similar approach here with wrapping container with Query Renderer. And for the sake of completeness, we will add example here: ```javascript - test('Refetch Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -386,7 +370,6 @@ test('Refetch Container', () => { ); // expect(renderer).toMatchSnapshot(); }); - ``` ### Mutations @@ -394,7 +377,6 @@ test('Refetch Container', () => { Mutations itself are operations so we can test them independently (unit-test) for specific mutation, or in combination with the view from which this mutation is called. ```javascript - // Say, you have a mutation function function sendMutation(environment, onCompleted, onError, variables) commitMutation(environment, { @@ -417,7 +399,6 @@ test('it should send mutation', () => { ); expect(onCompleted).toBeCalled(); }); - ``` ### Subscription @@ -425,7 +406,6 @@ test('it should send mutation', () => { We can test subscription in a similar way we test mutations ```javascript - // Example subscribe function function subscribe(environment, onNext, onError, variables) requestSubscription(environment, { @@ -448,7 +428,6 @@ test('it should subscribe', () => { ); expect(onNext).toBeCalled(); }); - ``` ### Example with `queueOperationResolver` @@ -456,7 +435,6 @@ test('it should subscribe', () => { With `queueOpeararionResolver`, it possible to define responses for operations that will be executed on the environment ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { diff --git a/website/versioned_docs/version-v10.1.3/Modern-TypeEmission.md b/website/versioned_docs/version-v10.1.3/Modern-TypeEmission.md index 63614b869a322..4ff63e4a7d81b 100644 --- a/website/versioned_docs/version-v10.1.3/Modern-TypeEmission.md +++ b/website/versioned_docs/version-v10.1.3/Modern-TypeEmission.md @@ -16,7 +16,6 @@ In this example the emitted type-information would require the variables object #### Flow ```javascript - /** * export type ExampleQueryVariables = {| * +artistID: string @@ -44,7 +43,6 @@ const variables: ExampleQueryVariables = { #### TypeScript ```javascript - /** * export type ExampleQueryVariables = { * readonly artistID: string @@ -79,7 +77,6 @@ In this example the emitted type-information describes the response data availab #### Flow ```javascript - /** * export type ExampleQueryResponse = {| * +artist: ?{| @@ -110,7 +107,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * export type ExampleQueryResponse = { * readonly artist?: { @@ -146,7 +142,6 @@ Similarly, in this example the emitted type-information describes the prop data #### Flow ```javascript - /** * export type ExampleFragment_artist = {| * +name: string @@ -172,7 +167,6 @@ export const ExampleFragment = createFragmentContainer( #### TypeScript ```javascript - /** * export type ExampleFragment_artist = { * readonly name: string @@ -206,7 +200,6 @@ Consider a component that composes the above fragment container example. In this #### Flow ```javascript - /** * import type { FragmentReference } from "relay-runtime"; * declare export opaque type ExampleFragment_artist$ref: FragmentReference; @@ -250,7 +243,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * declare const _ExampleFragment_artist$ref: unique symbol; * export type ExampleFragment_artist$ref = typeof _ExampleFragment_artist$ref; @@ -315,7 +307,6 @@ $ relay-compiler --artifactDirectory ./src/__generated__ […] ["relay", { "artifactDirectory": "./src/__generated__" }] ] } - ``` It is recommended to alias this directory in your module resolution configuration such that you don’t need to specify relative paths in your source files. This is what is also done in the above examples, where artifacts are imported from a `__generated__` alias, rather than relative paths like `../../../../__generated__`. diff --git a/website/versioned_docs/version-v10.1.3/Modern-UpgradingSetVariables.md b/website/versioned_docs/version-v10.1.3/Modern-UpgradingSetVariables.md index d5b086fafce20..ff73feec04f8b 100644 --- a/website/versioned_docs/version-v10.1.3/Modern-UpgradingSetVariables.md +++ b/website/versioned_docs/version-v10.1.3/Modern-UpgradingSetVariables.md @@ -36,7 +36,6 @@ fragment on User { # ... } } - ``` This should be upgraded to use a [`PaginationContainer`](./pagination-container). @@ -61,7 +60,6 @@ fragment on User { # ... } } - ``` This can be upgraded by using a [`RefetchContainer`](./refetch-container) which allows you to specify the exact query to use to fetch the new data. @@ -86,7 +84,6 @@ fragment on FeedbackTarget { # ... } } - ``` This can be upgraded by conditionally rendering a [`QueryRenderer`](./query-renderer) which will load the data once it is rendered. The code overhead of doing this is dramatically reduced with the new API. diff --git a/website/versioned_docs/version-v10.1.3/Modern-fetchQuery.md b/website/versioned_docs/version-v10.1.3/Modern-fetchQuery.md index 2e9461ad527bd..c1a06ab7d2493 100644 --- a/website/versioned_docs/version-v10.1.3/Modern-fetchQuery.md +++ b/website/versioned_docs/version-v10.1.3/Modern-fetchQuery.md @@ -6,7 +6,6 @@ original_id: fetch-query You can use the `fetchQuery` function to imperatively make GraphQL Requests. This is useful for cases where you want to make requests outside of React but still utilize the Relay store and network layer. ```javascript - import {fetchQuery, graphql} from 'relay-runtime'; const query = graphql` @@ -25,7 +24,6 @@ fetchQuery(environment, query, variables) .then(data => { // access the graphql response }); - ``` ## Arguments diff --git a/website/versioned_docs/version-v10.1.3/PrinciplesAndArchitecture-Compiler.md b/website/versioned_docs/version-v10.1.3/PrinciplesAndArchitecture-Compiler.md index c195491682b1f..fcd0490cb724f 100644 --- a/website/versioned_docs/version-v10.1.3/PrinciplesAndArchitecture-Compiler.md +++ b/website/versioned_docs/version-v10.1.3/PrinciplesAndArchitecture-Compiler.md @@ -74,7 +74,6 @@ foo { # type FooType foo { id } - ``` - `SkipRedundantNodeTransform`: A more advanced version of flattening, this eliminates more complex cases of field duplication such as when a field is fetched both unconditionally and conditionally, or is fetched by two different sub-fragments. For example: @@ -97,7 +96,6 @@ foo { id } } - ``` - `GenerateRequisiteFieldTransform`: This optional, Relay-specific transform inserts `id` fields for globally identifiable objects and `__typename` fields wherever the type cannot be statically determined (e.g. for unions). diff --git a/website/versioned_docs/version-v10.1.3/PrinciplesAndArchitecture-Runtime.md b/website/versioned_docs/version-v10.1.3/PrinciplesAndArchitecture-Runtime.md index 9491d290c146f..e9221631a701d 100644 --- a/website/versioned_docs/version-v10.1.3/PrinciplesAndArchitecture-Runtime.md +++ b/website/versioned_docs/version-v10.1.3/PrinciplesAndArchitecture-Runtime.md @@ -77,7 +77,6 @@ RecordSource { city: 'Seattle', } } - ``` [1] Note that GraphQL itself does not impose this constraint, and Relay Runtime may also be used for schemas that do not conform to it. For example, both systems can be used to query a single denormalized table. However, many of the features that Relay Runtime provides, such as caching and normalization, work best when the data is represented as a normalized graph with stable identities for discrete pieces of information. diff --git a/website/versioned_docs/version-v10.1.3/PrinciplesAndArchitecture-ThinkingInGraphQL.md b/website/versioned_docs/version-v10.1.3/PrinciplesAndArchitecture-ThinkingInGraphQL.md index a8842ae084922..9ff8a7840df90 100644 --- a/website/versioned_docs/version-v10.1.3/PrinciplesAndArchitecture-ThinkingInGraphQL.md +++ b/website/versioned_docs/version-v10.1.3/PrinciplesAndArchitecture-ThinkingInGraphQL.md @@ -12,7 +12,6 @@ In this article we'll explore what it means to build a GraphQL client framework Imagine we have a simple application that fetches a list of stories, and some details about each one. Here's how that might look in resource-oriented REST: ```javascript - // Fetch the list of story IDs but not their details: rest.get('/stories').then(stories => // This resolves to a list of items with linked resources: @@ -25,13 +24,11 @@ rest.get('/stories').then(stories => // `[ { id: "...", text: "..." } ]` console.log(stories); }); - ``` Note that this approach requires _n+1_ requests to the server: 1 to fetch the list, and _n_ to fetch each item. With GraphQL we can fetch the same data in a single network request to the server (without creating a custom endpoint that we'd then have to maintain): ```javascript - graphql.get(`query { stories { id, text } }`).then( stories => { // A list of story items: @@ -39,7 +36,6 @@ graphql.get(`query { stories { id, text } }`).then( console.log(stories); } ); - ``` So far we're just using GraphQL as a more efficient version of typical REST approaches. Note two important benefits in the GraphQL version: @@ -56,7 +52,6 @@ Repeatedly refetching information from the server can get quite slow. For exampl In a resource-oriented REST system, we can maintain a **response cache** based on URIs: ```javascript - var _cache = new Map(); rest.get = uri => { if (!_cache.has(uri)) { @@ -64,13 +59,11 @@ rest.get = uri => { } return _cache.get(uri); }; - ``` Response-caching can also be applied to GraphQL. A basic approach would work similarly to the REST version. The text of the query itself can be used as a cache key: ```javascript - var _cache = new Map(); graphql.get = queryText => { if (!_cache.has(queryText)) { @@ -78,7 +71,6 @@ graphql.get = queryText => { } return _cache.get(queryText); }; - ``` Now, requests for previously cached data can be answered immediately without making a network request. This is a practical approach to improving the perceived performance of an application. However, this method of caching can cause problems with data consistency. @@ -90,7 +82,6 @@ With GraphQL it is very common for the results of multiple queries to overlap. H ``` query { stories { id, text, likeCount } } - ``` and then later refetch one of the stories whose `likeCount` has since been incremented: @@ -98,7 +89,6 @@ and then later refetch one of the stories whose `likeCount` has since been incre ``` query { story(id: "123") { id, text, likeCount } } - ``` We'll now see different `likeCount`s depending on how the story is accessed. A view that uses the first query will see an outdated count, while a view using the second query will see the updated count. @@ -119,7 +109,6 @@ query { } } } - ``` And here's a possible response: @@ -134,13 +123,11 @@ query: { } } } - ``` Although the response is hierarchical, we'll cache it by flattening all the records. Here is an example of how Relay would cache this query response: ```javascript - Map { // `story(id: "1")` 1: Map { @@ -152,7 +139,6 @@ Map { name: 'Jan', }, }; - ``` This is only a simple example: in reality the cache must handle one-to-many associations and pagination (among other things). @@ -182,7 +168,6 @@ The first query was for a list of stories: ``` query { stories { id, text, likeCount } } - ``` With a normalized response cache, a record would be created for each story in the list. The `stories` field would store links to each of these records. @@ -192,7 +177,6 @@ The second query refetched the information for one of those stories: ``` query { story(id: "123") { id, text, likeCount } } - ``` When this response is normalized, Relay can detect that this result overlaps with existing data based on its `id`. Rather than create a new record, Relay will update the existing `123` record. The new `likeCount` is therefore available to _both_ queries, as well as any other query that might reference this story. @@ -215,7 +199,6 @@ query { } } } - ``` After initially fetching this story our cache might be as follows. Note that the story and comment both link to the same record as `author`: @@ -242,7 +225,6 @@ Map { author: Link(2), }, } - ``` The author of this story also commented on it — quite common. Now imagine that some other view fetches new information about the author, and her profile photo has changed to a new URI. Here's the _only_ part of our cached data that changes: @@ -256,7 +238,6 @@ Map { photo: 'http://.../photo2.jpg', }, } - ``` The value of the `photo` field has changed; and therefore the record `2` has also changed. And that's it. Nothing else in the _cache_ is affected. But clearly our _view_ needs to reflect the update: both instances of the author in the UI (as story author and comment author) need to show the new photo. @@ -273,7 +254,6 @@ ImmutableMap { }, 3: ImmutableMap // same as before } - ``` If we replace `2` with a new immutable record, we'll also get a new immutable instance of the cache object. However, records `1` and `3` are untouched. Because the data is normalized, we can't tell that `story`'s contents have changed just by looking at the `story` record alone. @@ -299,7 +279,6 @@ mutation StoryLike($storyID: String) { likeCount } } - ``` Notice that we're querying for data that _may_ have changed as a result of the mutation. An obvious question is: why can't the server just tell us what changed? The answer is: it's complicated. GraphQL abstracts over _any_ data storage layer (or an aggregation of multiple sources), and works with any programming language. Furthermore, the goal of GraphQL is to provide data in a form that is useful to product developers building a view. diff --git a/website/versioned_docs/version-v10.1.3/PrinciplesAndArchitecture-ThinkingInRelay.md b/website/versioned_docs/version-v10.1.3/PrinciplesAndArchitecture-ThinkingInRelay.md index e61f3fd21c933..62b1914ef3ff9 100644 --- a/website/versioned_docs/version-v10.1.3/PrinciplesAndArchitecture-ThinkingInRelay.md +++ b/website/versioned_docs/version-v10.1.3/PrinciplesAndArchitecture-ThinkingInRelay.md @@ -30,13 +30,11 @@ fragment Story_story on Story { photo } } - ``` And this fragment can then be used to define the Story container: ```javascript - const {createFragmentContainer, graphql} = require('react-relay'); // Plain React component. @@ -64,7 +62,6 @@ const StoryContainer = createFragmentContainer(Story, { In React, rendering a view requires two inputs: the _component_ to render, and a _root_ DOM (UI) node to render into. Rendering Relay containers is similar: we need a _container_ to render, and a _root_ in the graph from which to start our query. We also must ensure that the queries for the container are executed and may want to show a loading indicator while data is being fetched. Similar to `ReactDOM.render(component, domNode)`, Relay provides `` for this purpose. The `query` and `variables` define what data to fetch and `render` defines what to render. Here's how we might render ``: ```javascript - ReactDOM.render( Process {item.title} ); } - ``` ## `@relay(mask: Boolean)` @@ -138,14 +128,12 @@ Keep in mind that it is typically considered an **anti-pattern** to create a sin In the example below, the `user` prop will include the data for `id` and `name` fields wherever `...Component_internUser` is included, instead of Relay's normal behavior to mask those fields: ```javascript - graphql` fragment Component_internUser on InternUser @relay(mask: false) { id name } `; - ``` diff --git a/website/versioned_docs/version-v11.0.0/api-reference/relay-runtime/store.md b/website/versioned_docs/version-v11.0.0/api-reference/relay-runtime/store.md index fe2b0debb4eeb..8b41d5528b0c2 100644 --- a/website/versioned_docs/version-v11.0.0/api-reference/relay-runtime/store.md +++ b/website/versioned_docs/version-v11.0.0/api-reference/relay-runtime/store.md @@ -20,7 +20,6 @@ Table of Contents: The `RecordSourceSelectorProxy` is the type of the `store` that [`updater` functions](../../guided-tour/updating-data/graphql-mutations/) receive as an argument. The following is the `RecordSourceSelectorProxy` interface: ```javascript - interface RecordSourceSelectorProxy { create(dataID: string, typeName: string): RecordProxy; delete(dataID: string): void; @@ -30,7 +29,6 @@ interface RecordSourceSelectorProxy { getPluralRootField(fieldName: string): ?Array; invalidateStore(): void; } - ``` ### `create(dataID: string, typeName: string): RecordProxy` @@ -40,9 +38,7 @@ Creates a new record in the store given a `dataID` and the `typeName` as defined #### Example ```javascript - const record = store.create(dataID, 'Todo'); - ``` ### `delete(dataID: string): void` @@ -52,9 +48,7 @@ Deletes a record from the store given its `dataID`. #### Example ```javascript - store.delete(dataID); - ``` ### `get(dataID: string): ?RecordProxy` @@ -64,9 +58,7 @@ Retrieves a record from the store given its `dataID`. Returns a [`RecordProxy`]( #### Example ```javascript - const record = store.get(dataID); - ``` ### `getRoot(): RecordProxy` @@ -78,20 +70,16 @@ Returns the [`RecordProxy`](#recordproxy) representing the root of the GraphQL d Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - // Represents root query const root = store.getRoot(); - ``` ### `getRootField(fieldName: string): ?RecordProxy` @@ -103,19 +91,15 @@ Retrieves a root field from the store given the `fieldName`, as defined by the G Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - const viewer = store.getRootField('viewer'); - ``` ### `getPluralRootField(fieldName: string): ?Array` @@ -127,19 +111,15 @@ Retrieves a root field that represents a collection from the store given the `fi Given the GraphQL document: ```graphql - nodes(first: 10) { # ... } - ``` Usage: ```javascript - const nodes = store.getPluralRootField('nodes'); - ``` ### `invalidateStore(): void` @@ -149,15 +129,12 @@ Globally invalidates the Relay store. This will cause any data that was written #### Example ```javascript - store.invalidateStore(); - ``` After global invalidation, any query that is checked before refetching it will be considered stale: ```javascript - environment.check(query) === 'stale' ``` @@ -167,7 +144,6 @@ environment.check(query) === 'stale' The `RecordProxy` serves as an interface to mutate records: ```javascript - interface RecordProxy { copyFieldsFrom(sourceRecord: RecordProxy): void; getDataID(): string; @@ -193,7 +169,6 @@ interface RecordProxy { setValue(value: mixed, name: string, arguments?: ?Object): RecordProxy; invalidateRecord(): void; } - ``` ### `getDataID(): string` @@ -203,9 +178,7 @@ Returns the `dataID` of the current record. #### Example ```javascript - const id = record.getDataID(); - ``` ### `getType(): string` @@ -215,7 +188,6 @@ Gets the type of the current record, as defined by the GraphQL schema. #### Example ```javascript - const type = user.getType(); // User ``` @@ -229,20 +201,16 @@ Gets the value of a field in the current record given the field name. Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - const name = viewer.getValue('name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. @@ -252,20 +220,16 @@ Optionally, if the field takes arguments, you can pass a bag of `variables`. Given the GraphQL document: ```graphql - viewer { id name(arg: $arg) } - ``` Usage: ```javascript - const name = viewer.getValue('name', {arg: 'value'}); - ``` ### `getLinkedRecord(name: string, arguments?: ?Object): ?RecordProxy` @@ -277,23 +241,19 @@ Retrieves a record associated with the current record given the field name, as d Given the GraphQL document: ```graphql - rootField { viewer { id name } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -303,22 +263,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { viewer(arg: $arg) { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {arg: 'value'}); - ``` ### `getLinkedRecords(name: string, arguments?: ?Object): ?Array` @@ -330,22 +286,18 @@ Retrieves the set of records associated with the current record given the field Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const nodes = rootField.getLinkedRecords('nodes'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -355,22 +307,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { nodes(first: $count) { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const nodes = rootField.getLinkedRecords('nodes', {count: 10}); - ``` ### `getOrCreateLinkedRecord(name: string, typeName: string, arguments?: ?Object)` @@ -382,19 +330,16 @@ Retrieves a record associated with the current record given the field name, as d Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = rootField.getOrCreateLinkedRecord('viewer', 'User'); // Will create if it doesn't exist @@ -409,28 +354,22 @@ Mutates the current record by setting a new value on the specified field. Return Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - viewer.setValue('New Name', 'name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. ```javascript - viewer.setValue('New Name', 'name', {arg: 'value'}); - ``` ### `copyFieldsFrom(sourceRecord: RecordProxy): void` @@ -440,7 +379,6 @@ Mutates the current record by copying the fields over from the passed in record #### Example ```javascript - const record = store.get(id1); const otherRecord = store.get(id2); record.copyFieldsFrom(otherRecord); // Mutates `record` @@ -456,23 +394,19 @@ Mutates the current record by setting a new linked record on the given field nam Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = store.create(/* ... */); rootField.setLinkedRecord(newViewer, 'viewer'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -486,24 +420,20 @@ Mutates the current record by setting a new set of linked records on the given f Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newNode = store.create(/* ... */); const newNodes = [...rootField.getLinkedRecords('nodes'), newNode]; rootField.setLinkedRecords(newNodes, 'nodes'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -515,16 +445,13 @@ Invalidates the record. This will cause any query that references this record to #### Example ```javascript - const record = store.get('4'); record.invalidateRecord(); - ``` After invalidating a record, any query that references the invalidated record and that is checked before refetching it will be considered stale: ```javascript - environment.check(query) === 'stale' ``` @@ -534,7 +461,6 @@ environment.check(query) === 'stale' `ConnectionHandler` is a utility module exposed by `relay-runtime` that aids in the manipulation of connections. `ConnectionHandler` exposes the following interface: ```javascript - interface ConnectionHandler { getConnection( record: RecordProxy, @@ -559,7 +485,6 @@ interface ConnectionHandler { ): void, deleteNode(connection: RecordProxy, nodeID: string): void } - ``` ### `getConnection(record: RecordProxy, key: string, filters?: ?Object)` @@ -569,7 +494,6 @@ Given a record and a connection key, and optionally a set of filters, `getConnec First, let's take a look at a plain connection: ```graphql - fragment FriendsFragment on User { friends(first: 10) { edges { @@ -579,26 +503,22 @@ fragment FriendsFragment on User { } } } - ``` Accessing a plain connection field like this is the same as other regular fields: ```javascript - // The `friends` connection record can be accessed with: const user = store.get(userID); const friends = user && user.getLinkedRecord('friends'); // Access fields on the connection: const edges = friends && friends.getLinkedRecords('edges'); - ``` When using [usePaginationFragment](../use-pagination-fragment/), we usually annotate the actual connection field with `@connection` to tell Relay which part needs to be paginated: ```graphql - fragment FriendsFragment on User { friends(first: 10, orderby: "firstname") @connection( key: "FriendsFragment_friends", @@ -610,13 +530,11 @@ fragment FriendsFragment on User { } } } - ``` For connections like the above, `ConnectionHandler` helps us find the record: ```javascript - import {ConnectionHandler} from 'relay-runtime'; // The `friends` connection record can be accessed with: @@ -628,7 +546,6 @@ const friends = ConnectionHandler.getConnection( ); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` ### Edge creation and insertion @@ -648,7 +565,6 @@ Given a connection, inserts the edge at the end of the connection, or after the #### Example ```javascript - const user = store.get(userID); const friends = ConnectionHandler.getConnection(user, 'FriendsFragment_friends'); const newFriend = store.get(newFriendId); @@ -659,7 +575,6 @@ ConnectionHandler.insertEdgeAfter(friends, edge); // No cursor provided, insert the edge at the front: ConnectionHandler.insertEdgeBefore(friends, edge); - ``` ### `deleteNode(connection: RecordProxy, nodeID: string): void` @@ -669,11 +584,9 @@ Given a connection, deletes any edges whose node id matches the given id. #### Example ```javascript - const user = store.get(userID); const friends = ConnectionHandler.getConnection(user, 'FriendsFragment_friends'); ConnectionHandler.deleteNode(friends, idToDelete); - ``` diff --git a/website/versioned_docs/version-v11.0.0/getting-started/installation-and-setup.md b/website/versioned_docs/version-v11.0.0/getting-started/installation-and-setup.md index 71541301487d7..fe39c53ac6709 100644 --- a/website/versioned_docs/version-v11.0.0/getting-started/installation-and-setup.md +++ b/website/versioned_docs/version-v11.0.0/getting-started/installation-and-setup.md @@ -136,15 +136,13 @@ polyfill in your bundled application, such as [core-js][] or A polyfilled environment for Relay using [core-js][] to support older browsers might look like: -```js - +```javascript require('core-js/es6/map'); require('core-js/es6/set'); require('core-js/es6/promise'); require('core-js/es6/object'); require('./myRelayApplication'); - ``` [core-js]: https://github.com/zloirock/core-js diff --git a/website/versioned_docs/version-v11.0.0/glossary/glossary.md b/website/versioned_docs/version-v11.0.0/glossary/glossary.md index 112e95e7b8078..78bb02852cb96 100644 --- a/website/versioned_docs/version-v11.0.0/glossary/glossary.md +++ b/website/versioned_docs/version-v11.0.0/glossary/glossary.md @@ -75,8 +75,7 @@ The concept of availability refers to whether there is enough non-stale, non-inv A build-time transformation of the Javascript codebase, which turns calls to -```js - +```javascript graphql`...` ``` @@ -377,8 +376,7 @@ Compare to [value](#value). A GraphQL literal is a call to -```js - +```javascript graphql`...` ``` diff --git a/website/versioned_docs/version-v11.0.0/guided-tour/list-data/advanced-pagination.md b/website/versioned_docs/version-v11.0.0/guided-tour/list-data/advanced-pagination.md index 6139647272338..0fe4215fe4afa 100644 --- a/website/versioned_docs/version-v11.0.0/guided-tour/list-data/advanced-pagination.md +++ b/website/versioned_docs/version-v11.0.0/guided-tour/list-data/advanced-pagination.md @@ -146,7 +146,6 @@ function FriendsListComponent(props: Props) { ); } - ``` * The APIs for both *"forward"* and *"backward"* are exactly the same, they're only named differently. When paginating forward, then the `after` and `first` connection arguments will be used, when paginating backward, the `before` and `last` connection arguments will be used. diff --git a/website/versioned_docs/version-v11.0.0/guided-tour/rendering/fragments.md b/website/versioned_docs/version-v11.0.0/guided-tour/rendering/fragments.md index 1efffbb4bdecd..93caabfec4a1f 100644 --- a/website/versioned_docs/version-v11.0.0/guided-tour/rendering/fragments.md +++ b/website/versioned_docs/version-v11.0.0/guided-tour/rendering/fragments.md @@ -334,7 +334,6 @@ function App({appQueryRef}) { ); } - ``` Note that: diff --git a/website/versioned_docs/version-v11.0.0/guided-tour/reusing-cached-data/rendering-partially-cached-data.md b/website/versioned_docs/version-v11.0.0/guided-tour/reusing-cached-data/rendering-partially-cached-data.md index 1c52de1412b71..d40718ad28042 100644 --- a/website/versioned_docs/version-v11.0.0/guided-tour/reusing-cached-data/rendering-partially-cached-data.md +++ b/website/versioned_docs/version-v11.0.0/guided-tour/reusing-cached-data/rendering-partially-cached-data.md @@ -54,8 +54,7 @@ module.exports = UsernameComponent; And we have the following query component, which queries for some data, and also includes the fragment above: -```js - +```javascript /** * AppTabs.react.js * @@ -158,7 +157,6 @@ function HomeTab() { ); } - ``` diff --git a/website/versioned_docs/version-v11.0.0/guided-tour/updating-data/client-only-data.md b/website/versioned_docs/version-v11.0.0/guided-tour/updating-data/client-only-data.md index fe69e6fd99d4c..621edf0c3b6ad 100644 --- a/website/versioned_docs/version-v11.0.0/guided-tour/updating-data/client-only-data.md +++ b/website/versioned_docs/version-v11.0.0/guided-tour/updating-data/client-only-data.md @@ -31,7 +31,6 @@ In order to extend an existing type, add a `.graphql` file to your appropriate s ```graphql - extend type Comment { is_new_comment: Boolean } @@ -55,7 +54,6 @@ You can define types using the same regular GraphQL syntax, by defining it insid ```graphql - # You can define more than one type in a single file enum FetchStatus { FETCHED @@ -76,7 +74,6 @@ extend type Item { # You can extend server types with client-only types fetch_state: FetchState } - ``` * In this contrived example, we're defining 2 new client-only types, and `enum` and a regular `type`. Note that they can reference themselves as normal, and reference regular server defined types. Also note that we can extend server types and add fields that are of our client-only types. diff --git a/website/versioned_docs/version-v11.0.0/guides/client-schema-extensions.md b/website/versioned_docs/version-v11.0.0/guides/client-schema-extensions.md index 5e36136445e49..d3876e7940a6f 100644 --- a/website/versioned_docs/version-v11.0.0/guides/client-schema-extensions.md +++ b/website/versioned_docs/version-v11.0.0/guides/client-schema-extensions.md @@ -32,23 +32,19 @@ It can even be used to extend an existing server schema. For example, we can create a new type called `Note`: ```graphql - type Note { id: ID! title: String body: String } - ``` And then extend the server schema type `User`, with a list of `Note`, called `notes`. ```graphql - extend type User { notes: [Note] } - ``` ## Querying local state @@ -59,7 +55,6 @@ The field can be from the server schema, or it can be schema agnostic, like an i 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. ```javascript - // Example.js import * as React from 'react'; import { useLazyLoadQuery, graphql } from 'react-relay'; @@ -80,7 +75,6 @@ const Example = (props) => { `, {}); // ... } - ``` ## Mutating local state @@ -96,7 +90,6 @@ To build upon the previous example, let's try creating, updating and deleting a ### Create ```javascript - import {commitLocalUpdate} from 'react-relay'; let tempID = 0; @@ -116,7 +109,6 @@ function createUserNote(environment) { user.setLinkedRecords([...userNoteRecords, newNoteRecord], 'notes'); }); } - ``` 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. @@ -124,7 +116,6 @@ Note that since this record will be rendered by the `ExampleQuery` via `useLazyL If no component is rendering the local data and you want to manually retain it, you can do so by calling `environment.retain()`: ```javascript - import {createOperationDescriptor, getRequest} from 'relay-runtime'; // Create a query that references that record @@ -151,13 +142,11 @@ const disposable = environment.retain(operation); // Whenever you don't need that data anymore and it's okay for Relay to garbage collect it, // you can dispose of the retain disposable.dispose(); - ``` ### Update ```javascript - import {commitLocalUpdate} from 'react-relay'; function updateUserNote(environment, dataID, body, title) { @@ -168,13 +157,11 @@ function updateUserNote(environment, dataID, body, title) { note.setValue(title, 'title') }); } - ``` ### Delete ```javascript - import {commitLocalUpdate} from 'react-relay'; function deleteUserNote(environment, dataID) { @@ -192,7 +179,6 @@ function deleteUserNote(environment, dataID) { user.setLinkedRecords(newUserNoteRecords, 'notes'); }); } - ``` ## Initial local state @@ -201,7 +187,6 @@ All new client-side schema fields default to `undefined` value. Often however, y You can use an updater function via `commitLocalUpdate` to prime local state. ```javascript - import {commitLocalUpdate} from 'react-relay'; commitLocalUpdate(environment, store => { @@ -210,7 +195,6 @@ commitLocalUpdate(environment, store => { // initialize user notes to an empty array. user.setLinkedRecords([], 'notes'); }); - ``` diff --git a/website/versioned_docs/version-v11.0.0/guides/compiler.md b/website/versioned_docs/version-v11.0.0/guides/compiler.md index 18be59cbf31a2..e70b78a85702f 100644 --- a/website/versioned_docs/version-v11.0.0/guides/compiler.md +++ b/website/versioned_docs/version-v11.0.0/guides/compiler.md @@ -15,7 +15,6 @@ import FbImportingGeneratedDefinitions from './fb/FbImportingGeneratedDefinition The `graphql` template tag provided by Relay serves as the mechanism to write queries, fragments, mutations and subscriptions in the [GraphQL](http://graphql.org/learn/) language. For example: ```javascript - import {graphql} from 'react-relay'; graphql` @@ -25,7 +24,6 @@ graphql` } } `; - ``` The result of using the `graphql` template tag is a `GraphQLTaggedNode`; a runtime representation of the GraphQL document. @@ -40,7 +38,6 @@ Relay uses the Relay Compiler to convert [`graphql`](#graphql) literals into gen A fragment like the following: ```javascript - graphql` fragment MyComponent on Type { field @@ -66,7 +63,6 @@ The Relay Compiler is responsible for generating code as part of a build step wh To use the Relay Compiler, you need either a `.graphql` or `.json` [GraphQL Schema](https://graphql.org/learn/schema/) file, describing your GraphQL server's API. Typically these files are local representations of a server source of truth and are not edited directly. For example, we might have a `schema.graphql` like: ```graphql - schema { query: Root } @@ -84,7 +80,6 @@ type WordDefinition { text: String image: String } - ``` @@ -108,7 +103,6 @@ For example, given the two files: - `src/Components/DictionaryComponent.js` ```javascript - const DictionaryWordFragment = graphql` fragment DictionaryComponent_word on Word { id @@ -130,7 +124,6 @@ const DictionaryDefinitionFragment = graphql` - `src/Queries/DictionaryQuery.js` ```javascript - const DictionaryQuery = graphql` query DictionaryQuery { dictionary { @@ -164,9 +157,7 @@ Typically you will not need to import your generated definitions. The [Relay Bab However the Relay Compiler also automatically generates [Flow](https://flow.org) types as [type comments](https://flow.org/en/docs/types/comments/). For example, you can import the generated Flow types like so: ```javascript - import type {DictionaryComponent_word} from './__generated__/DictionaryComponent_word.graphql'; - ``` More rarely, you may need to access a query, mutation, fragment or subscription from multiple files. In these cases, you can also import it directly: diff --git a/website/versioned_docs/version-v11.0.0/guides/graphql-server-specification.md b/website/versioned_docs/version-v11.0.0/guides/graphql-server-specification.md index ac2aa97df265e..78526d2cf2b5f 100644 --- a/website/versioned_docs/version-v11.0.0/guides/graphql-server-specification.md +++ b/website/versioned_docs/version-v11.0.0/guides/graphql-server-specification.md @@ -92,7 +92,6 @@ query RebelsQuery { name } } - ``` returns @@ -105,7 +104,6 @@ returns "name": "Alliance to Restore the Republic" } } - ``` So now we know the ID of the Rebels in our system. We can now refetch them: @@ -120,7 +118,6 @@ query RebelsRefetchQuery { } } } - ``` returns @@ -133,7 +130,6 @@ returns "name": "Alliance to Restore the Republic" } } - ``` If we do the same thing with the Empire, we'll find that it returns a different ID, and we can refetch it as well: @@ -146,7 +142,6 @@ query EmpireQuery { name } } - ``` yields @@ -159,7 +154,6 @@ yields "name": "Galactic Empire" } } - ``` and @@ -174,7 +168,6 @@ query EmpireRefetchQuery { } } } - ``` yields @@ -187,7 +180,6 @@ yields "name": "Galactic Empire" } } - ``` The `Node` interface and `node` field assume globally unique IDs for this refetching. A system without globally unique IDs can usually synthesize them by combining the type with the type-specific ID, which is what was done in this example. @@ -216,7 +208,6 @@ query RebelsShipsQuery { } } } - ``` yields @@ -237,7 +228,6 @@ yields } } } - ``` That used the `first` argument to `ships` to slice the result set down to the first one. But what if we wanted to paginate through it? On each edge, a cursor will be exposed that we can use to paginate. Let's ask for the first two this time, and get the cursor as well: @@ -257,7 +247,6 @@ query MoreRebelShipsQuery { } } } - ``` and we get back @@ -285,7 +274,6 @@ and we get back } } } - ``` Notice that the cursor is a base64 string. That's the pattern from earlier: the server is reminding us that this is an opaque string. We can pass this string back to the server as the `after` argument to the `ships` field, which will let us ask for the next three ships after the last one in the previous result: @@ -305,7 +293,6 @@ query EndOfRebelShipsQuery { } } } - ``` gives us @@ -340,7 +327,6 @@ gives us } } } - ``` Sweet! Let's keep going and get the next four! @@ -360,7 +346,6 @@ query RebelsQuery { } } } - ``` yields @@ -375,7 +360,6 @@ yields } } } - ``` Hm. There were no more ships; guess there were only five in the system for the rebels. It would have been nice to know that we'd reached the end of the connection, without having to do another round trip in order to verify that. The connection model exposes this capability with a type called `PageInfo`. So let's issue the two queries that got us ships again, but this time ask for `hasNextPage`: @@ -407,7 +391,6 @@ query EndOfRebelShipsQuery { } } } - ``` and we get back @@ -458,7 +441,6 @@ and we get back } } } - ``` So on the first query for ships, GraphQL told us there was a next page, but on the next one, it told us we'd reached the end of the connection. diff --git a/website/versioned_docs/version-v11.0.0/guides/network-layer.md b/website/versioned_docs/version-v11.0.0/guides/network-layer.md index 78c2580f50293..f724caaa3c06c 100644 --- a/website/versioned_docs/version-v11.0.0/guides/network-layer.md +++ b/website/versioned_docs/version-v11.0.0/guides/network-layer.md @@ -18,7 +18,6 @@ In order to know how to access your GraphQL server, Relay requires developers to Currently the easiest way to create a network layer is via a helper from the `relay-runtime` package: ```javascript - import { Environment, Network, @@ -60,7 +59,6 @@ const environment = new Environment({ }); export default environment; - ``` Note that this is a basic example to help you get started. This example could be extended with additional features such as request/response caching (enabled e.g. when `cacheConfig.force` is false) and uploading form data for mutations (the `uploadables` parameter). diff --git a/website/versioned_docs/version-v11.0.0/guides/persisted-queries.md b/website/versioned_docs/version-v11.0.0/guides/persisted-queries.md index ddda97ac39339..e37ced4923b22 100644 --- a/website/versioned_docs/version-v11.0.0/guides/persisted-queries.md +++ b/website/versioned_docs/version-v11.0.0/guides/persisted-queries.md @@ -29,12 +29,10 @@ The relay compiler supports persisted queries. This is useful because: In your `npm` script in `package.json`, run the relay compiler using the `--persist-output` flag: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` The `--persist-ouput` flag does 2 things: @@ -43,8 +41,7 @@ The `--persist-ouput` flag does 2 things: For example without `--persist-output`, a generated `ConcreteRequest` might look like below: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -61,8 +58,7 @@ The `--persist-ouput` flag does 2 things: With `--persist-output ` this becomes: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -80,12 +76,10 @@ The `--persist-ouput` flag does 2 things: 2. It generates a JSON file at the `` you specify containing a mapping from query ids to the corresponding operation texts. -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./src/queryMaps/queryMap.json" } - ``` The example above writes the complete query map file to `./src/queryMaps/queryMap.json`. You need to ensure all the directories @@ -97,8 +91,7 @@ leading to the `queryMap.json` file exist. You'll need to modify your network layer fetch implementation to pass a doc_id parameter in the POST body instead of a query parameter: -```js - +```javascript function fetchQuery(operation, variables,) { return fetch('/graphql', { method: 'POST', @@ -114,7 +107,6 @@ function fetchQuery(operation, variables,) { return response.json(); }); } - ``` @@ -139,13 +131,11 @@ the query map file in a common location accessible to both the client and the se For applications where the client and server projects are separate, one option is to have an additional npm run script to push the query map at compile time to a location accessible by your server: -```js - +```javascript "scripts": { "push-queries": "node ./pushQueries.js", "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-ouput && npm run push-queries" } - ``` Some possibilities of what you can do in `./pushQueries.js`: @@ -169,8 +159,7 @@ database technologies you use, so we'll just cover the most common and basic exa If you use `express-graphql` and have access to the query map file, you can import the `--persist-output` JSON file directly and perform the matching using the `matchQueryMiddleware` from [relay-compiler-plus](https://github.com/yusinto/relay-compiler-plus). -```js - +```javascript import Express from 'express'; import expressGraphql from 'express-graphql'; import {matchQueryMiddleware} from 'relay-compiler-plus'; @@ -181,7 +170,6 @@ const app = Express(); app.use('/graphql', matchQueryMiddleware(queryMapJson), expressGraphql({schema})); - ``` ## Using `--persist-output` and `--watch` diff --git a/website/versioned_docs/version-v11.0.0/guides/testing-relay-components.md b/website/versioned_docs/version-v11.0.0/guides/testing-relay-components.md index 3604a0cdfc11f..c4475ac4b8534 100644 --- a/website/versioned_docs/version-v11.0.0/guides/testing-relay-components.md +++ b/website/versioned_docs/version-v11.0.0/guides/testing-relay-components.md @@ -153,8 +153,7 @@ Most of GraphQL type information for a specific field in the selection is not av Operation with the @relay_test_operation directive will have additional metadata that will contain GraphQL type info for fields in the operation's selection. And it will improve the quality of the generated data. You also will be able to define Mock resolvers for Scalar (not only ID and String) and Abstract types: -```js - +```javascript { Float() { return 123.456; @@ -181,8 +180,7 @@ Operation with the @relay_test_operation directive will have additional metadata Using `createMockEnvironment` and `MockPayloadGenerator` allows writing concise tests for components that are using Relay hooks. Both those modules can be imported from `relay-test-utils` -```js - +```javascript // Say you have a component with the useLazyLoadQuery or a QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { @@ -251,8 +249,7 @@ test('Error State', () => { Essentially, in the example above will `resolveMostRecentOperation` will generate data for all child fragment containers (pagination, refetch). But, usually the root component may have many child fragment components and you may want to exercise a specific component that uses `useFragment`. The solution for that would be to wrap your fragment container with the `useLazyLoadQuery` component that renders a Query that's spreads fragments from your fragment component: -```js - +```javascript test('Fragment', () => { const environment = createMockEnvironment(); const TestRenderer = () => { @@ -369,7 +366,6 @@ test('`Pagination` Container', () => { expect(loadMore.props.disabled).toBe(true); }); - ``` ### Refetch Component @@ -505,8 +501,7 @@ test('it should subscribe', () => { With `queueOperationResolver` it possible to define responses for operations that will be executed on the environment -```js - +```javascript // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { diff --git a/website/versioned_docs/version-v11.0.0/guides/testing-relay-with-preloaded-queries.md b/website/versioned_docs/version-v11.0.0/guides/testing-relay-with-preloaded-queries.md index 89e226048a609..1cd7819ab7fde 100644 --- a/website/versioned_docs/version-v11.0.0/guides/testing-relay-with-preloaded-queries.md +++ b/website/versioned_docs/version-v11.0.0/guides/testing-relay-with-preloaded-queries.md @@ -23,8 +23,7 @@ In short, there are two steps that need to be performed **before rendering the c ## TL;DR -```js - +```javascript const {RelayEnvironmentProvider} = require('react-relay'); const { MockPayloadGenerator, createMockEnvironment } = require('relay-test-utils'); const {render} = require('testing-library-react'); @@ -60,7 +59,6 @@ test("...", () => { // assert // your assertions go here }); - ``` ### Configure the query resolver to generate the response @@ -98,14 +96,12 @@ The type you need seems to be the type returned by the *innermost function call* It is **possible** to return different data for different query variables via [Mock Resolver Context](../testing-relay-components/#mock-resolver-context). The query variables will be available on the `context.args`, but only to the *innermost function call* (for the query above, only `offer_ids` are available) -```js - +```javascript CurrencyAmount(context) { console.log(JSON.stringify(context, null, 2)); // <-- return { formatted_amount: mockResponse } } // <-- logs { ...snip..., "name": "subtotal_price_for_offers", args: { offer_ids: [...] } } - ``` ### Record a pending queue invocation diff --git a/website/versioned_docs/version-v11.0.0/guides/type-emission.md b/website/versioned_docs/version-v11.0.0/guides/type-emission.md index 37ccdc8e5c01c..c2efa4b34f8fc 100644 --- a/website/versioned_docs/version-v11.0.0/guides/type-emission.md +++ b/website/versioned_docs/version-v11.0.0/guides/type-emission.md @@ -410,7 +410,6 @@ $ relay-compiler --artifactDirectory ./src/__generated__ […] ["relay", { "artifactDirectory": "./src/__generated__" }] ] } - ``` It is recommended to alias this directory in your module resolution configuration such that you don’t need to specify relative paths in your source files. This is what is also done in the above examples, where artifacts are imported from a `__generated__` alias, rather than relative paths like `../../../../__generated__`. diff --git a/website/versioned_docs/version-v11.0.0/principles-and-architecture/compiler-architecture.md b/website/versioned_docs/version-v11.0.0/principles-and-architecture/compiler-architecture.md index ae7664a37eb52..6c165119dd2b1 100644 --- a/website/versioned_docs/version-v11.0.0/principles-and-architecture/compiler-architecture.md +++ b/website/versioned_docs/version-v11.0.0/principles-and-architecture/compiler-architecture.md @@ -77,7 +77,6 @@ foo { # type FooType foo { id } - ``` - `SkipRedundantNodeTransform`: A more advanced version of flattening, this eliminates more complex cases of field duplication such as when a field is fetched both unconditionally and conditionally, or is fetched by two different sub-fragments. For example: @@ -100,7 +99,6 @@ foo { id } } - ``` diff --git a/website/versioned_docs/version-v11.0.0/principles-and-architecture/runtime-architecture.md b/website/versioned_docs/version-v11.0.0/principles-and-architecture/runtime-architecture.md index 8c73ba0b5587a..eee42db30d462 100644 --- a/website/versioned_docs/version-v11.0.0/principles-and-architecture/runtime-architecture.md +++ b/website/versioned_docs/version-v11.0.0/principles-and-architecture/runtime-architecture.md @@ -74,7 +74,6 @@ RecordSource { city: 'Seattle', } } - ``` [1] Note that GraphQL itself does not impose this constraint, and Relay Runtime may also be used for schemas that do not conform to it. For example, both systems can be used to query a single denormalized table. However, many of the features that Relay Runtime provides, such as caching and normalization, work best when the data is represented as a normalized graph with stable identities for discrete pieces of information. diff --git a/website/versioned_docs/version-v11.0.0/principles-and-architecture/thinking-in-graphql.md b/website/versioned_docs/version-v11.0.0/principles-and-architecture/thinking-in-graphql.md index 301a0eb5d151f..a50356ab37a84 100644 --- a/website/versioned_docs/version-v11.0.0/principles-and-architecture/thinking-in-graphql.md +++ b/website/versioned_docs/version-v11.0.0/principles-and-architecture/thinking-in-graphql.md @@ -15,7 +15,6 @@ In this article we'll explore what it means to build a GraphQL client framework Imagine we have a simple application that fetches a list of stories, and some details about each one. Here's how that might look in resource-oriented REST: ```javascript - // Fetch the list of story IDs but not their details: rest.get('/stories').then(stories => // This resolves to a list of items with linked resources: @@ -28,13 +27,11 @@ rest.get('/stories').then(stories => // `[ { id: "...", text: "..." } ]` console.log(stories); }); - ``` Note that this approach requires _n+1_ requests to the server: 1 to fetch the list, and _n_ to fetch each item. With GraphQL we can fetch the same data in a single network request to the server (without creating a custom endpoint that we'd then have to maintain): ```javascript - graphql.get(`query { stories { id, text } }`).then( stories => { // A list of story items: @@ -42,7 +39,6 @@ graphql.get(`query { stories { id, text } }`).then( console.log(stories); } ); - ``` So far we're just using GraphQL as a more efficient version of typical REST approaches. Note two important benefits in the GraphQL version: @@ -59,7 +55,6 @@ Repeatedly refetching information from the server can get quite slow. For exampl In a resource-oriented REST system, we can maintain a **response cache** based on URIs: ```javascript - var _cache = new Map(); rest.get = uri => { if (!_cache.has(uri)) { @@ -67,13 +62,11 @@ rest.get = uri => { } return _cache.get(uri); }; - ``` Response-caching can also be applied to GraphQL. A basic approach would work similarly to the REST version. The text of the query itself can be used as a cache key: ```javascript - var _cache = new Map(); graphql.get = queryText => { if (!_cache.has(queryText)) { @@ -81,7 +74,6 @@ graphql.get = queryText => { } return _cache.get(queryText); }; - ``` Now, requests for previously cached data can be answered immediately without making a network request. This is a practical approach to improving the perceived performance of an application. However, this method of caching can cause problems with data consistency. @@ -93,7 +85,6 @@ With GraphQL it is very common for the results of multiple queries to overlap. H ``` query { stories { id, text, likeCount } } - ``` and then later refetch one of the stories whose `likeCount` has since been incremented: @@ -101,7 +92,6 @@ and then later refetch one of the stories whose `likeCount` has since been incre ``` query { story(id: "123") { id, text, likeCount } } - ``` We'll now see different `likeCount`s depending on how the story is accessed. A view that uses the first query will see an outdated count, while a view using the second query will see the updated count. @@ -122,7 +112,6 @@ query { } } } - ``` And here's a possible response: @@ -137,13 +126,11 @@ query: { } } } - ``` Although the response is hierarchical, we'll cache it by flattening all the records. Here is an example of how Relay would cache this query response: ```javascript - Map { // `story(id: "1")` 1: Map { @@ -155,7 +142,6 @@ Map { name: 'Jan', }, }; - ``` This is only a simple example: in reality the cache must handle one-to-many associations and pagination (among other things). @@ -185,7 +171,6 @@ The first query was for a list of stories: ``` query { stories { id, text, likeCount } } - ``` With a normalized response cache, a record would be created for each story in the list. The `stories` field would store links to each of these records. @@ -195,7 +180,6 @@ The second query refetched the information for one of those stories: ``` query { story(id: "123") { id, text, likeCount } } - ``` When this response is normalized, Relay can detect that this result overlaps with existing data based on its `id`. Rather than create a new record, Relay will update the existing `123` record. The new `likeCount` is therefore available to _both_ queries, as well as any other query that might reference this story. @@ -218,7 +202,6 @@ query { } } } - ``` After initially fetching this story our cache might be as follows. Note that the story and comment both link to the same record as `author`: @@ -245,7 +228,6 @@ Map { author: Link(2), }, } - ``` The author of this story also commented on it — quite common. Now imagine that some other view fetches new information about the author, and her profile photo has changed to a new URI. Here's the _only_ part of our cached data that changes: @@ -259,7 +241,6 @@ Map { photo: 'http://.../photo2.jpg', }, } - ``` The value of the `photo` field has changed; and therefore the record `2` has also changed. And that's it. Nothing else in the _cache_ is affected. But clearly our _view_ needs to reflect the update: both instances of the author in the UI (as story author and comment author) need to show the new photo. @@ -276,7 +257,6 @@ ImmutableMap { }, 3: ImmutableMap // same as before } - ``` If we replace `2` with a new immutable record, we'll also get a new immutable instance of the cache object. However, records `1` and `3` are untouched. Because the data is normalized, we can't tell that `story`'s contents have changed just by looking at the `story` record alone. @@ -302,7 +282,6 @@ mutation StoryLike($storyID: String) { likeCount } } - ``` Notice that we're querying for data that _may_ have changed as a result of the mutation. An obvious question is: why can't the server just tell us what changed? The answer is: it's complicated. GraphQL abstracts over _any_ data storage layer (or an aggregation of multiple sources), and works with any programming language. Furthermore, the goal of GraphQL is to provide data in a form that is useful to product developers building a view. diff --git a/website/versioned_docs/version-v11.0.0/principles-and-architecture/thinking-in-relay.md b/website/versioned_docs/version-v11.0.0/principles-and-architecture/thinking-in-relay.md index b445997247eed..b4f521b15cf1c 100644 --- a/website/versioned_docs/version-v11.0.0/principles-and-architecture/thinking-in-relay.md +++ b/website/versioned_docs/version-v11.0.0/principles-and-architecture/thinking-in-relay.md @@ -28,8 +28,7 @@ Let's dive deeper to understand how Relay achieves this feat. With Relay, the data requirements for a component are specified with fragments. Fragments are named snippets of GraphQL that specify which fields to select from an object of a particular type. Fragments are written within GraphQL literals. For example, the following declares a GraphQL literal containing a fragment which selects an author's name and photo url: -```js - +```javascript // AuthorDetails.react.js const authorDetailsFragment = graphql` fragment AuthorDetails_author on Author { @@ -39,19 +38,16 @@ const authorDetailsFragment = graphql` } } `; - ``` This data is then read out from the store by calling the `useFragment(...)` hook in a functional React component. The actual author from which to read this data is determined by the second parameter passed to `useFragment`. For example: -```js - +```javascript // AuthorDetails.react.js export default function AuthorDetails(props) { const data = useFragment(authorDetailsFragment, props.author); // ... } - ``` This second parameter (`props.author`) is a fragment reference. Fragment references are obtained by **spreading** a fragment into another fragment or query. Fragments cannot be fetched directly. Instead, all fragments must ultimately be spread (either directly or transitively) into a query for the data to be fetched. @@ -62,8 +58,7 @@ Let's take a look at one such query. In order to fetch that data, we might declare a query which spreads `AuthorDetails_author` as follows: -```js - +```javascript // Story.react.js const storyQuery = graphql` query StoryQuery($storyID: ID!) { @@ -75,13 +70,11 @@ const storyQuery = graphql` } } `; - ``` Now, we can fetch the query by calling `const data = useLazyLoadQuery(storyQuery, {storyID})`. At this point, `data.author` (if it is present; all fields are nullable by default) will be a fragment reference that we can pass to `AuthorDetails`. For example: -```js - +```javascript // Story.react.js function Story(props) { const data = useLazyLoadQuery(storyQuery, props.storyId); @@ -91,7 +84,6 @@ function Story(props) { {data?.story?.author && } ); } - ``` Note what has happened here. We made a single network request which contained the data required by *both* the `Story` component *and* the `AuthorDetails` component! When that data was available, the entire view could render in a single pass. diff --git a/website/versioned_docs/version-v2.0.0/GraphQL-ServerSpecification.md b/website/versioned_docs/version-v2.0.0/GraphQL-ServerSpecification.md index 6757812678ef1..5523ebd7bd46c 100644 --- a/website/versioned_docs/version-v2.0.0/GraphQL-ServerSpecification.md +++ b/website/versioned_docs/version-v2.0.0/GraphQL-ServerSpecification.md @@ -92,7 +92,6 @@ type IntroduceShipPayload { type Mutation { introduceShip(input: IntroduceShipInput!): IntroduceShipPayload } - ``` ## Object Identification @@ -111,7 +110,6 @@ query RebelsQuery { name } } - ``` returns @@ -124,7 +122,6 @@ returns "name": "Alliance to Restore the Republic" } } - ``` So now we know the ID of the Rebels in our system. We can now refetch them: @@ -139,7 +136,6 @@ query RebelsRefetchQuery { } } } - ``` returns @@ -152,7 +148,6 @@ returns "name": "Alliance to Restore the Republic" } } - ``` If we do the same thing with the Empire, we'll find that it returns a different ID, and we can refetch it as well: @@ -165,7 +160,6 @@ query EmpireQuery { name } } - ``` yields @@ -178,7 +172,6 @@ yields "name": "Galactic Empire" } } - ``` and @@ -193,7 +186,6 @@ query EmpireRefetchQuery { } } } - ``` yields @@ -206,7 +198,6 @@ yields "name": "Galactic Empire" } } - ``` The `Node` interface and `node` field assume globally unique IDs for this refetching. A system without globally unique IDs can usually synthesize them by combining the type with the type-specific ID, which is what was done in this example. @@ -235,7 +226,6 @@ query RebelsShipsQuery { } } } - ``` yields @@ -256,7 +246,6 @@ yields } } } - ``` That used the `first` argument to `ships` to slice the result set down to the first one. But what if we wanted to paginate through it? On each edge, a cursor will be exposed that we can use to paginate. Let's ask for the first two this time, and get the cursor as well: @@ -276,7 +265,6 @@ query MoreRebelShipsQuery { } } } - ``` and we get back @@ -304,7 +292,6 @@ and we get back } } } - ``` Notice that the cursor is a base64 string. That's the pattern from earlier: the server is reminding us that this is an opaque string. We can pass this string back to the server as the `after` argument to the `ships` field, which will let us ask for the next three ships after the last one in the previous result: @@ -324,7 +311,6 @@ query EndOfRebelShipsQuery { } } } - ``` gives us @@ -359,7 +345,6 @@ gives us } } } - ``` Sweet! Let's keep going and get the next four! @@ -379,7 +364,6 @@ query RebelsQuery { } } } - ``` yields @@ -394,7 +378,6 @@ yields } } } - ``` Hm. There were no more ships; guess there were only five in the system for the rebels. It would have been nice to know that we'd reached the end of the connection, without having to do another round trip in order to verify that. The connection model exposes this capability with a type called `PageInfo`. So let's issue the two queries that got us ships again, but this time ask for `hasNextPage`: @@ -426,7 +409,6 @@ query EndOfRebelShipsQuery { } } } - ``` and we get back @@ -477,7 +459,6 @@ and we get back } } } - ``` So on the first query for ships, GraphQL told us there was a next page, but on the next one, it told us we'd reached the end of the connection. @@ -507,7 +488,6 @@ type IntroduceShipPayload { ship: Ship clientMutationId: String! } - ``` With this input and payload, we can issue the following mutation: @@ -526,7 +506,6 @@ mutation AddBWingQuery($input: IntroduceShipInput!) { clientMutationId } } - ``` with these params: @@ -540,7 +519,6 @@ with these params: "clientMutationId": "abcde" } } - ``` and we'll get this result: @@ -559,7 +537,6 @@ and we'll get this result: "clientMutationId": "abcde" } } - ``` ## Further Reading diff --git a/website/versioned_docs/version-v2.0.0/Introduction-InstallationAndSetup.md b/website/versioned_docs/version-v2.0.0/Introduction-InstallationAndSetup.md index 240135d0bda12..d2db1ad3fac49 100644 --- a/website/versioned_docs/version-v2.0.0/Introduction-InstallationAndSetup.md +++ b/website/versioned_docs/version-v2.0.0/Introduction-InstallationAndSetup.md @@ -26,13 +26,11 @@ yarn add --dev babel-plugin-relay graphql Add `"relay"` to the list of plugins your `.babelrc` file: ```javascript - { "plugins": [ "relay" ] } - ``` Please note that the `"relay"` plugin should run before other plugins or @@ -44,9 +42,7 @@ See the [Migration Setup](./migration-setup) guide if upgrading an existing Rela Alternatively, instead of using `babel-plugin-relay`, you can use Relay with [babel-plugin-macros](https://github.com/kentcdodds/babel-plugin-macros). After installing `babel-plugin-macros` and adding it to your Babel config: ```javascript - const graphql = require('babel-plugin-relay/macro'); - ``` ## Set up relay-compiler @@ -61,22 +57,18 @@ yarn add --dev relay-compiler This installs the bin script `relay-compiler` in your node_modules folder. It's recommended to run this from a `yarn`/`npm` script by adding a script to your `package.json` file: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql" } - ``` or if you are using jsx: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --extensions js jsx" } - ``` Then, after making edits to your application files, just run the `relay` script to generate new compiled artifacts: @@ -111,15 +103,13 @@ polyfill in your bundled application, such as [core-js][] or A polyfilled environment for Relay using [core-js][] to support older browsers might look like: -```js - +```javascript require('core-js/es6/map'); require('core-js/es6/set'); require('core-js/es6/promise'); require('core-js/es6/object'); require('./myRelayApplication'); - ``` [core-js]: https://github.com/zloirock/core-js diff --git a/website/versioned_docs/version-v2.0.0/Introduction-QuickStartGuide.md b/website/versioned_docs/version-v2.0.0/Introduction-QuickStartGuide.md index 947915524a5eb..54bbaa8852cdd 100644 --- a/website/versioned_docs/version-v2.0.0/Introduction-QuickStartGuide.md +++ b/website/versioned_docs/version-v2.0.0/Introduction-QuickStartGuide.md @@ -24,7 +24,6 @@ Before starting, make sure to check out our [Prerequisites](./prerequisites) and Fortunately, we are going to be using this [example todo list app](https://github.com/relayjs/relay-examples/tree/master/todo), which already has a [server](https://github.com/relayjs/relay-examples/blob/master/todo/server.js) and [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql) available for us to use: ```graphql - # From schema.graphql # https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql @@ -37,7 +36,6 @@ type Query { id: ID! ): Node } - ``` Additionally, we will be using [Flow](https://flow.org/) inside our JavaScript code examples. Flow is optional to set up in your project, but we will include it in our examples for completeness. @@ -49,7 +47,6 @@ Before we can start rendering pixels on the screen, we need to configure Relay v For the purposes of our example, we are simply going to configure our environment to communicate with our existing GraphQL server: ```javascript - import { Environment, Network, @@ -81,7 +78,6 @@ const environment = new Environment({ }); export default environment; - ``` A Relay Environment requires at least a [Store](./relay-store) and a [Network Layer](./network-layer). The above code uses the default implementation for `Store`, and creates a [Network Layer](./network-layer) using a simple `fetchQuery` function to fetch a GraphQL query from our server. @@ -95,19 +91,16 @@ Now that we've configured our Relay Environment, we can start fetching queries a To start, let's assume we just want to render the user id on the screen. From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L66), we know that we can get the current `User` via the `viewer` field, so let's write a sample query to fetch the current user id: ```graphql - query UserQuery { viewer { id } } - ``` Now, let's see what it would take to create a component that fetches and renders the above query: ```javascript - // App.js import React from 'react'; import {graphql, QueryRenderer} from 'react-relay'; @@ -140,7 +133,6 @@ export default class App extends React.Component { ); } } - ``` Our app is rendering a `QueryRenderer` in the above code, like any other React Component, but let's see what's going on in the props that we are passing to it: @@ -159,19 +151,16 @@ For more details on `QueryRenderer`, check out the [docs](./query-renderer). Let's assume for a moment that in our app we want to be able to view data for different users, so we're going to somehow need to query users by id. From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L69), we know we can query nodes given an id, so let's write a parameterized query to get a user by id: ```graphql - query UserQuery($userID: ID!) { node(id: $userID) { id } } - ``` Now, let's see how we would fetch the above query using a `QueryRenderer`: ```javascript - // UserTodoList.js // @flow import React from 'react'; @@ -212,7 +201,6 @@ export default class UserTodoList extends React.Component { ); } } - ``` The above code is doing something very similar to our [previous example](#rendering-graphql-queries). However, we are now passing a `$userID` variable to the GraphQL query via the `variables` prop. This has a couple of important implications: @@ -229,7 +217,6 @@ Now that we know how to define and fetch queries, let's actually start building First, let's start at the bottom. Suppose that we want to render a component that simply displays a given todo item's text and completed state: ```javascript - // Todo.js import React from 'react'; @@ -259,7 +246,6 @@ export default class Todo extends React.Component { ); } } - ``` From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L107), we know that we can query this data on the `Todo` type. However, we don't want to have to send a separate query for each todo item; that would defeat the purpose of using GraphQL over a traditional REST API. We could manually query for these fields directly in our `QueryRenderer` query, but that would hurt re-usability: what if we want to query the same set of fields as part of a different query? Additionally, we wouldn't know which component needs the data we're querying, which is a problem Relay directly tries to address. @@ -267,18 +253,15 @@ From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/dat Instead, we can define a reusable [Fragment](http://graphql.org/learn/queries/#fragments), which allows us to define a set of fields on a type and reuse them within our queries wherever we need to: ```graphql - fragment TodoItemFragment on Todo { complete text } - ``` Our component can then use this fragment to declare its data dependency on the `Todo` GraphQL type: ```javascript - // Todo.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -338,7 +321,6 @@ Before proceeding, don't forget to run the Relay Compiler with `yarn relay`. Given that [Fragment Containers](./fragment-container) are just React components, we can compose them as such. We can even re-use fragment containers within other fragment containers. As an example, let's see how we would define a `TodoList` component that just renders a list of todo items, and whether all have been completed or not: ```javascript - // TodoList.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -397,7 +379,6 @@ export default createFragmentContainer( } `, ); - ``` As with the first fragment container we defined, `TodoList` declares it's data dependencies via a fragment. However, this component additionally re-uses the fragment previously defined by the `Todo` component, and passes the appropriate data when rendering the child `Todo` components (a.k.a. fragment containers). @@ -412,7 +393,6 @@ fragment containers do not directly fetch data. Instead, containers declare a sp A `QueryRenderer` rendering these fragment containers could look like the following: ```javascript - // ViewerTodoList.js import React from 'react'; import PropTypes from 'prop-types'; @@ -454,7 +434,6 @@ export default class ViewerTodoList extends React.Component { ); } } - ``` Check out our docs for [Fragment Containers](./fragment-container) for more details, and our guides on [Refetch](./refetch-container) and [Pagination](./pagination-container) for more advanced usage of containers. @@ -466,7 +445,6 @@ Now that we know how to query for and render data, let's move on to changing our From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L35), we know that we have some mutations available to us, so let's start by writing a mutation to change the `complete` status of a given todo item (i.e. mark or unmark it as done): ```graphql - mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { changeTodoStatus(input: $input) { todo { @@ -475,7 +453,6 @@ mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { } } } - ``` This mutation allows us to query back some data as a [result of the mutation](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L18), so we're going to query for the updated `complete` status on the todo item. @@ -483,7 +460,6 @@ This mutation allows us to query back some data as a [result of the mutation](ht In order to execute this mutation in Relay, we're going to write a new mutation using Relay's `commitMutation` api: ```javascript - // ChangeTodoStatusMutation.js import {graphql, commitMutation} from 'react-relay'; @@ -517,7 +493,6 @@ function commit( } export default {commit}; - ``` Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mutation to the server and, in our case, upon receiving a response it will automatically update the local data store with the latest data from the server. This also means that upon receiving the response, Relay will ensure that any components (i.e. containers) that depend on the updated data are re-rendered. @@ -525,7 +500,6 @@ Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mut In order to actually use this mutation in our component, we could update our `Todo` component in the following way: ```javascript - // Todo.js // ... @@ -559,7 +533,6 @@ In order to make the experience better, we can configure our mutation to do an o In Relay, there's a couple of options we can pass to `commitMutation` to enable optimistic updates. Let's see what that would look like in our `ChangeTodoStatusMutation`: ```javascript - // ChangeTodoStatusMutation.js // ... @@ -594,7 +567,6 @@ function commit( } export default {commit}; - ``` In the simplest case above, we just need to pass an `optimisticResponse` option, which should refer to an object having the same shape as the mutation response payload. When we pass this option, Relay will know to immediately update our local data with the optimistic response, and then update it with the actual server response or roll it back if an error occurs. diff --git a/website/versioned_docs/version-v2.0.0/Modern-ConvertingMutations.md b/website/versioned_docs/version-v2.0.0/Modern-ConvertingMutations.md index 08ad2e998cb2d..8f4bdc1d8e0d2 100644 --- a/website/versioned_docs/version-v2.0.0/Modern-ConvertingMutations.md +++ b/website/versioned_docs/version-v2.0.0/Modern-ConvertingMutations.md @@ -12,19 +12,16 @@ FatQueries in Relay Classic mutations was a concept that was confusing for a num Example of existing fat query: ```javascript - RelayClassic.QL` fragment on MarkReadNotificationResponsePayload @relay(pattern: true) { notification } `; - ``` Example of converted mutation query: ```javascript - graphql` mutation MarkReadNotificationMutation( $input: MarkReadNotificationData! @@ -37,7 +34,6 @@ graphql` } } `; - ``` ## Migrating Configs @@ -67,7 +63,6 @@ This is no longer needed in Compatibility Mode for neither environments. Simply Take this example of a simple mutation in Relay Classic: ```javascript - class LikeStoryMutation extends RelayClassic.Mutation { getMutation() { return RelayClassic.QL`mutation {likeStory}`; @@ -106,7 +101,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { `, }; } - ``` ### Converting `getMutation()` and `getFatQuery()` @@ -114,7 +108,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { We combine these two into a regular GraphQL mutation, which list out specific fields that needs to be updated. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story(data: $input) { @@ -126,7 +119,6 @@ const mutation = graphql` } } `; - ``` ### Converting `getConfigs()` @@ -138,13 +130,11 @@ As specified above, `FIELDS_CHANGE` configs can be omitted. To convert `getVariables()`, we take the return value from the original function and wrap it in an object that contains a property that matches the variable name for the mutation. In this case, the mutation has a `input` variable that is of type `LikeStoryData`. ```javascript - const variables = { input: { storyID: args.storyID } } - ``` ### Final Result @@ -152,7 +142,6 @@ const variables = { As you can see, our resulting mutation is a lot simpler and more like regular GraphQL than the Relay Classic version we started out with. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story { @@ -178,7 +167,6 @@ function commit(environment: CompatEnvironment, args) { variables, }); } - ``` See [Mutation](./mutations) for additional options on `commitMutation` for more complex mutations. diff --git a/website/versioned_docs/version-v2.0.0/Modern-FragmentContainer.md b/website/versioned_docs/version-v2.0.0/Modern-FragmentContainer.md index e86b79995c1c7..7bbd0a9f22899 100644 --- a/website/versioned_docs/version-v2.0.0/Modern-FragmentContainer.md +++ b/website/versioned_docs/version-v2.0.0/Modern-FragmentContainer.md @@ -17,12 +17,10 @@ Table of Contents: `createFragmentContainer` has the following signature: ```javascript - createFragmentContainer( component: ReactComponentClass, fragmentSpec: GraphQLTaggedNode | {[string]: GraphQLTaggedNode}, ): ReactComponentClass; - ``` ### Arguments @@ -46,7 +44,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -61,7 +58,6 @@ To start, let's build the plain React version of a hypothetical `` c Here's a basic implementation of `` that ignores styling in order to highlight the functionality: ```javascript - // TodoItem.js class TodoItem extends React.Component { render() { @@ -81,7 +77,6 @@ class TodoItem extends React.Component { ); } } - ``` ### Data Dependencies With GraphQL @@ -89,7 +84,6 @@ class TodoItem extends React.Component { In Relay, data dependencies are described using [GraphQL](https://github.com/facebook/graphql). For ``, the dependency can be expressed as follows. Note that this exactly matches the shape that the component expected for the `item` prop. ```javascript - graphql` # This fragment only applies to objects of type 'Todo'. fragment TodoItem_item on Todo { @@ -105,7 +99,6 @@ graphql` Given the plain React component and a GraphQL fragment, we can now define a Fragment Container to specify this component's data requirements. Let's look at the code first and then see what's happening: ```javascript - // TodoItem.js import {createFragmentContainer, graphql} from 'react-relay'; @@ -123,13 +116,11 @@ export default createFragmentContainer(TodoItem, { } `, }); - ``` Relay will infer the prop name from the fragment name according to the fragment naming convention `<...>_`. The example below is equivalent to the one above: ```javascript - export default createFragmentContainer( TodoItem, graphql` @@ -139,13 +130,11 @@ export default createFragmentContainer( } `, ); - ``` If there is no `_` suffix, the `data` prop name will be used: ```javascript - class TodoItem extends React.Component { render() { const item = this.props.data; @@ -162,7 +151,6 @@ export default createFragmentContainer( } `, ); - ``` ## Container Composition @@ -176,7 +164,6 @@ Let's explore how this works via a `` component that composes the `< View composition is _exactly_ what you're used to — Relay containers are just standard React components. Here's the `` component: ```javascript - class TodoList extends React.Component { render() { // Expects a `list` with a string `title`, as well as the information @@ -191,7 +178,6 @@ class TodoList extends React.Component { ); } } - ``` ### Composing Fragments @@ -199,7 +185,6 @@ class TodoList extends React.Component { Fragment composition works similarly — a parent container's fragment composes the fragment for each of its children. In this case, `` needs to fetch information about the `Todo`s that are required by ``. ```javascript - class TodoList extends React.Component // as above export default createFragmentContainer( @@ -217,7 +202,6 @@ export default createFragmentContainer( } `, ); - ``` Note that when composing fragments, the type of the composed fragment must match the field on the parent in which it is embedded. For example, it wouldn't make sense to embed a fragment of type `Story` into a parent's field of type `User`. Relay and GraphQL will provide helpful error messages if you get this wrong (and if they aren't helpful, let us know!). @@ -231,7 +215,6 @@ When defining a fragment, you can use the [`@argumentDefinitions`](./graphql-in- For example, let's redefine our `TodoList_list` fragment to take some arguments using `@argumentDefinitions`: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -241,7 +224,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` Any arguments defined inside `@argumentDefinitions` will be local variables available inside the fragment's scope. However, a fragment can also reference global variables that were defined in the root query. @@ -253,11 +235,9 @@ In order to pass arguments to a fragment that has `@argumentDefinitions`, you ne Following our `TodoList_list` example, we would pass arguments to the fragment like so: ```graphql - query TodoListQuery($count: Int, $userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` ### Calling Component Instance Methods @@ -268,7 +248,6 @@ Since Relay composes these component instances in a container, you need to use t Consider an input with a server-defined placeholder text and an imperative method to focus the input node: ```javascript - export default createFragmentContainer( class TodoInput extends React.Component { focus() { @@ -288,13 +267,11 @@ export default createFragmentContainer( } `, ); - ``` To call this method on the underlying component, first provide a `componentRef` function to the Relay container. This differs from providing a [`ref`](https://facebook.github.io/react/docs/refs-and-the-dom.html) function which would provide a reference to the Relay container itself, not the underlying React Component. ```javascript - export default createFragmentContainer( class TodoListView extends React.Component { render() { @@ -312,7 +289,6 @@ export default createFragmentContainer( } `, ); - ``` ## Rendering Containers diff --git a/website/versioned_docs/version-v2.0.0/Modern-GraphQLInRelay.md b/website/versioned_docs/version-v2.0.0/Modern-GraphQLInRelay.md index 18692b0d01784..6e544e33d2d13 100644 --- a/website/versioned_docs/version-v2.0.0/Modern-GraphQLInRelay.md +++ b/website/versioned_docs/version-v2.0.0/Modern-GraphQLInRelay.md @@ -14,7 +14,6 @@ Table of Contents: The `graphql` template tag provided by Relay serves as the mechanism to write queries, fragments, mutations or subscriptions in the [GraphQL](http://graphql.org/learn/) language. For example: ```javascript - import {graphql} from 'react-relay'; graphql` @@ -24,7 +23,6 @@ graphql` } } `; - ``` The result of using the `graphql` template tag is a `GraphQLTaggedNode`; a runtime representation of the GraphQL document which can be used to define [Query Renderers](./query-renderer), [Fragment Containers](./fragment-container), [Refetch Containers](./refetch-container), [Pagination Containers](./pagination-container), etc. @@ -42,11 +40,9 @@ Relay uses directives to add additional information to GraphQL documents, which `@arguments` is a directive used to pass arguments to a fragment that was defined using [`@argumentDefinitions`](#argumentdefinitions). For example: ```graphql - query TodoListQuery($userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -56,7 +52,6 @@ See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fr `@argumentDefinitions` is a directive used to specify arguments taken by a fragment. For example: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -66,7 +61,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -82,7 +76,6 @@ When using the [Pagination Container](./pagination-container), Relay expects con When defining a fragment for use with a Fragment container, you can use the `@relay(plural: true)` directive to indicate that container expects the prop for that fragment to be a list of items instead of a single item. A query or parent that spreads a `@relay(plural: true)` fragment should do so within a plural field (ie a field backed by a [GraphQL list](http://graphql.org/learn/schema/#lists-and-non-null). For example: ```javascript - // Plural fragment definition graphql` fragment TodoItems_items on TodoItem @relay(plural: true) { @@ -97,7 +90,6 @@ fragment TodoApp_app on App { ...TodoItem_items } } - ``` ### `@relay(mask: Boolean)` @@ -115,7 +107,6 @@ Keep in mind that it is typically considered an **anti-pattern** to create a sin In the example below, the `user` prop will include the data for `id` and `name` fields wherever `...Component_internUser` is included, instead of Relay's normal behavior to mask those fields: ```javascript - graphql` fragment Component_internUser on InternUser @relay(mask: false) { id @@ -143,7 +134,6 @@ export default createFragmentContainer( } `, ); - ``` ## Relay Compiler @@ -153,7 +143,6 @@ Relay uses the Relay Compiler to convert [`graphql`](#graphql) literals into gen A query like the following: ```javascript - graphql` fragment MyComponent on Type { field @@ -174,12 +163,10 @@ Relay Compiler supports the use of **persisted queries**, in which each version Persisted queries can be enabled by instructing Relay Compiler to emit metadata about each query, mutation, and subscription into a JSON file. The generated file will contain a mapping of query identifiers to query text, which you can then save to your server. To enable persisted queries, use the `--persist-output` flag to the compiler: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` Relay Compiler will then create the id => query text mapping in the path you specify. You can then use this complete @@ -196,7 +183,6 @@ See our relay-compiler section in our [Installation and Setup guide](./installat To use the Relay Compiler, you need either a .graphql or .json GraphQL schema file, describing your GraphQL server's API. Typically these files are local representations of a server source of truth and are not edited directly. For example, we might have a `schema.graphql` like: ```graphql - schema { query: Root } @@ -214,7 +200,6 @@ type WordDefinition { text: String image: String } - ``` ### Source files @@ -230,7 +215,6 @@ For example, given the two files: - `src/Components/DictionaryComponent.js` ```javascript - const DictionaryWordFragment = graphql` fragment DictionaryComponent_word on Word { id @@ -252,7 +236,6 @@ For example, given the two files: - `src/Queries/DictionaryQuery.js` ```javascript - const DictionaryQuery = graphql` query DictionaryQuery { dictionary { @@ -276,9 +259,7 @@ Typically you will not need to import your generated definitions. The [Relay Bab However the Relay Compiler also automatically generates [Flow](https://flow.org) types as [type comments](https://flow.org/en/docs/types/comments/). For example, you can import the generated Flow types like so: ```javascript - import type {DictionaryComponent_word} from './__generated__/DictionaryComponent_word.graphql'; - ``` ### Advanced usage diff --git a/website/versioned_docs/version-v2.0.0/Modern-LocalStateManagement.md b/website/versioned_docs/version-v2.0.0/Modern-LocalStateManagement.md index f3427f392a611..dc50079ca5fbe 100644 --- a/website/versioned_docs/version-v2.0.0/Modern-LocalStateManagement.md +++ b/website/versioned_docs/version-v2.0.0/Modern-LocalStateManagement.md @@ -23,23 +23,19 @@ It can even be used to extend an existing server schema. For example, we can create a new type called `Note`: ```graphql - type Note { id: ID! title: String body: String } - ``` And then extend the server schema type `User`, with a list of `Note`, called `notes`. ```graphql - extend type User { notes: [Note] } - ``` ## Querying local state @@ -50,7 +46,6 @@ The field can be from the server schema, or it can be schema agnostic, like an i Here, we use a [QueryRenderer](./query-renderer) to get the current `User` via the `viewer` field, along with their id, name and the local list of notes. ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -96,7 +91,6 @@ const Example = (props) => { /> ); } - ``` ## Mutating local state @@ -110,7 +104,6 @@ To build upon the previous example, let's try creating, updating and deleting a ### Create ```javascript - import {commitLocalUpdate} from 'react-relay'; let tempID = 0; @@ -130,7 +123,6 @@ function createUserNote() { user.setLinkedRecords([...userNoteRecords, newNoteRecord], 'notes'); }); } - ``` Note that since this record will be rendered by the `ExampleQuery` in our `QueryRenderer`, the QueryRenderer will automatically retain this data so it isn't garbage collected. @@ -138,7 +130,6 @@ Note that since this record will be rendered by the `ExampleQuery` in our `Query If no component is rendering the local data and you want to manually retain it, you can do so by calling `environment.retain()`: ```javascript - import {createOperationDescriptor, getRequest} from 'relay-runtime'; // Create a query that references that record @@ -165,13 +156,11 @@ const disposable = environment.retain(operation); // Whenever you don't need that data anymore and it's okay for Relay to garbage collect it, // you can dispose of the retain disposable.dispose(); - ``` ### Update ```javascript - import {commitLocalUpdate} from 'react-relay'; function updateUserNote(dataID, body, title) { @@ -182,13 +171,11 @@ function updateUserNote(dataID, body, title) { note.setValue(title, 'title') }); } - ``` ### Delete ```javascript - import {commitLocalUpdate} from 'react-relay'; function deleteUserNote(dataID) { @@ -206,7 +193,6 @@ function deleteUserNote(dataID) { user.setLinkedRecords(newUserNoteRecords, 'notes'); }); } - ``` ## Initial local state @@ -215,7 +201,6 @@ All new client-side schema fields default to `undefined` value. Often however, y You can use an updater function via `commitLocalUpdate` to prime local state. ```javascript - import {commitLocalUpdate} from 'react-relay'; commitLocalUpdate(environment, store => { @@ -224,5 +209,4 @@ commitLocalUpdate(environment, store => { // initialize user notes to an empty array. user.setLinkedRecords([], 'notes'); }); - ``` diff --git a/website/versioned_docs/version-v2.0.0/Modern-MigrationSetup.md b/website/versioned_docs/version-v2.0.0/Modern-MigrationSetup.md index 66f1145357e25..a89c0e178e0e5 100644 --- a/website/versioned_docs/version-v2.0.0/Modern-MigrationSetup.md +++ b/website/versioned_docs/version-v2.0.0/Modern-MigrationSetup.md @@ -13,13 +13,11 @@ With some additional configuration, the `"relay"` babel plugin can also translat Relay Classic `Relay.QL` literals. Most importantly, include a reference to your GraphQL Schema as either a json file or graphql schema file. ```javascript - { "plugins": [ ["relay", {"schema": "path/schema.graphql"}] ] } - ``` ## Set up babel-plugin-relay for "[compatibility mode](./relay-compat)" @@ -29,13 +27,11 @@ literals can be translated to be usable by _both_ runtimes if configured to use compatibility mode: ```javascript - { "plugins": [ ["relay", {"compat": true, "schema": "path/schema.graphql"}] ] } - ``` ## Additional Options @@ -47,7 +43,6 @@ thrown at runtime. When compiling code for production deployment, the plugin can be configured to immediately throw upon encountering a validation problem. The plugin can be further customized for different environments with the following options: ```javascript - { "plugins": [ ["relay", { @@ -56,5 +51,4 @@ When compiling code for production deployment, the plugin can be configured to i }] ] } - ``` diff --git a/website/versioned_docs/version-v2.0.0/Modern-Mutations.md b/website/versioned_docs/version-v2.0.0/Modern-Mutations.md index 2285d7a90be70..198060f21cb03 100644 --- a/website/versioned_docs/version-v2.0.0/Modern-Mutations.md +++ b/website/versioned_docs/version-v2.0.0/Modern-Mutations.md @@ -17,7 +17,6 @@ Table of Contents: Use `commitMutation` to create and execute mutations. `commitMutation` has the following signature: ```javascript - commitMutation( environment: Environment, config: { @@ -31,7 +30,6 @@ commitMutation( configs?: Array, }, ); - ``` ### Arguments @@ -58,7 +56,6 @@ commitMutation( Example of a simple mutation: ```javascript - import {commitMutation, graphql} from 'react-relay'; const mutation = graphql` @@ -93,7 +90,6 @@ function markNotificationAsRead(environment, source, storyID) { }, ); } - ``` ## Optimistic Updates @@ -101,7 +97,6 @@ function markNotificationAsRead(environment, source, storyID) { To improve perceived responsiveness, you may wish to perform an "optimistic update", in which the client immediately updates to reflect the anticipated new value even before the response from the server has come back. The simplest way to do this is by providing an `optimisticResponse` and adding it to the `config` that we pass into `commitMutation`: ```javascript - const mutation = graphql` mutation MarkReadNotificationMutation( $input: MarkReadNotificationInput! @@ -130,7 +125,6 @@ commitMutation( variables, }, ); - ``` Another way to enable optimistic updates is via the `optimisticUpdater`, which can be used for more complicated update scenarios. Using `optimisticUpdater` is covered in the section [below](#using-updater-and-optimisticupdater). @@ -152,7 +146,6 @@ Given a deletedIDFieldName, Relay will remove the node(s) from the store. #### Example ```javascript - const mutation = graphql` mutation DestroyShipMutation($input: DestroyShipInput!) { destroyShip(input: $input) { @@ -170,7 +163,6 @@ const configs = [{ type: 'NODE_DELETE', deletedIDFieldName: 'destroyedShipId', }]; - ``` ### RANGE_ADD @@ -190,7 +182,6 @@ Given a parent, information about the connection, and the name of the newly crea #### Example ```javascript - const mutation = graphql` mutation AddShipMutation($input: AddShipInput!) { addShip(input: $input) { @@ -220,7 +211,6 @@ function commit(environment, factionId, name) { }], }); } - ``` ### RANGE_DELETE @@ -242,7 +232,6 @@ from the connection but leave the associated record(s) in the store. #### Example ```javascript - const mutation = graphql` mutation RemoveTagMutation($input: RemoveTagInput!) { removeTag(input: $input) { @@ -268,7 +257,6 @@ function commit(environment, todoId, tagId) { }], }); } - ``` ## Using updater and optimisticUpdater @@ -286,7 +274,6 @@ When you provide these functions, this is roughly what happens during the mutati Here are a quick example of adding a todo item to a Todo list using this [example schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L36): ```javascript - // AddTodoMutation.js import {commitMutation, graphql} from 'react-relay'; import {ConnectionHandler} from 'relay-runtime'; @@ -373,7 +360,6 @@ function commit(environment, text, user) { }, }); } - ``` For details on how to interact with the Relay Store, please refer to our Relay Store [docs](./relay-store). diff --git a/website/versioned_docs/version-v2.0.0/Modern-NetworkLayer.md b/website/versioned_docs/version-v2.0.0/Modern-NetworkLayer.md index fcd9fd4dd5e03..daa8c71294c59 100644 --- a/website/versioned_docs/version-v2.0.0/Modern-NetworkLayer.md +++ b/website/versioned_docs/version-v2.0.0/Modern-NetworkLayer.md @@ -8,7 +8,6 @@ In order to know how to access your GraphQL server, Relay Modern requires develo Currently the easiest way to create a network layer is via a helper from the `relay-runtime` package: ```javascript - import { Environment, Network, @@ -50,7 +49,6 @@ const environment = new Environment({ }); export default environment; - ``` Note that this is a basic example to help you get started. This example could be extended with additional features such as request/response caching (enabled e.g. when `cacheConfig.force` is false) and uploading form data for mutations (the `uploadables` parameter). @@ -62,7 +60,6 @@ Relay modern makes no assumptions about what to cache and will garbage collect a You have to implement your own cache strategy. A simple solution is to use `RelayQueryResponseCache`(an in-memory cache): ```javascript - import { Environment, Network, @@ -126,7 +123,6 @@ const environment = new Environment({ }); export default environment; - ``` ## Custom open-source implementations diff --git a/website/versioned_docs/version-v2.0.0/Modern-PaginationContainer.md b/website/versioned_docs/version-v2.0.0/Modern-PaginationContainer.md index e17127d79bb52..818a870d5fe63 100644 --- a/website/versioned_docs/version-v2.0.0/Modern-PaginationContainer.md +++ b/website/versioned_docs/version-v2.0.0/Modern-PaginationContainer.md @@ -24,7 +24,6 @@ However, when [specifying connection fragments](#createpaginationcontainer) for The purpose of the `@connection` directive is to allow Relay to uniquely identify different connections under a parent type. The `@connection` directive takes 2 arguments that help identify the connection: ```graphql - @connection(key: String!, filters: [String]) ``` @@ -37,7 +36,6 @@ The purpose of the `@connection` directive is to allow Relay to uniquely identif Specifying just the `key`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and the value of `$orderBy` (given that no `filters` were provided) @@ -53,13 +51,11 @@ fragment Feed_user on User { } } } - ``` Specifying `key` and `filters`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and /only/ the value of `$searchTerm`, i.e. @@ -77,7 +73,6 @@ fragment Feed_user on User { } } } - ``` ## `createPaginationContainer` @@ -85,7 +80,6 @@ fragment Feed_user on User { `createPaginationContainer` has the following signature: ```javascript - createPaginationContainer( component: ReactComponentClass, fragmentSpec: GraphQLTaggedNode | {[string]: GraphQLTaggedNode}, @@ -113,7 +107,6 @@ type ConnectionData = { startCursor: ?string, }, }; - ``` ### Arguments @@ -137,7 +130,6 @@ type ConnectionData = { The Component resulting from `createPaginationContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -148,7 +140,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -163,7 +154,6 @@ type Props = { `hasMore` is a function available on the `relay` [prop](#available-props). This function indicates whether there are more pages to fetch from the server or not. ```javascript - hasMore: () => boolean, ``` @@ -173,7 +163,6 @@ hasMore: () => boolean, `isLoading` is a function available on the `relay` [prop](#available-props). This function indicates if a previous call to [`loadMore()`](#loadmore) is still pending. This is convenient for avoiding duplicate load calls. ```javascript - isLoading: () => boolean, ``` @@ -183,7 +172,6 @@ isLoading: () => boolean, `loadMore` is a function available on the `relay` [prop](#available-props). You can call `loadMore()` to fetch more items from the server based on the `connectionConfig` provided to the container. This will return null if there are no more items to fetch, otherwise it will fetch more items and return a Disposable that can be used to cancel the fetch. ```javascript - loadMore(pageSize: number, callback: ?(error: ?Error) => void): ?Disposable ``` @@ -198,7 +186,6 @@ loadMore(pageSize: number, callback: ?(error: ?Error) => void): ?Disposable `refetchConnection` is a function available on the `relay` [prop](#available-props). You can call `refetchConnection` to restart pagination on a connection from scratch, with optionally a completely new set of variables to pass to the pagination `query`. This is useful for example if you are paginating over a collection based on a userID and the userID changes, you'd want to start paginating over the new collection for the new user. ```javascript - refetchConnection:( totalCount: number, callback: (error: ?Error) => void, @@ -216,7 +203,6 @@ refetchConnection:( ## Pagination Example ```javascript - // Feed.js import {createPaginationContainer, graphql} from 'react-relay'; @@ -311,5 +297,4 @@ module.exports = createPaginationContainer( ` } ); - ``` diff --git a/website/versioned_docs/version-v2.0.0/Modern-PersistedQueries.md b/website/versioned_docs/version-v2.0.0/Modern-PersistedQueries.md index 137cc2e23220c..ec03b69ba09c3 100644 --- a/website/versioned_docs/version-v2.0.0/Modern-PersistedQueries.md +++ b/website/versioned_docs/version-v2.0.0/Modern-PersistedQueries.md @@ -17,12 +17,10 @@ The relay compiler supports persisted queries which is useful because: In your `npm` script in `package.json`, run the relay compiler using the `--persist-output` flag: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` The `--persist-ouput` flag does 3 things: @@ -31,8 +29,7 @@ The `--persist-ouput` flag does 3 things: For example without `--persist-output`, a generated `ConcreteRequest` might look like below: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -49,8 +46,7 @@ The `--persist-ouput` flag does 3 things: With `--persist-output ` this becomes: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -68,12 +64,10 @@ The `--persist-ouput` flag does 3 things: 2. It generates a JSON file at the `` you specify containing a mapping from query ids to the corresponding operation texts. -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./src/queryMaps/queryMap.json" } - ``` The example above writes the complete query map file to `./src/queryMaps/queryMap.json`. You need to ensure all the directories @@ -83,8 +77,7 @@ leading to the `queryMap.json` file exist. You'll need to modify your network layer fetch implementation to pass a documentId parameter in the POST body instead of a query parameter: -```js - +```javascript function fetchQuery(operation, variables,) { return fetch('/graphql', { method: 'POST', @@ -100,7 +93,6 @@ function fetchQuery(operation, variables,) { return response.json(); }); } - ``` ## Executing Persisted Queries on the Server @@ -116,13 +108,11 @@ the query map file in a common location accessible to both the client and the se For applications where the client and server projects are separate, one option is to have an additional npm run script to push the query map at compile time to a location accessible by your server: -```js - +```javascript "scripts": { "push-queries": "node ./pushQueries.js", "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-ouput && npm run push-queries" } - ``` Some possibilities of what you can do in `./pushQueries.js`: @@ -146,8 +136,7 @@ database technologies you use, so we'll just cover the most common and basic exa If you use `express-graphql` and have access to the query map file, you can import the `--persist-output` JSON file directly and perform the matching using the `matchQueryMiddleware` from [relay-compiler-plus](https://github.com/yusinto/relay-compiler-plus). -```js - +```javascript import Express from 'express'; import expressGraphql from 'express-graphql'; import {matchQueryMiddleware} from 'relay-compiler-plus'; @@ -158,7 +147,6 @@ const app = Express(); app.use('/graphql', matchQueryMiddleware(queryMapJson), expressGraphql({schema})); - ``` ## Using `--persist-output` and `--watch` diff --git a/website/versioned_docs/version-v2.0.0/Modern-QueryRenderer.md b/website/versioned_docs/version-v2.0.0/Modern-QueryRenderer.md index 8787283987b82..4259a7a543545 100644 --- a/website/versioned_docs/version-v2.0.0/Modern-QueryRenderer.md +++ b/website/versioned_docs/version-v2.0.0/Modern-QueryRenderer.md @@ -23,7 +23,6 @@ However, a `QueryRenderer` will not start loading its data until it is mounted, ## Example ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -55,5 +54,4 @@ class Example extends React.Component { ); } } - ``` diff --git a/website/versioned_docs/version-v2.0.0/Modern-RefetchContainer.md b/website/versioned_docs/version-v2.0.0/Modern-RefetchContainer.md index 930b460e80f54..d33fc948d775c 100644 --- a/website/versioned_docs/version-v2.0.0/Modern-RefetchContainer.md +++ b/website/versioned_docs/version-v2.0.0/Modern-RefetchContainer.md @@ -16,13 +16,11 @@ Table of Contents: `createRefetchContainer` has the following signature: ```javascript - createRefetchContainer( component: ReactComponentClass, fragmentSpec: GraphQLTaggedNode | {[string]: GraphQLTaggedNode}, refetchQuery: GraphQLTaggedNode, ): ReactComponentClass; - ``` ### Arguments @@ -40,7 +38,6 @@ createRefetchContainer( The Component resulting from `createRefetchContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -48,7 +45,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -64,7 +60,6 @@ type Props = { `refetch` has the following signature: ```javascript - type RefetchOptions = { force?: boolean, }; @@ -104,7 +99,6 @@ Returns a `Disposable` on which you could call `dispose()` to cancel the refetch In this simple example, let's assume we want to fetch the latest data for a `TodoItem` from the server: ```javascript - // TodoItem.js import {createRefetchContainer, graphql} from 'react-relay'; @@ -148,7 +142,6 @@ export default createRefetchContainer( } ` ); - ``` ### Loading more data @@ -156,7 +149,6 @@ export default createRefetchContainer( In this example we are using a Refetch Container to fetch more stories in a story feed component. ```javascript - import {createRefetchContainer, graphql} from 'react-relay'; class FeedStories extends React.Component { @@ -212,5 +204,4 @@ export default createRefetchContainer( } `, ); - ``` diff --git a/website/versioned_docs/version-v2.0.0/Modern-RelayCompat.md b/website/versioned_docs/version-v2.0.0/Modern-RelayCompat.md index 36632d3a8f1a1..f47dbd845ba3e 100644 --- a/website/versioned_docs/version-v2.0.0/Modern-RelayCompat.md +++ b/website/versioned_docs/version-v2.0.0/Modern-RelayCompat.md @@ -31,7 +31,6 @@ Relay Modern. The components using Relay Compat can be referred to by both other Relay Modern and Relay Classic components. ```javascript - const {createFragmentContainer, graphql} = require('react-relay/compat'); class TodoItem extends React.Component { @@ -47,5 +46,4 @@ module.exports = createFragmentContainer(TodoItem, graphql` isComplete } `); - ``` diff --git a/website/versioned_docs/version-v2.0.0/Modern-RelayEnvironment.md b/website/versioned_docs/version-v2.0.0/Modern-RelayEnvironment.md index b356b5deecdc5..ed75bc69d1f86 100644 --- a/website/versioned_docs/version-v2.0.0/Modern-RelayEnvironment.md +++ b/website/versioned_docs/version-v2.0.0/Modern-RelayEnvironment.md @@ -12,7 +12,6 @@ Most applications will create a single Environment instance and use it throughou To create an environment instance in Relay Modern, use the `RelayModernEnvironment` class: ```javascript - const { Environment, Network, @@ -30,7 +29,6 @@ const environment = new Environment({ network, store, }); - ``` For more details on creating a Network, see the [NetworkLayer guide](./network-layer). @@ -44,7 +42,6 @@ The example above did not configure a `handlerProvider`, which means that a defa If you wish to provide your own `handlerProvider`, you can do so: ```javascript - const { ConnectionHandler, ViewerHandler, @@ -60,5 +57,4 @@ function handlerProvider(handle) { `handlerProvider: No handler provided for ${handle}` ); } - ``` diff --git a/website/versioned_docs/version-v2.0.0/Modern-RelayStore.md b/website/versioned_docs/version-v2.0.0/Modern-RelayStore.md index 6bdeeb471b64f..4de7abfbecf1d 100644 --- a/website/versioned_docs/version-v2.0.0/Modern-RelayStore.md +++ b/website/versioned_docs/version-v2.0.0/Modern-RelayStore.md @@ -16,7 +16,6 @@ Table of Contents: The `RecordSourceSelectorProxy` is the type of the `store` that [`updater` functions](./mutations#using-updater-and-optimisticupdater) receive as an argument. The following is the `RecordSourceSelectorProxy` interface: ```javascript - interface RecordSourceSelectorProxy { create(dataID: string, typeName: string): RecordProxy; delete(dataID: string): void; @@ -25,7 +24,6 @@ interface RecordSourceSelectorProxy { getRootField(fieldName: string): ?RecordProxy; getPluralRootField(fieldName: string): ?Array; } - ``` ### `create(dataID: string, typeName: string): RecordProxy` @@ -35,9 +33,7 @@ Creates a new record in the store given a `dataID` and the `typeName` as defined #### Example ```javascript - const record = store.create(dataID, 'Todo'); - ``` ### `delete(dataID: string): void` @@ -47,9 +43,7 @@ Deletes a record from the store given its `dataID`. #### Example ```javascript - store.delete(dataID); - ``` ### `get(dataID: string): ?RecordProxy` @@ -59,9 +53,7 @@ Retrieves a record from the store given its `dataID`. Returns a [`RecordProxy`]( #### Example ```javascript - const record = store.get(dataID); - ``` ### `getRoot(): RecordProxy` @@ -73,20 +65,16 @@ Returns the [`RecordProxy`](#recordproxy) representing the root of the GraphQL d Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - // Represents root query const root = store.getRoot(); - ``` ### `getRootField(fieldName: string): ?RecordProxy` @@ -98,19 +86,15 @@ Retrieves a root field from the store given the `fieldName`, as defined by the G Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - const viewer = store.getRootField('viewer'); - ``` ### `getPluralRootField(fieldName: string): ?Array` @@ -122,19 +106,15 @@ Retrieves a root field that represents a collection from the store given the `fi Given the GraphQL document: ```graphql - nodes(first: 10) { # ... } - ``` Usage: ```javascript - const nodes = store.getPluralRootField('nodes'); - ``` ## RecordProxy @@ -142,7 +122,6 @@ const nodes = store.getPluralRootField('nodes'); The `RecordProxy` serves as an interface to mutate records: ```javascript - interface RecordProxy { copyFieldsFrom(sourceRecord: RecordProxy): void; getDataID(): string; @@ -167,7 +146,6 @@ interface RecordProxy { ): RecordProxy; setValue(value: mixed, name: string, arguments?: ?Object): RecordProxy; } - ``` ### `getDataID(): string` @@ -177,9 +155,7 @@ Returns the dataID of the current record. #### Example ```javascript - const id = record.getDataID(); - ``` ### `getType(): string` @@ -189,7 +165,6 @@ Gets the type of the current record, as defined by the GraphQL schema. #### Example ```javascript - const type = user.getType(); // User ``` @@ -203,20 +178,16 @@ Gets the value of a field in the current record given the field name. Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - const name = viewer.getValue('name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. @@ -226,20 +197,16 @@ Optionally, if the field takes arguments, you can pass a bag of `variables`. Given the GraphQL document: ```graphql - viewer { id name(arg: $arg) } - ``` Usage: ```javascript - const name = viewer.getValue('name', {arg: 'value'}); - ``` ### `getLinkedRecord(name: string, arguments?: ?Object): ?RecordProxy` @@ -251,23 +218,19 @@ Retrieves a record associated with the current record given the field name, as d Given the GraphQL document: ```graphql - rootField { viewer { id name } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -277,22 +240,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { viewer(arg: $arg) { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {arg: 'value'}); - ``` ### `getLinkedRecords(name: string, arguments?: ?Object): ?Array` @@ -304,22 +263,18 @@ Retrieves the set of records associated with the current record given the field Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const nodes = rootField.getLinkedRecords('nodes'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -329,22 +284,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { nodes(first: $count) { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {count: 10}); - ``` ### `getOrCreateLinkedRecord(name: string, typeName: string, arguments?: ?Object)` @@ -356,19 +307,16 @@ Retrieves the a record associated with the current record given the field name, Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = rootField.getOrCreateLinkedRecord('viewer', 'User'); // Will create if it doesn't exist @@ -383,28 +331,22 @@ Mutates the current record by setting a new value on the specified field. Return Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - viewer.setValue('New Name', 'name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. ```javascript - viewer.setValue('New Name', 'name', {arg: 'value'}); - ``` ### `copyFieldsFrom(sourceRecord: RecordProxy): void` @@ -414,7 +356,6 @@ Mutates the current record by copying the fields over from the passed in record #### Example ```javascript - const record = store.get(id1); const otherRecord = store.get(id2); record.copyFieldsFrom(otherRecord); // Mutates `record` @@ -430,19 +371,16 @@ Mutates the current record by setting a new linked record on the given the field Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = store.create(/* ... */)'' rootField.setLinkedRecord(newViewer, 'viewer'); // @@ -460,19 +398,16 @@ Mutates the current record by setting a new set of linked records on the given t Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newNode = store.create(/* ... */); const newNodes = [...rootField.getLinkedRecords('nodes'), newNode]; @@ -487,7 +422,6 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl `ConnectionHandler` is a utility module exposed by `relay-runtime` that aids in the manipulation of connections. `ConnectionHandler` exposes the following interface: ```javascript - interface ConnectionHandler { getConnection( record: RecordProxy, @@ -512,7 +446,6 @@ interface ConnectionHandler { ): void, deleteNode(connection: RecordProxy, nodeID: string): void } - ``` ### `getConnection(record: RecordProxy, key: string, filters?: ?Object)` @@ -522,7 +455,6 @@ Given a record and a connection key, and optionally a set of filters, `getConnec First, let's take a look at a plain connection: ```graphql - fragment FriendsFragment on User { friends(first: 10) { edges { @@ -532,26 +464,22 @@ fragment FriendsFragment on User { } } } - ``` Accessing a plain connection field like this is the same as other regular field: ```javascript - // The `friends` connection record can be accessed with: const user = store.get(userID); const friends = user && user.getLinkedRecord(user, 'friends'); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` In a [pagination container](./pagination-container), we usually annotate the actual connection field with `@connection` to tell Relay which part needs to be paginated: ```graphql - fragment FriendsFragment on User { friends(first: 10, orderby: "firstname") @connection( key: "FriendsFragment_friends", @@ -563,7 +491,6 @@ fragment FriendsFragment on User { } } } - ``` For connections like the above, `ConnectionHandler` helps us find the record: @@ -581,7 +508,6 @@ const friends = ConnectionHandler.getConnection( ); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` ### Edge creation and insertion @@ -611,7 +537,6 @@ ConnectionHandler.insertEdgeAfter(friends, edge); // No cursor provided, Insert the edge at the front: ConnectionHandler.insertEdgeBefore(friends, edge); - ``` ### `deleteNode(connection: RecordProxy, nodeID: string): void` @@ -625,5 +550,4 @@ Given a connection, deletes any edges whose id matches the given id. const user = store.get(userID); const friends = ConnectionHandler.getConnection(user, 'friends'); ConnectionHandler.deleteNode(friends, idToDelete); - ``` diff --git a/website/versioned_docs/version-v2.0.0/Modern-Subscriptions.md b/website/versioned_docs/version-v2.0.0/Modern-Subscriptions.md index 3521d610d6bc6..a104adde23e89 100644 --- a/website/versioned_docs/version-v2.0.0/Modern-Subscriptions.md +++ b/website/versioned_docs/version-v2.0.0/Modern-Subscriptions.md @@ -6,7 +6,6 @@ original_id: subscriptions Relay exposes the following APIs to create subscriptions. ```javascript - const {requestSubscription} = require('react-relay'); type Variables = {[name: string]: any}; @@ -27,7 +26,6 @@ requestSubscription( configs?: Array, }, ) => Disposable; - ``` The function returns a `Disposable` on which you could call `dispose()` to cancel the refetch. @@ -53,7 +51,6 @@ appropriate when you are only changing the properties of existing records that can be identified by their `id`: ```javascript - const { requestSubscription, graphql, @@ -87,7 +84,6 @@ requestSubscription( onError: error => console.error(error), } ); - ``` # Updating the client on each response @@ -97,7 +93,6 @@ Relay's in-memory cache when each subscription response is received. To do so, pass an `updater` function: ```javascript - const {ConnectionHandler} = require('relay-runtime'); requestSubscription( @@ -123,5 +118,4 @@ requestSubscription( }, }, ); - ``` diff --git a/website/versioned_docs/version-v2.0.0/Modern-TestingRelayComponents.md b/website/versioned_docs/version-v2.0.0/Modern-TestingRelayComponents.md index f30317b146e96..eaa443bd20147 100644 --- a/website/versioned_docs/version-v2.0.0/Modern-TestingRelayComponents.md +++ b/website/versioned_docs/version-v2.0.0/Modern-TestingRelayComponents.md @@ -64,7 +64,6 @@ With the `MockPayloadGenerator` and `@relay_test_operation`, we want to get rid Example of a simple Mock Resolver: ```javascript - { ID() { // Return mock value for a scalar filed with type ID @@ -75,13 +74,11 @@ Example of a simple Mock Resolver: return "Lorem Ipsum" } } - ``` It is possible to define more resolvers for Object types: ```javascript - { // This will be the default values for User object in the query response User() { @@ -94,7 +91,6 @@ It is possible to define more resolvers for Object types: }; }, } - ``` ### Mock Resolver Context @@ -102,7 +98,6 @@ It is possible to define more resolvers for Object types: The first argument of the MockResolver is the object that contains Mock Resolver Context. It is possible to return dynamic values from mock resolvers based on the context - for instance, name or alias of the field, a path in the selection, arguments, or parent type. ```javascript - { String(context) { if (context.name === 'zip') { @@ -116,7 +111,6 @@ The first argument of the MockResolver is the object that contains Mock Resolver } } } - ``` ### ID Generation @@ -124,14 +118,12 @@ The first argument of the MockResolver is the object that contains Mock Resolver The second argument of the Mock Resolver its a function that will generate a sequence of integers, useful to generate unique IDs in the tests: ```javascript - { // will generate strings "my-id-1", "my-id-2", etc. ID(_, generateId) { return `my-id-${generateId()}`; }, } - ``` ### `@relay_test_operation` @@ -141,7 +133,6 @@ Most of GraphQL type information for a specific field in the selection is not av Operations with the `@relay_test_operation` directive will have additional metadata that will contain GraphQL type info for fields in the operation's selection. And it will improve the quality of the generated data. You also will be able to define Mock resolvers for Scalar (not only ID and String) and Abstract types: ```javascript - { Float() { return 123.456; @@ -159,7 +150,6 @@ Operations with the `@relay_test_operation` directive will have additional metad }; } } - ``` ## Examples @@ -169,7 +159,6 @@ Operations with the `@relay_test_operation` directive will have additional metad Using `createMockEnvironment` and `MockPayloadGenerator` allows writing concise tests for components that are using Relay Containers and Renderers. Both those modules can be imported from `relay-test-utils`. ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { @@ -222,7 +211,6 @@ test('Error State', () => { renderer.root.find(item => (item.props.testID = 'errorMessage')), ).toBeDefined(); }); - ``` ### Fragment Container Tests @@ -230,7 +218,6 @@ test('Error State', () => { Essentially, in the example above, `resolveMostRecentOperation` will generate data for all child fragment containers (pagination, refetch). Usually, the Root Components container may have many child fragment components and you may want to exercise a specific Fragment Container. The solution for that would be to wrap your fragment container with the QueryRenderer that renders a Query that's spreads fragments from your fragment container. ```javascript - test('Fragment Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -261,7 +248,6 @@ test('Fragment Container', () => { expect(renderer).toMatchSnapshot(); }); - ``` ### Pagination Container Test @@ -269,7 +255,6 @@ test('Fragment Container', () => { Essentially, tests for Pagination container are not different from Fragment Container tests. We can also do more here. We can actually see how the pagination works by asserting the behavior of our components when performing pagination (load more, refetch). ```javascript - // Pagination Example test('Pagination Container', () => { const environment = createMockEnvironment(); @@ -343,7 +328,6 @@ test('Pagination Container', () => { We can use similar approach here with wrapping container with Query Renderer. And for the sake of completeness, we will add example here: ```javascript - test('Refetch Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -385,7 +369,6 @@ test('Refetch Container', () => { ); // expect(renderer).toMatchSnapshot(); }); - ``` ### Mutations @@ -393,7 +376,6 @@ test('Refetch Container', () => { Mutations itself are operations so we can test them independently (unit-test) for specific mutation, or in combination with the view from which this mutation is called. ```javascript - // Say, you have a mutation function function sendMutation(environment, onCompleted, onError, variables) commitMutation(environment, { @@ -416,7 +398,6 @@ test('it should send mutation', () => { ); expect(onCompleted).toBeCalled(); }); - ``` ### Subscription @@ -424,7 +405,6 @@ test('it should send mutation', () => { We can test subscription in a similar way we test mutations ```javascript - // Example subscribe function function subscribe(environment, onNext, onError, variables) requestSubscription(environment, { @@ -447,7 +427,6 @@ test('it should subscribe', () => { ); expect(onNext).toBeCalled(); }); - ``` ### Example with `queueOperationResolver` @@ -455,7 +434,6 @@ test('it should subscribe', () => { With `queueOpeararionResolver`, it possible to define responses for operations that will be executed on the environment ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { diff --git a/website/versioned_docs/version-v2.0.0/Modern-TypeEmission.md b/website/versioned_docs/version-v2.0.0/Modern-TypeEmission.md index c25bc737d5684..9f41810a3618b 100644 --- a/website/versioned_docs/version-v2.0.0/Modern-TypeEmission.md +++ b/website/versioned_docs/version-v2.0.0/Modern-TypeEmission.md @@ -15,7 +15,6 @@ In this example the emitted type-information would require the variables object #### Flow ```javascript - /** * export type ExampleQueryVariables = {| * +artistID: string @@ -43,7 +42,6 @@ const variables: ExampleQueryVariables = { #### TypeScript ```javascript - /** * export type ExampleQueryVariables = { * readonly artistID: string @@ -78,7 +76,6 @@ In this example the emitted type-information describes the response data availab #### Flow ```javascript - /** * export type ExampleQueryResponse = {| * +artist: ?{| @@ -109,7 +106,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * export type ExampleQueryResponse = { * readonly artist?: { @@ -145,7 +141,6 @@ Similarly, in this example the emitted type-information describes the prop data #### Flow ```javascript - /** * export type ExampleFragment_artist = {| * +name: string @@ -171,7 +166,6 @@ export const ExampleFragment = createFragmentContainer( #### TypeScript ```javascript - /** * export type ExampleFragment_artist = { * readonly name: string @@ -205,7 +199,6 @@ Consider a component that composes the above fragment container example. In this #### Flow ```javascript - /** * import type { FragmentReference } from "relay-runtime"; * declare export opaque type ExampleFragment_artist$ref: FragmentReference; @@ -249,7 +242,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * declare const _ExampleFragment_artist$ref: unique symbol; * export type ExampleFragment_artist$ref = typeof _ExampleFragment_artist$ref; @@ -314,7 +306,6 @@ $ relay-compiler --artifactDirectory ./src/__generated__ […] ["relay", { "artifactDirectory": "./src/__generated__" }] ] } - ``` It is recommended to alias this directory in your module resolution configuration such that you don’t need to specify relative paths in your source files. This is what is also done in the above examples, where artifacts are imported from a `__generated__` alias, rather than relative paths like `../../../../__generated__`. diff --git a/website/versioned_docs/version-v2.0.0/Modern-UpgradingSetVariables.md b/website/versioned_docs/version-v2.0.0/Modern-UpgradingSetVariables.md index d5b086fafce20..ff73feec04f8b 100644 --- a/website/versioned_docs/version-v2.0.0/Modern-UpgradingSetVariables.md +++ b/website/versioned_docs/version-v2.0.0/Modern-UpgradingSetVariables.md @@ -36,7 +36,6 @@ fragment on User { # ... } } - ``` This should be upgraded to use a [`PaginationContainer`](./pagination-container). @@ -61,7 +60,6 @@ fragment on User { # ... } } - ``` This can be upgraded by using a [`RefetchContainer`](./refetch-container) which allows you to specify the exact query to use to fetch the new data. @@ -86,7 +84,6 @@ fragment on FeedbackTarget { # ... } } - ``` This can be upgraded by conditionally rendering a [`QueryRenderer`](./query-renderer) which will load the data once it is rendered. The code overhead of doing this is dramatically reduced with the new API. diff --git a/website/versioned_docs/version-v2.0.0/Modern-fetchQuery.md b/website/versioned_docs/version-v2.0.0/Modern-fetchQuery.md index 939631d03832b..b4922b01b6c2b 100644 --- a/website/versioned_docs/version-v2.0.0/Modern-fetchQuery.md +++ b/website/versioned_docs/version-v2.0.0/Modern-fetchQuery.md @@ -6,7 +6,6 @@ original_id: fetch-query You can use the `fetchQuery` function to imperatively make GraphQL Requests. This is useful for cases where you want to make requests outside of React but still utilize the Relay store and network layer. ```javascript - import {fetchQuery, graphql} from 'relay-runtime'; const query = graphql` @@ -25,7 +24,6 @@ fetchQuery(environment, query, variables) .then(data => { // access the graphql response }); - ``` ## Arguments diff --git a/website/versioned_docs/version-v2.0.0/PrinciplesAndArchitecture-Compiler.md b/website/versioned_docs/version-v2.0.0/PrinciplesAndArchitecture-Compiler.md index c195491682b1f..fcd0490cb724f 100644 --- a/website/versioned_docs/version-v2.0.0/PrinciplesAndArchitecture-Compiler.md +++ b/website/versioned_docs/version-v2.0.0/PrinciplesAndArchitecture-Compiler.md @@ -74,7 +74,6 @@ foo { # type FooType foo { id } - ``` - `SkipRedundantNodeTransform`: A more advanced version of flattening, this eliminates more complex cases of field duplication such as when a field is fetched both unconditionally and conditionally, or is fetched by two different sub-fragments. For example: @@ -97,7 +96,6 @@ foo { id } } - ``` - `GenerateRequisiteFieldTransform`: This optional, Relay-specific transform inserts `id` fields for globally identifiable objects and `__typename` fields wherever the type cannot be statically determined (e.g. for unions). diff --git a/website/versioned_docs/version-v2.0.0/PrinciplesAndArchitecture-Runtime.md b/website/versioned_docs/version-v2.0.0/PrinciplesAndArchitecture-Runtime.md index 9491d290c146f..e9221631a701d 100644 --- a/website/versioned_docs/version-v2.0.0/PrinciplesAndArchitecture-Runtime.md +++ b/website/versioned_docs/version-v2.0.0/PrinciplesAndArchitecture-Runtime.md @@ -77,7 +77,6 @@ RecordSource { city: 'Seattle', } } - ``` [1] Note that GraphQL itself does not impose this constraint, and Relay Runtime may also be used for schemas that do not conform to it. For example, both systems can be used to query a single denormalized table. However, many of the features that Relay Runtime provides, such as caching and normalization, work best when the data is represented as a normalized graph with stable identities for discrete pieces of information. diff --git a/website/versioned_docs/version-v2.0.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md b/website/versioned_docs/version-v2.0.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md index a8842ae084922..9ff8a7840df90 100644 --- a/website/versioned_docs/version-v2.0.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md +++ b/website/versioned_docs/version-v2.0.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md @@ -12,7 +12,6 @@ In this article we'll explore what it means to build a GraphQL client framework Imagine we have a simple application that fetches a list of stories, and some details about each one. Here's how that might look in resource-oriented REST: ```javascript - // Fetch the list of story IDs but not their details: rest.get('/stories').then(stories => // This resolves to a list of items with linked resources: @@ -25,13 +24,11 @@ rest.get('/stories').then(stories => // `[ { id: "...", text: "..." } ]` console.log(stories); }); - ``` Note that this approach requires _n+1_ requests to the server: 1 to fetch the list, and _n_ to fetch each item. With GraphQL we can fetch the same data in a single network request to the server (without creating a custom endpoint that we'd then have to maintain): ```javascript - graphql.get(`query { stories { id, text } }`).then( stories => { // A list of story items: @@ -39,7 +36,6 @@ graphql.get(`query { stories { id, text } }`).then( console.log(stories); } ); - ``` So far we're just using GraphQL as a more efficient version of typical REST approaches. Note two important benefits in the GraphQL version: @@ -56,7 +52,6 @@ Repeatedly refetching information from the server can get quite slow. For exampl In a resource-oriented REST system, we can maintain a **response cache** based on URIs: ```javascript - var _cache = new Map(); rest.get = uri => { if (!_cache.has(uri)) { @@ -64,13 +59,11 @@ rest.get = uri => { } return _cache.get(uri); }; - ``` Response-caching can also be applied to GraphQL. A basic approach would work similarly to the REST version. The text of the query itself can be used as a cache key: ```javascript - var _cache = new Map(); graphql.get = queryText => { if (!_cache.has(queryText)) { @@ -78,7 +71,6 @@ graphql.get = queryText => { } return _cache.get(queryText); }; - ``` Now, requests for previously cached data can be answered immediately without making a network request. This is a practical approach to improving the perceived performance of an application. However, this method of caching can cause problems with data consistency. @@ -90,7 +82,6 @@ With GraphQL it is very common for the results of multiple queries to overlap. H ``` query { stories { id, text, likeCount } } - ``` and then later refetch one of the stories whose `likeCount` has since been incremented: @@ -98,7 +89,6 @@ and then later refetch one of the stories whose `likeCount` has since been incre ``` query { story(id: "123") { id, text, likeCount } } - ``` We'll now see different `likeCount`s depending on how the story is accessed. A view that uses the first query will see an outdated count, while a view using the second query will see the updated count. @@ -119,7 +109,6 @@ query { } } } - ``` And here's a possible response: @@ -134,13 +123,11 @@ query: { } } } - ``` Although the response is hierarchical, we'll cache it by flattening all the records. Here is an example of how Relay would cache this query response: ```javascript - Map { // `story(id: "1")` 1: Map { @@ -152,7 +139,6 @@ Map { name: 'Jan', }, }; - ``` This is only a simple example: in reality the cache must handle one-to-many associations and pagination (among other things). @@ -182,7 +168,6 @@ The first query was for a list of stories: ``` query { stories { id, text, likeCount } } - ``` With a normalized response cache, a record would be created for each story in the list. The `stories` field would store links to each of these records. @@ -192,7 +177,6 @@ The second query refetched the information for one of those stories: ``` query { story(id: "123") { id, text, likeCount } } - ``` When this response is normalized, Relay can detect that this result overlaps with existing data based on its `id`. Rather than create a new record, Relay will update the existing `123` record. The new `likeCount` is therefore available to _both_ queries, as well as any other query that might reference this story. @@ -215,7 +199,6 @@ query { } } } - ``` After initially fetching this story our cache might be as follows. Note that the story and comment both link to the same record as `author`: @@ -242,7 +225,6 @@ Map { author: Link(2), }, } - ``` The author of this story also commented on it — quite common. Now imagine that some other view fetches new information about the author, and her profile photo has changed to a new URI. Here's the _only_ part of our cached data that changes: @@ -256,7 +238,6 @@ Map { photo: 'http://.../photo2.jpg', }, } - ``` The value of the `photo` field has changed; and therefore the record `2` has also changed. And that's it. Nothing else in the _cache_ is affected. But clearly our _view_ needs to reflect the update: both instances of the author in the UI (as story author and comment author) need to show the new photo. @@ -273,7 +254,6 @@ ImmutableMap { }, 3: ImmutableMap // same as before } - ``` If we replace `2` with a new immutable record, we'll also get a new immutable instance of the cache object. However, records `1` and `3` are untouched. Because the data is normalized, we can't tell that `story`'s contents have changed just by looking at the `story` record alone. @@ -299,7 +279,6 @@ mutation StoryLike($storyID: String) { likeCount } } - ``` Notice that we're querying for data that _may_ have changed as a result of the mutation. An obvious question is: why can't the server just tell us what changed? The answer is: it's complicated. GraphQL abstracts over _any_ data storage layer (or an aggregation of multiple sources), and works with any programming language. Furthermore, the goal of GraphQL is to provide data in a form that is useful to product developers building a view. diff --git a/website/versioned_docs/version-v2.0.0/PrinciplesAndArchitecture-ThinkingInRelay.md b/website/versioned_docs/version-v2.0.0/PrinciplesAndArchitecture-ThinkingInRelay.md index d6f1572d5590b..4fb68372ec4b3 100644 --- a/website/versioned_docs/version-v2.0.0/PrinciplesAndArchitecture-ThinkingInRelay.md +++ b/website/versioned_docs/version-v2.0.0/PrinciplesAndArchitecture-ThinkingInRelay.md @@ -30,13 +30,11 @@ fragment Story_story on Story { photo } } - ``` And this fragment can then be used to define the Story container: ```javascript - const {createFragmentContainer, graphql} = require('react-relay'); // Plain React component. @@ -64,7 +62,6 @@ const StoryContainer = createFragmentContainer(Story, { In React, rendering a view requires two inputs: the _component_ to render, and a _root_ DOM (UI) node to render into. Rendering Relay containers is similar: we need a _container_ to render, and a _root_ in the graph from which to start our query. We also must ensure that the queries for the container are executed and may want to show a loading indicator while data is being fetched. Similar to `ReactDOM.render(component, domNode)`, Relay provides `` for this purpose. The `query` and `variables` define what data to fetch and `render` defines what to render. Here's how we might render ``: ```javascript - ReactDOM.render( { ); } } - ``` The above code is doing something very similar to our [previous example](#rendering-graphql-queries). However, we are now passing a `$userID` variable to the GraphQL query via the `variables` prop. This has a couple of important implications: @@ -229,7 +217,6 @@ Now that we know how to define and fetch queries, let's actually start building First, let's start at the bottom. Suppose that we want to render a component that simply displays a given todo item's text and completed state: ```javascript - // Todo.js import React from 'react'; @@ -259,7 +246,6 @@ export default class Todo extends React.Component { ); } } - ``` From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L107), we know that we can query this data on the `Todo` type. However, we don't want to have to send a separate query for each todo item; that would defeat the purpose of using GraphQL over a traditional REST API. We could manually query for these fields directly in our `QueryRenderer` query, but that would hurt re-usability: what if we want to query the same set of fields as part of a different query? Additionally, we wouldn't know which component needs the data we're querying, which is a problem Relay directly tries to address. @@ -267,18 +253,15 @@ From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/dat Instead, we can define a reusable [Fragment](http://graphql.org/learn/queries/#fragments), which allows us to define a set of fields on a type and reuse them within our queries wherever we need to: ```graphql - fragment TodoItemFragment on Todo { complete text } - ``` Our component can then use this fragment to declare its data dependency on the `Todo` GraphQL type: ```javascript - // Todo.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -338,7 +321,6 @@ Before proceeding, don't forget to run the Relay Compiler with `yarn relay`. Given that [Fragment Containers](./fragment-container) are just React components, we can compose them as such. We can even re-use fragment containers within other fragment containers. As an example, let's see how we would define a `TodoList` component that just renders a list of todo items, and whether all have been completed or not: ```javascript - // TodoList.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -397,7 +379,6 @@ export default createFragmentContainer( } `, ); - ``` As with the first fragment container we defined, `TodoList` declares it's data dependencies via a fragment. However, this component additionally re-uses the fragment previously defined by the `Todo` component, and passes the appropriate data when rendering the child `Todo` components (a.k.a. fragment containers). @@ -412,7 +393,6 @@ fragment containers do not directly fetch data. Instead, containers declare a sp A `QueryRenderer` rendering these fragment containers could look like the following: ```javascript - // ViewerTodoList.js import React from 'react'; import PropTypes from 'prop-types'; @@ -454,7 +434,6 @@ export default class ViewerTodoList extends React.Component { ); } } - ``` Check out our docs for [Fragment Containers](./fragment-container) for more details, and our guides on [Refetch](./refetch-container) and [Pagination](./pagination-container) for more advanced usage of containers. @@ -466,7 +445,6 @@ Now that we know how to query for and render data, let's move on to changing our From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L35), we know that we have some mutations available to us, so let's start by writing a mutation to change the `complete` status of a given todo item (i.e. mark or unmark it as done): ```graphql - mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { changeTodoStatus(input: $input) { todo { @@ -475,7 +453,6 @@ mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { } } } - ``` This mutation allows us to query back some data as a [result of the mutation](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L18), so we're going to query for the updated `complete` status on the todo item. @@ -483,7 +460,6 @@ This mutation allows us to query back some data as a [result of the mutation](ht In order to execute this mutation in Relay, we're going to write a new mutation using Relay's `commitMutation` api: ```javascript - // ChangeTodoStatusMutation.js import {graphql, commitMutation} from 'react-relay'; @@ -517,7 +493,6 @@ function commit( } export default {commit}; - ``` Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mutation to the server and, in our case, upon receiving a response it will automatically update the local data store with the latest data from the server. This also means that upon receiving the response, Relay will ensure that any components (i.e. containers) that depend on the updated data are re-rendered. @@ -525,7 +500,6 @@ Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mut In order to actually use this mutation in our component, we could update our `Todo` component in the following way: ```javascript - // Todo.js // ... @@ -559,7 +533,6 @@ In order to make the experience better, we can configure our mutation to do an o In Relay, there's a couple of options we can pass to `commitMutation` to enable optimistic updates. Let's see what that would look like in our `ChangeTodoStatusMutation`: ```javascript - // ChangeTodoStatusMutation.js // ... @@ -594,7 +567,6 @@ function commit( } export default {commit}; - ``` In the simplest case above, we just need to pass an `optimisticResponse` option, which should refer to an object having the same shape as the mutation response payload. When we pass this option, Relay will know to immediately update our local data with the optimistic response, and then update it with the actual server response or roll it back if an error occurs. diff --git a/website/versioned_docs/version-v3.0.0/Modern-ConvertingMutations.md b/website/versioned_docs/version-v3.0.0/Modern-ConvertingMutations.md index 08ad2e998cb2d..8f4bdc1d8e0d2 100644 --- a/website/versioned_docs/version-v3.0.0/Modern-ConvertingMutations.md +++ b/website/versioned_docs/version-v3.0.0/Modern-ConvertingMutations.md @@ -12,19 +12,16 @@ FatQueries in Relay Classic mutations was a concept that was confusing for a num Example of existing fat query: ```javascript - RelayClassic.QL` fragment on MarkReadNotificationResponsePayload @relay(pattern: true) { notification } `; - ``` Example of converted mutation query: ```javascript - graphql` mutation MarkReadNotificationMutation( $input: MarkReadNotificationData! @@ -37,7 +34,6 @@ graphql` } } `; - ``` ## Migrating Configs @@ -67,7 +63,6 @@ This is no longer needed in Compatibility Mode for neither environments. Simply Take this example of a simple mutation in Relay Classic: ```javascript - class LikeStoryMutation extends RelayClassic.Mutation { getMutation() { return RelayClassic.QL`mutation {likeStory}`; @@ -106,7 +101,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { `, }; } - ``` ### Converting `getMutation()` and `getFatQuery()` @@ -114,7 +108,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { We combine these two into a regular GraphQL mutation, which list out specific fields that needs to be updated. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story(data: $input) { @@ -126,7 +119,6 @@ const mutation = graphql` } } `; - ``` ### Converting `getConfigs()` @@ -138,13 +130,11 @@ As specified above, `FIELDS_CHANGE` configs can be omitted. To convert `getVariables()`, we take the return value from the original function and wrap it in an object that contains a property that matches the variable name for the mutation. In this case, the mutation has a `input` variable that is of type `LikeStoryData`. ```javascript - const variables = { input: { storyID: args.storyID } } - ``` ### Final Result @@ -152,7 +142,6 @@ const variables = { As you can see, our resulting mutation is a lot simpler and more like regular GraphQL than the Relay Classic version we started out with. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story { @@ -178,7 +167,6 @@ function commit(environment: CompatEnvironment, args) { variables, }); } - ``` See [Mutation](./mutations) for additional options on `commitMutation` for more complex mutations. diff --git a/website/versioned_docs/version-v3.0.0/Modern-FragmentContainer.md b/website/versioned_docs/version-v3.0.0/Modern-FragmentContainer.md index e86b79995c1c7..7bbd0a9f22899 100644 --- a/website/versioned_docs/version-v3.0.0/Modern-FragmentContainer.md +++ b/website/versioned_docs/version-v3.0.0/Modern-FragmentContainer.md @@ -17,12 +17,10 @@ Table of Contents: `createFragmentContainer` has the following signature: ```javascript - createFragmentContainer( component: ReactComponentClass, fragmentSpec: GraphQLTaggedNode | {[string]: GraphQLTaggedNode}, ): ReactComponentClass; - ``` ### Arguments @@ -46,7 +44,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -61,7 +58,6 @@ To start, let's build the plain React version of a hypothetical `` c Here's a basic implementation of `` that ignores styling in order to highlight the functionality: ```javascript - // TodoItem.js class TodoItem extends React.Component { render() { @@ -81,7 +77,6 @@ class TodoItem extends React.Component { ); } } - ``` ### Data Dependencies With GraphQL @@ -89,7 +84,6 @@ class TodoItem extends React.Component { In Relay, data dependencies are described using [GraphQL](https://github.com/facebook/graphql). For ``, the dependency can be expressed as follows. Note that this exactly matches the shape that the component expected for the `item` prop. ```javascript - graphql` # This fragment only applies to objects of type 'Todo'. fragment TodoItem_item on Todo { @@ -105,7 +99,6 @@ graphql` Given the plain React component and a GraphQL fragment, we can now define a Fragment Container to specify this component's data requirements. Let's look at the code first and then see what's happening: ```javascript - // TodoItem.js import {createFragmentContainer, graphql} from 'react-relay'; @@ -123,13 +116,11 @@ export default createFragmentContainer(TodoItem, { } `, }); - ``` Relay will infer the prop name from the fragment name according to the fragment naming convention `<...>_`. The example below is equivalent to the one above: ```javascript - export default createFragmentContainer( TodoItem, graphql` @@ -139,13 +130,11 @@ export default createFragmentContainer( } `, ); - ``` If there is no `_` suffix, the `data` prop name will be used: ```javascript - class TodoItem extends React.Component { render() { const item = this.props.data; @@ -162,7 +151,6 @@ export default createFragmentContainer( } `, ); - ``` ## Container Composition @@ -176,7 +164,6 @@ Let's explore how this works via a `` component that composes the `< View composition is _exactly_ what you're used to — Relay containers are just standard React components. Here's the `` component: ```javascript - class TodoList extends React.Component { render() { // Expects a `list` with a string `title`, as well as the information @@ -191,7 +178,6 @@ class TodoList extends React.Component { ); } } - ``` ### Composing Fragments @@ -199,7 +185,6 @@ class TodoList extends React.Component { Fragment composition works similarly — a parent container's fragment composes the fragment for each of its children. In this case, `` needs to fetch information about the `Todo`s that are required by ``. ```javascript - class TodoList extends React.Component // as above export default createFragmentContainer( @@ -217,7 +202,6 @@ export default createFragmentContainer( } `, ); - ``` Note that when composing fragments, the type of the composed fragment must match the field on the parent in which it is embedded. For example, it wouldn't make sense to embed a fragment of type `Story` into a parent's field of type `User`. Relay and GraphQL will provide helpful error messages if you get this wrong (and if they aren't helpful, let us know!). @@ -231,7 +215,6 @@ When defining a fragment, you can use the [`@argumentDefinitions`](./graphql-in- For example, let's redefine our `TodoList_list` fragment to take some arguments using `@argumentDefinitions`: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -241,7 +224,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` Any arguments defined inside `@argumentDefinitions` will be local variables available inside the fragment's scope. However, a fragment can also reference global variables that were defined in the root query. @@ -253,11 +235,9 @@ In order to pass arguments to a fragment that has `@argumentDefinitions`, you ne Following our `TodoList_list` example, we would pass arguments to the fragment like so: ```graphql - query TodoListQuery($count: Int, $userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` ### Calling Component Instance Methods @@ -268,7 +248,6 @@ Since Relay composes these component instances in a container, you need to use t Consider an input with a server-defined placeholder text and an imperative method to focus the input node: ```javascript - export default createFragmentContainer( class TodoInput extends React.Component { focus() { @@ -288,13 +267,11 @@ export default createFragmentContainer( } `, ); - ``` To call this method on the underlying component, first provide a `componentRef` function to the Relay container. This differs from providing a [`ref`](https://facebook.github.io/react/docs/refs-and-the-dom.html) function which would provide a reference to the Relay container itself, not the underlying React Component. ```javascript - export default createFragmentContainer( class TodoListView extends React.Component { render() { @@ -312,7 +289,6 @@ export default createFragmentContainer( } `, ); - ``` ## Rendering Containers diff --git a/website/versioned_docs/version-v3.0.0/Modern-GraphQLInRelay.md b/website/versioned_docs/version-v3.0.0/Modern-GraphQLInRelay.md index 18692b0d01784..6e544e33d2d13 100644 --- a/website/versioned_docs/version-v3.0.0/Modern-GraphQLInRelay.md +++ b/website/versioned_docs/version-v3.0.0/Modern-GraphQLInRelay.md @@ -14,7 +14,6 @@ Table of Contents: The `graphql` template tag provided by Relay serves as the mechanism to write queries, fragments, mutations or subscriptions in the [GraphQL](http://graphql.org/learn/) language. For example: ```javascript - import {graphql} from 'react-relay'; graphql` @@ -24,7 +23,6 @@ graphql` } } `; - ``` The result of using the `graphql` template tag is a `GraphQLTaggedNode`; a runtime representation of the GraphQL document which can be used to define [Query Renderers](./query-renderer), [Fragment Containers](./fragment-container), [Refetch Containers](./refetch-container), [Pagination Containers](./pagination-container), etc. @@ -42,11 +40,9 @@ Relay uses directives to add additional information to GraphQL documents, which `@arguments` is a directive used to pass arguments to a fragment that was defined using [`@argumentDefinitions`](#argumentdefinitions). For example: ```graphql - query TodoListQuery($userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -56,7 +52,6 @@ See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fr `@argumentDefinitions` is a directive used to specify arguments taken by a fragment. For example: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -66,7 +61,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -82,7 +76,6 @@ When using the [Pagination Container](./pagination-container), Relay expects con When defining a fragment for use with a Fragment container, you can use the `@relay(plural: true)` directive to indicate that container expects the prop for that fragment to be a list of items instead of a single item. A query or parent that spreads a `@relay(plural: true)` fragment should do so within a plural field (ie a field backed by a [GraphQL list](http://graphql.org/learn/schema/#lists-and-non-null). For example: ```javascript - // Plural fragment definition graphql` fragment TodoItems_items on TodoItem @relay(plural: true) { @@ -97,7 +90,6 @@ fragment TodoApp_app on App { ...TodoItem_items } } - ``` ### `@relay(mask: Boolean)` @@ -115,7 +107,6 @@ Keep in mind that it is typically considered an **anti-pattern** to create a sin In the example below, the `user` prop will include the data for `id` and `name` fields wherever `...Component_internUser` is included, instead of Relay's normal behavior to mask those fields: ```javascript - graphql` fragment Component_internUser on InternUser @relay(mask: false) { id @@ -143,7 +134,6 @@ export default createFragmentContainer( } `, ); - ``` ## Relay Compiler @@ -153,7 +143,6 @@ Relay uses the Relay Compiler to convert [`graphql`](#graphql) literals into gen A query like the following: ```javascript - graphql` fragment MyComponent on Type { field @@ -174,12 +163,10 @@ Relay Compiler supports the use of **persisted queries**, in which each version Persisted queries can be enabled by instructing Relay Compiler to emit metadata about each query, mutation, and subscription into a JSON file. The generated file will contain a mapping of query identifiers to query text, which you can then save to your server. To enable persisted queries, use the `--persist-output` flag to the compiler: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` Relay Compiler will then create the id => query text mapping in the path you specify. You can then use this complete @@ -196,7 +183,6 @@ See our relay-compiler section in our [Installation and Setup guide](./installat To use the Relay Compiler, you need either a .graphql or .json GraphQL schema file, describing your GraphQL server's API. Typically these files are local representations of a server source of truth and are not edited directly. For example, we might have a `schema.graphql` like: ```graphql - schema { query: Root } @@ -214,7 +200,6 @@ type WordDefinition { text: String image: String } - ``` ### Source files @@ -230,7 +215,6 @@ For example, given the two files: - `src/Components/DictionaryComponent.js` ```javascript - const DictionaryWordFragment = graphql` fragment DictionaryComponent_word on Word { id @@ -252,7 +236,6 @@ For example, given the two files: - `src/Queries/DictionaryQuery.js` ```javascript - const DictionaryQuery = graphql` query DictionaryQuery { dictionary { @@ -276,9 +259,7 @@ Typically you will not need to import your generated definitions. The [Relay Bab However the Relay Compiler also automatically generates [Flow](https://flow.org) types as [type comments](https://flow.org/en/docs/types/comments/). For example, you can import the generated Flow types like so: ```javascript - import type {DictionaryComponent_word} from './__generated__/DictionaryComponent_word.graphql'; - ``` ### Advanced usage diff --git a/website/versioned_docs/version-v3.0.0/Modern-LocalStateManagement.md b/website/versioned_docs/version-v3.0.0/Modern-LocalStateManagement.md index f3427f392a611..dc50079ca5fbe 100644 --- a/website/versioned_docs/version-v3.0.0/Modern-LocalStateManagement.md +++ b/website/versioned_docs/version-v3.0.0/Modern-LocalStateManagement.md @@ -23,23 +23,19 @@ It can even be used to extend an existing server schema. For example, we can create a new type called `Note`: ```graphql - type Note { id: ID! title: String body: String } - ``` And then extend the server schema type `User`, with a list of `Note`, called `notes`. ```graphql - extend type User { notes: [Note] } - ``` ## Querying local state @@ -50,7 +46,6 @@ The field can be from the server schema, or it can be schema agnostic, like an i Here, we use a [QueryRenderer](./query-renderer) to get the current `User` via the `viewer` field, along with their id, name and the local list of notes. ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -96,7 +91,6 @@ const Example = (props) => { /> ); } - ``` ## Mutating local state @@ -110,7 +104,6 @@ To build upon the previous example, let's try creating, updating and deleting a ### Create ```javascript - import {commitLocalUpdate} from 'react-relay'; let tempID = 0; @@ -130,7 +123,6 @@ function createUserNote() { user.setLinkedRecords([...userNoteRecords, newNoteRecord], 'notes'); }); } - ``` Note that since this record will be rendered by the `ExampleQuery` in our `QueryRenderer`, the QueryRenderer will automatically retain this data so it isn't garbage collected. @@ -138,7 +130,6 @@ Note that since this record will be rendered by the `ExampleQuery` in our `Query If no component is rendering the local data and you want to manually retain it, you can do so by calling `environment.retain()`: ```javascript - import {createOperationDescriptor, getRequest} from 'relay-runtime'; // Create a query that references that record @@ -165,13 +156,11 @@ const disposable = environment.retain(operation); // Whenever you don't need that data anymore and it's okay for Relay to garbage collect it, // you can dispose of the retain disposable.dispose(); - ``` ### Update ```javascript - import {commitLocalUpdate} from 'react-relay'; function updateUserNote(dataID, body, title) { @@ -182,13 +171,11 @@ function updateUserNote(dataID, body, title) { note.setValue(title, 'title') }); } - ``` ### Delete ```javascript - import {commitLocalUpdate} from 'react-relay'; function deleteUserNote(dataID) { @@ -206,7 +193,6 @@ function deleteUserNote(dataID) { user.setLinkedRecords(newUserNoteRecords, 'notes'); }); } - ``` ## Initial local state @@ -215,7 +201,6 @@ All new client-side schema fields default to `undefined` value. Often however, y You can use an updater function via `commitLocalUpdate` to prime local state. ```javascript - import {commitLocalUpdate} from 'react-relay'; commitLocalUpdate(environment, store => { @@ -224,5 +209,4 @@ commitLocalUpdate(environment, store => { // initialize user notes to an empty array. user.setLinkedRecords([], 'notes'); }); - ``` diff --git a/website/versioned_docs/version-v3.0.0/Modern-MigrationSetup.md b/website/versioned_docs/version-v3.0.0/Modern-MigrationSetup.md index 66f1145357e25..a89c0e178e0e5 100644 --- a/website/versioned_docs/version-v3.0.0/Modern-MigrationSetup.md +++ b/website/versioned_docs/version-v3.0.0/Modern-MigrationSetup.md @@ -13,13 +13,11 @@ With some additional configuration, the `"relay"` babel plugin can also translat Relay Classic `Relay.QL` literals. Most importantly, include a reference to your GraphQL Schema as either a json file or graphql schema file. ```javascript - { "plugins": [ ["relay", {"schema": "path/schema.graphql"}] ] } - ``` ## Set up babel-plugin-relay for "[compatibility mode](./relay-compat)" @@ -29,13 +27,11 @@ literals can be translated to be usable by _both_ runtimes if configured to use compatibility mode: ```javascript - { "plugins": [ ["relay", {"compat": true, "schema": "path/schema.graphql"}] ] } - ``` ## Additional Options @@ -47,7 +43,6 @@ thrown at runtime. When compiling code for production deployment, the plugin can be configured to immediately throw upon encountering a validation problem. The plugin can be further customized for different environments with the following options: ```javascript - { "plugins": [ ["relay", { @@ -56,5 +51,4 @@ When compiling code for production deployment, the plugin can be configured to i }] ] } - ``` diff --git a/website/versioned_docs/version-v3.0.0/Modern-Mutations.md b/website/versioned_docs/version-v3.0.0/Modern-Mutations.md index 2285d7a90be70..198060f21cb03 100644 --- a/website/versioned_docs/version-v3.0.0/Modern-Mutations.md +++ b/website/versioned_docs/version-v3.0.0/Modern-Mutations.md @@ -17,7 +17,6 @@ Table of Contents: Use `commitMutation` to create and execute mutations. `commitMutation` has the following signature: ```javascript - commitMutation( environment: Environment, config: { @@ -31,7 +30,6 @@ commitMutation( configs?: Array, }, ); - ``` ### Arguments @@ -58,7 +56,6 @@ commitMutation( Example of a simple mutation: ```javascript - import {commitMutation, graphql} from 'react-relay'; const mutation = graphql` @@ -93,7 +90,6 @@ function markNotificationAsRead(environment, source, storyID) { }, ); } - ``` ## Optimistic Updates @@ -101,7 +97,6 @@ function markNotificationAsRead(environment, source, storyID) { To improve perceived responsiveness, you may wish to perform an "optimistic update", in which the client immediately updates to reflect the anticipated new value even before the response from the server has come back. The simplest way to do this is by providing an `optimisticResponse` and adding it to the `config` that we pass into `commitMutation`: ```javascript - const mutation = graphql` mutation MarkReadNotificationMutation( $input: MarkReadNotificationInput! @@ -130,7 +125,6 @@ commitMutation( variables, }, ); - ``` Another way to enable optimistic updates is via the `optimisticUpdater`, which can be used for more complicated update scenarios. Using `optimisticUpdater` is covered in the section [below](#using-updater-and-optimisticupdater). @@ -152,7 +146,6 @@ Given a deletedIDFieldName, Relay will remove the node(s) from the store. #### Example ```javascript - const mutation = graphql` mutation DestroyShipMutation($input: DestroyShipInput!) { destroyShip(input: $input) { @@ -170,7 +163,6 @@ const configs = [{ type: 'NODE_DELETE', deletedIDFieldName: 'destroyedShipId', }]; - ``` ### RANGE_ADD @@ -190,7 +182,6 @@ Given a parent, information about the connection, and the name of the newly crea #### Example ```javascript - const mutation = graphql` mutation AddShipMutation($input: AddShipInput!) { addShip(input: $input) { @@ -220,7 +211,6 @@ function commit(environment, factionId, name) { }], }); } - ``` ### RANGE_DELETE @@ -242,7 +232,6 @@ from the connection but leave the associated record(s) in the store. #### Example ```javascript - const mutation = graphql` mutation RemoveTagMutation($input: RemoveTagInput!) { removeTag(input: $input) { @@ -268,7 +257,6 @@ function commit(environment, todoId, tagId) { }], }); } - ``` ## Using updater and optimisticUpdater @@ -286,7 +274,6 @@ When you provide these functions, this is roughly what happens during the mutati Here are a quick example of adding a todo item to a Todo list using this [example schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L36): ```javascript - // AddTodoMutation.js import {commitMutation, graphql} from 'react-relay'; import {ConnectionHandler} from 'relay-runtime'; @@ -373,7 +360,6 @@ function commit(environment, text, user) { }, }); } - ``` For details on how to interact with the Relay Store, please refer to our Relay Store [docs](./relay-store). diff --git a/website/versioned_docs/version-v3.0.0/Modern-NetworkLayer.md b/website/versioned_docs/version-v3.0.0/Modern-NetworkLayer.md index fcd9fd4dd5e03..daa8c71294c59 100644 --- a/website/versioned_docs/version-v3.0.0/Modern-NetworkLayer.md +++ b/website/versioned_docs/version-v3.0.0/Modern-NetworkLayer.md @@ -8,7 +8,6 @@ In order to know how to access your GraphQL server, Relay Modern requires develo Currently the easiest way to create a network layer is via a helper from the `relay-runtime` package: ```javascript - import { Environment, Network, @@ -50,7 +49,6 @@ const environment = new Environment({ }); export default environment; - ``` Note that this is a basic example to help you get started. This example could be extended with additional features such as request/response caching (enabled e.g. when `cacheConfig.force` is false) and uploading form data for mutations (the `uploadables` parameter). @@ -62,7 +60,6 @@ Relay modern makes no assumptions about what to cache and will garbage collect a You have to implement your own cache strategy. A simple solution is to use `RelayQueryResponseCache`(an in-memory cache): ```javascript - import { Environment, Network, @@ -126,7 +123,6 @@ const environment = new Environment({ }); export default environment; - ``` ## Custom open-source implementations diff --git a/website/versioned_docs/version-v3.0.0/Modern-PaginationContainer.md b/website/versioned_docs/version-v3.0.0/Modern-PaginationContainer.md index e17127d79bb52..818a870d5fe63 100644 --- a/website/versioned_docs/version-v3.0.0/Modern-PaginationContainer.md +++ b/website/versioned_docs/version-v3.0.0/Modern-PaginationContainer.md @@ -24,7 +24,6 @@ However, when [specifying connection fragments](#createpaginationcontainer) for The purpose of the `@connection` directive is to allow Relay to uniquely identify different connections under a parent type. The `@connection` directive takes 2 arguments that help identify the connection: ```graphql - @connection(key: String!, filters: [String]) ``` @@ -37,7 +36,6 @@ The purpose of the `@connection` directive is to allow Relay to uniquely identif Specifying just the `key`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and the value of `$orderBy` (given that no `filters` were provided) @@ -53,13 +51,11 @@ fragment Feed_user on User { } } } - ``` Specifying `key` and `filters`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and /only/ the value of `$searchTerm`, i.e. @@ -77,7 +73,6 @@ fragment Feed_user on User { } } } - ``` ## `createPaginationContainer` @@ -85,7 +80,6 @@ fragment Feed_user on User { `createPaginationContainer` has the following signature: ```javascript - createPaginationContainer( component: ReactComponentClass, fragmentSpec: GraphQLTaggedNode | {[string]: GraphQLTaggedNode}, @@ -113,7 +107,6 @@ type ConnectionData = { startCursor: ?string, }, }; - ``` ### Arguments @@ -137,7 +130,6 @@ type ConnectionData = { The Component resulting from `createPaginationContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -148,7 +140,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -163,7 +154,6 @@ type Props = { `hasMore` is a function available on the `relay` [prop](#available-props). This function indicates whether there are more pages to fetch from the server or not. ```javascript - hasMore: () => boolean, ``` @@ -173,7 +163,6 @@ hasMore: () => boolean, `isLoading` is a function available on the `relay` [prop](#available-props). This function indicates if a previous call to [`loadMore()`](#loadmore) is still pending. This is convenient for avoiding duplicate load calls. ```javascript - isLoading: () => boolean, ``` @@ -183,7 +172,6 @@ isLoading: () => boolean, `loadMore` is a function available on the `relay` [prop](#available-props). You can call `loadMore()` to fetch more items from the server based on the `connectionConfig` provided to the container. This will return null if there are no more items to fetch, otherwise it will fetch more items and return a Disposable that can be used to cancel the fetch. ```javascript - loadMore(pageSize: number, callback: ?(error: ?Error) => void): ?Disposable ``` @@ -198,7 +186,6 @@ loadMore(pageSize: number, callback: ?(error: ?Error) => void): ?Disposable `refetchConnection` is a function available on the `relay` [prop](#available-props). You can call `refetchConnection` to restart pagination on a connection from scratch, with optionally a completely new set of variables to pass to the pagination `query`. This is useful for example if you are paginating over a collection based on a userID and the userID changes, you'd want to start paginating over the new collection for the new user. ```javascript - refetchConnection:( totalCount: number, callback: (error: ?Error) => void, @@ -216,7 +203,6 @@ refetchConnection:( ## Pagination Example ```javascript - // Feed.js import {createPaginationContainer, graphql} from 'react-relay'; @@ -311,5 +297,4 @@ module.exports = createPaginationContainer( ` } ); - ``` diff --git a/website/versioned_docs/version-v3.0.0/Modern-PersistedQueries.md b/website/versioned_docs/version-v3.0.0/Modern-PersistedQueries.md index 137cc2e23220c..ec03b69ba09c3 100644 --- a/website/versioned_docs/version-v3.0.0/Modern-PersistedQueries.md +++ b/website/versioned_docs/version-v3.0.0/Modern-PersistedQueries.md @@ -17,12 +17,10 @@ The relay compiler supports persisted queries which is useful because: In your `npm` script in `package.json`, run the relay compiler using the `--persist-output` flag: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` The `--persist-ouput` flag does 3 things: @@ -31,8 +29,7 @@ The `--persist-ouput` flag does 3 things: For example without `--persist-output`, a generated `ConcreteRequest` might look like below: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -49,8 +46,7 @@ The `--persist-ouput` flag does 3 things: With `--persist-output ` this becomes: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -68,12 +64,10 @@ The `--persist-ouput` flag does 3 things: 2. It generates a JSON file at the `` you specify containing a mapping from query ids to the corresponding operation texts. -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./src/queryMaps/queryMap.json" } - ``` The example above writes the complete query map file to `./src/queryMaps/queryMap.json`. You need to ensure all the directories @@ -83,8 +77,7 @@ leading to the `queryMap.json` file exist. You'll need to modify your network layer fetch implementation to pass a documentId parameter in the POST body instead of a query parameter: -```js - +```javascript function fetchQuery(operation, variables,) { return fetch('/graphql', { method: 'POST', @@ -100,7 +93,6 @@ function fetchQuery(operation, variables,) { return response.json(); }); } - ``` ## Executing Persisted Queries on the Server @@ -116,13 +108,11 @@ the query map file in a common location accessible to both the client and the se For applications where the client and server projects are separate, one option is to have an additional npm run script to push the query map at compile time to a location accessible by your server: -```js - +```javascript "scripts": { "push-queries": "node ./pushQueries.js", "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-ouput && npm run push-queries" } - ``` Some possibilities of what you can do in `./pushQueries.js`: @@ -146,8 +136,7 @@ database technologies you use, so we'll just cover the most common and basic exa If you use `express-graphql` and have access to the query map file, you can import the `--persist-output` JSON file directly and perform the matching using the `matchQueryMiddleware` from [relay-compiler-plus](https://github.com/yusinto/relay-compiler-plus). -```js - +```javascript import Express from 'express'; import expressGraphql from 'express-graphql'; import {matchQueryMiddleware} from 'relay-compiler-plus'; @@ -158,7 +147,6 @@ const app = Express(); app.use('/graphql', matchQueryMiddleware(queryMapJson), expressGraphql({schema})); - ``` ## Using `--persist-output` and `--watch` diff --git a/website/versioned_docs/version-v3.0.0/Modern-QueryRenderer.md b/website/versioned_docs/version-v3.0.0/Modern-QueryRenderer.md index 8787283987b82..4259a7a543545 100644 --- a/website/versioned_docs/version-v3.0.0/Modern-QueryRenderer.md +++ b/website/versioned_docs/version-v3.0.0/Modern-QueryRenderer.md @@ -23,7 +23,6 @@ However, a `QueryRenderer` will not start loading its data until it is mounted, ## Example ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -55,5 +54,4 @@ class Example extends React.Component { ); } } - ``` diff --git a/website/versioned_docs/version-v3.0.0/Modern-RefetchContainer.md b/website/versioned_docs/version-v3.0.0/Modern-RefetchContainer.md index 930b460e80f54..d33fc948d775c 100644 --- a/website/versioned_docs/version-v3.0.0/Modern-RefetchContainer.md +++ b/website/versioned_docs/version-v3.0.0/Modern-RefetchContainer.md @@ -16,13 +16,11 @@ Table of Contents: `createRefetchContainer` has the following signature: ```javascript - createRefetchContainer( component: ReactComponentClass, fragmentSpec: GraphQLTaggedNode | {[string]: GraphQLTaggedNode}, refetchQuery: GraphQLTaggedNode, ): ReactComponentClass; - ``` ### Arguments @@ -40,7 +38,6 @@ createRefetchContainer( The Component resulting from `createRefetchContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -48,7 +45,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -64,7 +60,6 @@ type Props = { `refetch` has the following signature: ```javascript - type RefetchOptions = { force?: boolean, }; @@ -104,7 +99,6 @@ Returns a `Disposable` on which you could call `dispose()` to cancel the refetch In this simple example, let's assume we want to fetch the latest data for a `TodoItem` from the server: ```javascript - // TodoItem.js import {createRefetchContainer, graphql} from 'react-relay'; @@ -148,7 +142,6 @@ export default createRefetchContainer( } ` ); - ``` ### Loading more data @@ -156,7 +149,6 @@ export default createRefetchContainer( In this example we are using a Refetch Container to fetch more stories in a story feed component. ```javascript - import {createRefetchContainer, graphql} from 'react-relay'; class FeedStories extends React.Component { @@ -212,5 +204,4 @@ export default createRefetchContainer( } `, ); - ``` diff --git a/website/versioned_docs/version-v3.0.0/Modern-RelayCompat.md b/website/versioned_docs/version-v3.0.0/Modern-RelayCompat.md index 36632d3a8f1a1..f47dbd845ba3e 100644 --- a/website/versioned_docs/version-v3.0.0/Modern-RelayCompat.md +++ b/website/versioned_docs/version-v3.0.0/Modern-RelayCompat.md @@ -31,7 +31,6 @@ Relay Modern. The components using Relay Compat can be referred to by both other Relay Modern and Relay Classic components. ```javascript - const {createFragmentContainer, graphql} = require('react-relay/compat'); class TodoItem extends React.Component { @@ -47,5 +46,4 @@ module.exports = createFragmentContainer(TodoItem, graphql` isComplete } `); - ``` diff --git a/website/versioned_docs/version-v3.0.0/Modern-RelayEnvironment.md b/website/versioned_docs/version-v3.0.0/Modern-RelayEnvironment.md index b356b5deecdc5..ed75bc69d1f86 100644 --- a/website/versioned_docs/version-v3.0.0/Modern-RelayEnvironment.md +++ b/website/versioned_docs/version-v3.0.0/Modern-RelayEnvironment.md @@ -12,7 +12,6 @@ Most applications will create a single Environment instance and use it throughou To create an environment instance in Relay Modern, use the `RelayModernEnvironment` class: ```javascript - const { Environment, Network, @@ -30,7 +29,6 @@ const environment = new Environment({ network, store, }); - ``` For more details on creating a Network, see the [NetworkLayer guide](./network-layer). @@ -44,7 +42,6 @@ The example above did not configure a `handlerProvider`, which means that a defa If you wish to provide your own `handlerProvider`, you can do so: ```javascript - const { ConnectionHandler, ViewerHandler, @@ -60,5 +57,4 @@ function handlerProvider(handle) { `handlerProvider: No handler provided for ${handle}` ); } - ``` diff --git a/website/versioned_docs/version-v3.0.0/Modern-RelayStore.md b/website/versioned_docs/version-v3.0.0/Modern-RelayStore.md index 6bdeeb471b64f..4de7abfbecf1d 100644 --- a/website/versioned_docs/version-v3.0.0/Modern-RelayStore.md +++ b/website/versioned_docs/version-v3.0.0/Modern-RelayStore.md @@ -16,7 +16,6 @@ Table of Contents: The `RecordSourceSelectorProxy` is the type of the `store` that [`updater` functions](./mutations#using-updater-and-optimisticupdater) receive as an argument. The following is the `RecordSourceSelectorProxy` interface: ```javascript - interface RecordSourceSelectorProxy { create(dataID: string, typeName: string): RecordProxy; delete(dataID: string): void; @@ -25,7 +24,6 @@ interface RecordSourceSelectorProxy { getRootField(fieldName: string): ?RecordProxy; getPluralRootField(fieldName: string): ?Array; } - ``` ### `create(dataID: string, typeName: string): RecordProxy` @@ -35,9 +33,7 @@ Creates a new record in the store given a `dataID` and the `typeName` as defined #### Example ```javascript - const record = store.create(dataID, 'Todo'); - ``` ### `delete(dataID: string): void` @@ -47,9 +43,7 @@ Deletes a record from the store given its `dataID`. #### Example ```javascript - store.delete(dataID); - ``` ### `get(dataID: string): ?RecordProxy` @@ -59,9 +53,7 @@ Retrieves a record from the store given its `dataID`. Returns a [`RecordProxy`]( #### Example ```javascript - const record = store.get(dataID); - ``` ### `getRoot(): RecordProxy` @@ -73,20 +65,16 @@ Returns the [`RecordProxy`](#recordproxy) representing the root of the GraphQL d Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - // Represents root query const root = store.getRoot(); - ``` ### `getRootField(fieldName: string): ?RecordProxy` @@ -98,19 +86,15 @@ Retrieves a root field from the store given the `fieldName`, as defined by the G Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - const viewer = store.getRootField('viewer'); - ``` ### `getPluralRootField(fieldName: string): ?Array` @@ -122,19 +106,15 @@ Retrieves a root field that represents a collection from the store given the `fi Given the GraphQL document: ```graphql - nodes(first: 10) { # ... } - ``` Usage: ```javascript - const nodes = store.getPluralRootField('nodes'); - ``` ## RecordProxy @@ -142,7 +122,6 @@ const nodes = store.getPluralRootField('nodes'); The `RecordProxy` serves as an interface to mutate records: ```javascript - interface RecordProxy { copyFieldsFrom(sourceRecord: RecordProxy): void; getDataID(): string; @@ -167,7 +146,6 @@ interface RecordProxy { ): RecordProxy; setValue(value: mixed, name: string, arguments?: ?Object): RecordProxy; } - ``` ### `getDataID(): string` @@ -177,9 +155,7 @@ Returns the dataID of the current record. #### Example ```javascript - const id = record.getDataID(); - ``` ### `getType(): string` @@ -189,7 +165,6 @@ Gets the type of the current record, as defined by the GraphQL schema. #### Example ```javascript - const type = user.getType(); // User ``` @@ -203,20 +178,16 @@ Gets the value of a field in the current record given the field name. Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - const name = viewer.getValue('name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. @@ -226,20 +197,16 @@ Optionally, if the field takes arguments, you can pass a bag of `variables`. Given the GraphQL document: ```graphql - viewer { id name(arg: $arg) } - ``` Usage: ```javascript - const name = viewer.getValue('name', {arg: 'value'}); - ``` ### `getLinkedRecord(name: string, arguments?: ?Object): ?RecordProxy` @@ -251,23 +218,19 @@ Retrieves a record associated with the current record given the field name, as d Given the GraphQL document: ```graphql - rootField { viewer { id name } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -277,22 +240,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { viewer(arg: $arg) { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {arg: 'value'}); - ``` ### `getLinkedRecords(name: string, arguments?: ?Object): ?Array` @@ -304,22 +263,18 @@ Retrieves the set of records associated with the current record given the field Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const nodes = rootField.getLinkedRecords('nodes'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -329,22 +284,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { nodes(first: $count) { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {count: 10}); - ``` ### `getOrCreateLinkedRecord(name: string, typeName: string, arguments?: ?Object)` @@ -356,19 +307,16 @@ Retrieves the a record associated with the current record given the field name, Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = rootField.getOrCreateLinkedRecord('viewer', 'User'); // Will create if it doesn't exist @@ -383,28 +331,22 @@ Mutates the current record by setting a new value on the specified field. Return Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - viewer.setValue('New Name', 'name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. ```javascript - viewer.setValue('New Name', 'name', {arg: 'value'}); - ``` ### `copyFieldsFrom(sourceRecord: RecordProxy): void` @@ -414,7 +356,6 @@ Mutates the current record by copying the fields over from the passed in record #### Example ```javascript - const record = store.get(id1); const otherRecord = store.get(id2); record.copyFieldsFrom(otherRecord); // Mutates `record` @@ -430,19 +371,16 @@ Mutates the current record by setting a new linked record on the given the field Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = store.create(/* ... */)'' rootField.setLinkedRecord(newViewer, 'viewer'); // @@ -460,19 +398,16 @@ Mutates the current record by setting a new set of linked records on the given t Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newNode = store.create(/* ... */); const newNodes = [...rootField.getLinkedRecords('nodes'), newNode]; @@ -487,7 +422,6 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl `ConnectionHandler` is a utility module exposed by `relay-runtime` that aids in the manipulation of connections. `ConnectionHandler` exposes the following interface: ```javascript - interface ConnectionHandler { getConnection( record: RecordProxy, @@ -512,7 +446,6 @@ interface ConnectionHandler { ): void, deleteNode(connection: RecordProxy, nodeID: string): void } - ``` ### `getConnection(record: RecordProxy, key: string, filters?: ?Object)` @@ -522,7 +455,6 @@ Given a record and a connection key, and optionally a set of filters, `getConnec First, let's take a look at a plain connection: ```graphql - fragment FriendsFragment on User { friends(first: 10) { edges { @@ -532,26 +464,22 @@ fragment FriendsFragment on User { } } } - ``` Accessing a plain connection field like this is the same as other regular field: ```javascript - // The `friends` connection record can be accessed with: const user = store.get(userID); const friends = user && user.getLinkedRecord(user, 'friends'); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` In a [pagination container](./pagination-container), we usually annotate the actual connection field with `@connection` to tell Relay which part needs to be paginated: ```graphql - fragment FriendsFragment on User { friends(first: 10, orderby: "firstname") @connection( key: "FriendsFragment_friends", @@ -563,7 +491,6 @@ fragment FriendsFragment on User { } } } - ``` For connections like the above, `ConnectionHandler` helps us find the record: @@ -581,7 +508,6 @@ const friends = ConnectionHandler.getConnection( ); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` ### Edge creation and insertion @@ -611,7 +537,6 @@ ConnectionHandler.insertEdgeAfter(friends, edge); // No cursor provided, Insert the edge at the front: ConnectionHandler.insertEdgeBefore(friends, edge); - ``` ### `deleteNode(connection: RecordProxy, nodeID: string): void` @@ -625,5 +550,4 @@ Given a connection, deletes any edges whose id matches the given id. const user = store.get(userID); const friends = ConnectionHandler.getConnection(user, 'friends'); ConnectionHandler.deleteNode(friends, idToDelete); - ``` diff --git a/website/versioned_docs/version-v3.0.0/Modern-Subscriptions.md b/website/versioned_docs/version-v3.0.0/Modern-Subscriptions.md index 3521d610d6bc6..a104adde23e89 100644 --- a/website/versioned_docs/version-v3.0.0/Modern-Subscriptions.md +++ b/website/versioned_docs/version-v3.0.0/Modern-Subscriptions.md @@ -6,7 +6,6 @@ original_id: subscriptions Relay exposes the following APIs to create subscriptions. ```javascript - const {requestSubscription} = require('react-relay'); type Variables = {[name: string]: any}; @@ -27,7 +26,6 @@ requestSubscription( configs?: Array, }, ) => Disposable; - ``` The function returns a `Disposable` on which you could call `dispose()` to cancel the refetch. @@ -53,7 +51,6 @@ appropriate when you are only changing the properties of existing records that can be identified by their `id`: ```javascript - const { requestSubscription, graphql, @@ -87,7 +84,6 @@ requestSubscription( onError: error => console.error(error), } ); - ``` # Updating the client on each response @@ -97,7 +93,6 @@ Relay's in-memory cache when each subscription response is received. To do so, pass an `updater` function: ```javascript - const {ConnectionHandler} = require('relay-runtime'); requestSubscription( @@ -123,5 +118,4 @@ requestSubscription( }, }, ); - ``` diff --git a/website/versioned_docs/version-v3.0.0/Modern-TestingRelayComponents.md b/website/versioned_docs/version-v3.0.0/Modern-TestingRelayComponents.md index f30317b146e96..eaa443bd20147 100644 --- a/website/versioned_docs/version-v3.0.0/Modern-TestingRelayComponents.md +++ b/website/versioned_docs/version-v3.0.0/Modern-TestingRelayComponents.md @@ -64,7 +64,6 @@ With the `MockPayloadGenerator` and `@relay_test_operation`, we want to get rid Example of a simple Mock Resolver: ```javascript - { ID() { // Return mock value for a scalar filed with type ID @@ -75,13 +74,11 @@ Example of a simple Mock Resolver: return "Lorem Ipsum" } } - ``` It is possible to define more resolvers for Object types: ```javascript - { // This will be the default values for User object in the query response User() { @@ -94,7 +91,6 @@ It is possible to define more resolvers for Object types: }; }, } - ``` ### Mock Resolver Context @@ -102,7 +98,6 @@ It is possible to define more resolvers for Object types: The first argument of the MockResolver is the object that contains Mock Resolver Context. It is possible to return dynamic values from mock resolvers based on the context - for instance, name or alias of the field, a path in the selection, arguments, or parent type. ```javascript - { String(context) { if (context.name === 'zip') { @@ -116,7 +111,6 @@ The first argument of the MockResolver is the object that contains Mock Resolver } } } - ``` ### ID Generation @@ -124,14 +118,12 @@ The first argument of the MockResolver is the object that contains Mock Resolver The second argument of the Mock Resolver its a function that will generate a sequence of integers, useful to generate unique IDs in the tests: ```javascript - { // will generate strings "my-id-1", "my-id-2", etc. ID(_, generateId) { return `my-id-${generateId()}`; }, } - ``` ### `@relay_test_operation` @@ -141,7 +133,6 @@ Most of GraphQL type information for a specific field in the selection is not av Operations with the `@relay_test_operation` directive will have additional metadata that will contain GraphQL type info for fields in the operation's selection. And it will improve the quality of the generated data. You also will be able to define Mock resolvers for Scalar (not only ID and String) and Abstract types: ```javascript - { Float() { return 123.456; @@ -159,7 +150,6 @@ Operations with the `@relay_test_operation` directive will have additional metad }; } } - ``` ## Examples @@ -169,7 +159,6 @@ Operations with the `@relay_test_operation` directive will have additional metad Using `createMockEnvironment` and `MockPayloadGenerator` allows writing concise tests for components that are using Relay Containers and Renderers. Both those modules can be imported from `relay-test-utils`. ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { @@ -222,7 +211,6 @@ test('Error State', () => { renderer.root.find(item => (item.props.testID = 'errorMessage')), ).toBeDefined(); }); - ``` ### Fragment Container Tests @@ -230,7 +218,6 @@ test('Error State', () => { Essentially, in the example above, `resolveMostRecentOperation` will generate data for all child fragment containers (pagination, refetch). Usually, the Root Components container may have many child fragment components and you may want to exercise a specific Fragment Container. The solution for that would be to wrap your fragment container with the QueryRenderer that renders a Query that's spreads fragments from your fragment container. ```javascript - test('Fragment Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -261,7 +248,6 @@ test('Fragment Container', () => { expect(renderer).toMatchSnapshot(); }); - ``` ### Pagination Container Test @@ -269,7 +255,6 @@ test('Fragment Container', () => { Essentially, tests for Pagination container are not different from Fragment Container tests. We can also do more here. We can actually see how the pagination works by asserting the behavior of our components when performing pagination (load more, refetch). ```javascript - // Pagination Example test('Pagination Container', () => { const environment = createMockEnvironment(); @@ -343,7 +328,6 @@ test('Pagination Container', () => { We can use similar approach here with wrapping container with Query Renderer. And for the sake of completeness, we will add example here: ```javascript - test('Refetch Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -385,7 +369,6 @@ test('Refetch Container', () => { ); // expect(renderer).toMatchSnapshot(); }); - ``` ### Mutations @@ -393,7 +376,6 @@ test('Refetch Container', () => { Mutations itself are operations so we can test them independently (unit-test) for specific mutation, or in combination with the view from which this mutation is called. ```javascript - // Say, you have a mutation function function sendMutation(environment, onCompleted, onError, variables) commitMutation(environment, { @@ -416,7 +398,6 @@ test('it should send mutation', () => { ); expect(onCompleted).toBeCalled(); }); - ``` ### Subscription @@ -424,7 +405,6 @@ test('it should send mutation', () => { We can test subscription in a similar way we test mutations ```javascript - // Example subscribe function function subscribe(environment, onNext, onError, variables) requestSubscription(environment, { @@ -447,7 +427,6 @@ test('it should subscribe', () => { ); expect(onNext).toBeCalled(); }); - ``` ### Example with `queueOperationResolver` @@ -455,7 +434,6 @@ test('it should subscribe', () => { With `queueOpeararionResolver`, it possible to define responses for operations that will be executed on the environment ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { diff --git a/website/versioned_docs/version-v3.0.0/Modern-TypeEmission.md b/website/versioned_docs/version-v3.0.0/Modern-TypeEmission.md index c6cad1e53d3b2..e3bb438428672 100644 --- a/website/versioned_docs/version-v3.0.0/Modern-TypeEmission.md +++ b/website/versioned_docs/version-v3.0.0/Modern-TypeEmission.md @@ -16,7 +16,6 @@ In this example the emitted type-information would require the variables object #### Flow ```javascript - /** * export type ExampleQueryVariables = {| * +artistID: string @@ -44,7 +43,6 @@ const variables: ExampleQueryVariables = { #### TypeScript ```javascript - /** * export type ExampleQueryVariables = { * readonly artistID: string @@ -79,7 +77,6 @@ In this example the emitted type-information describes the response data availab #### Flow ```javascript - /** * export type ExampleQueryResponse = {| * +artist: ?{| @@ -110,7 +107,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * export type ExampleQueryResponse = { * readonly artist?: { @@ -146,7 +142,6 @@ Similarly, in this example the emitted type-information describes the prop data #### Flow ```javascript - /** * export type ExampleFragment_artist = {| * +name: string @@ -172,7 +167,6 @@ export const ExampleFragment = createFragmentContainer( #### TypeScript ```javascript - /** * export type ExampleFragment_artist = { * readonly name: string @@ -206,7 +200,6 @@ Consider a component that composes the above fragment container example. In this #### Flow ```javascript - /** * import type { FragmentReference } from "relay-runtime"; * declare export opaque type ExampleFragment_artist$ref: FragmentReference; @@ -250,7 +243,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * declare const _ExampleFragment_artist$ref: unique symbol; * export type ExampleFragment_artist$ref = typeof _ExampleFragment_artist$ref; @@ -315,7 +307,6 @@ $ relay-compiler --artifactDirectory ./src/__generated__ […] ["relay", { "artifactDirectory": "./src/__generated__" }] ] } - ``` It is recommended to alias this directory in your module resolution configuration such that you don’t need to specify relative paths in your source files. This is what is also done in the above examples, where artifacts are imported from a `__generated__` alias, rather than relative paths like `../../../../__generated__`. diff --git a/website/versioned_docs/version-v3.0.0/Modern-UpgradingSetVariables.md b/website/versioned_docs/version-v3.0.0/Modern-UpgradingSetVariables.md index d5b086fafce20..ff73feec04f8b 100644 --- a/website/versioned_docs/version-v3.0.0/Modern-UpgradingSetVariables.md +++ b/website/versioned_docs/version-v3.0.0/Modern-UpgradingSetVariables.md @@ -36,7 +36,6 @@ fragment on User { # ... } } - ``` This should be upgraded to use a [`PaginationContainer`](./pagination-container). @@ -61,7 +60,6 @@ fragment on User { # ... } } - ``` This can be upgraded by using a [`RefetchContainer`](./refetch-container) which allows you to specify the exact query to use to fetch the new data. @@ -86,7 +84,6 @@ fragment on FeedbackTarget { # ... } } - ``` This can be upgraded by conditionally rendering a [`QueryRenderer`](./query-renderer) which will load the data once it is rendered. The code overhead of doing this is dramatically reduced with the new API. diff --git a/website/versioned_docs/version-v3.0.0/Modern-fetchQuery.md b/website/versioned_docs/version-v3.0.0/Modern-fetchQuery.md index 939631d03832b..b4922b01b6c2b 100644 --- a/website/versioned_docs/version-v3.0.0/Modern-fetchQuery.md +++ b/website/versioned_docs/version-v3.0.0/Modern-fetchQuery.md @@ -6,7 +6,6 @@ original_id: fetch-query You can use the `fetchQuery` function to imperatively make GraphQL Requests. This is useful for cases where you want to make requests outside of React but still utilize the Relay store and network layer. ```javascript - import {fetchQuery, graphql} from 'relay-runtime'; const query = graphql` @@ -25,7 +24,6 @@ fetchQuery(environment, query, variables) .then(data => { // access the graphql response }); - ``` ## Arguments diff --git a/website/versioned_docs/version-v3.0.0/PrinciplesAndArchitecture-Compiler.md b/website/versioned_docs/version-v3.0.0/PrinciplesAndArchitecture-Compiler.md index c195491682b1f..fcd0490cb724f 100644 --- a/website/versioned_docs/version-v3.0.0/PrinciplesAndArchitecture-Compiler.md +++ b/website/versioned_docs/version-v3.0.0/PrinciplesAndArchitecture-Compiler.md @@ -74,7 +74,6 @@ foo { # type FooType foo { id } - ``` - `SkipRedundantNodeTransform`: A more advanced version of flattening, this eliminates more complex cases of field duplication such as when a field is fetched both unconditionally and conditionally, or is fetched by two different sub-fragments. For example: @@ -97,7 +96,6 @@ foo { id } } - ``` - `GenerateRequisiteFieldTransform`: This optional, Relay-specific transform inserts `id` fields for globally identifiable objects and `__typename` fields wherever the type cannot be statically determined (e.g. for unions). diff --git a/website/versioned_docs/version-v3.0.0/PrinciplesAndArchitecture-Runtime.md b/website/versioned_docs/version-v3.0.0/PrinciplesAndArchitecture-Runtime.md index 9491d290c146f..e9221631a701d 100644 --- a/website/versioned_docs/version-v3.0.0/PrinciplesAndArchitecture-Runtime.md +++ b/website/versioned_docs/version-v3.0.0/PrinciplesAndArchitecture-Runtime.md @@ -77,7 +77,6 @@ RecordSource { city: 'Seattle', } } - ``` [1] Note that GraphQL itself does not impose this constraint, and Relay Runtime may also be used for schemas that do not conform to it. For example, both systems can be used to query a single denormalized table. However, many of the features that Relay Runtime provides, such as caching and normalization, work best when the data is represented as a normalized graph with stable identities for discrete pieces of information. diff --git a/website/versioned_docs/version-v3.0.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md b/website/versioned_docs/version-v3.0.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md index a8842ae084922..9ff8a7840df90 100644 --- a/website/versioned_docs/version-v3.0.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md +++ b/website/versioned_docs/version-v3.0.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md @@ -12,7 +12,6 @@ In this article we'll explore what it means to build a GraphQL client framework Imagine we have a simple application that fetches a list of stories, and some details about each one. Here's how that might look in resource-oriented REST: ```javascript - // Fetch the list of story IDs but not their details: rest.get('/stories').then(stories => // This resolves to a list of items with linked resources: @@ -25,13 +24,11 @@ rest.get('/stories').then(stories => // `[ { id: "...", text: "..." } ]` console.log(stories); }); - ``` Note that this approach requires _n+1_ requests to the server: 1 to fetch the list, and _n_ to fetch each item. With GraphQL we can fetch the same data in a single network request to the server (without creating a custom endpoint that we'd then have to maintain): ```javascript - graphql.get(`query { stories { id, text } }`).then( stories => { // A list of story items: @@ -39,7 +36,6 @@ graphql.get(`query { stories { id, text } }`).then( console.log(stories); } ); - ``` So far we're just using GraphQL as a more efficient version of typical REST approaches. Note two important benefits in the GraphQL version: @@ -56,7 +52,6 @@ Repeatedly refetching information from the server can get quite slow. For exampl In a resource-oriented REST system, we can maintain a **response cache** based on URIs: ```javascript - var _cache = new Map(); rest.get = uri => { if (!_cache.has(uri)) { @@ -64,13 +59,11 @@ rest.get = uri => { } return _cache.get(uri); }; - ``` Response-caching can also be applied to GraphQL. A basic approach would work similarly to the REST version. The text of the query itself can be used as a cache key: ```javascript - var _cache = new Map(); graphql.get = queryText => { if (!_cache.has(queryText)) { @@ -78,7 +71,6 @@ graphql.get = queryText => { } return _cache.get(queryText); }; - ``` Now, requests for previously cached data can be answered immediately without making a network request. This is a practical approach to improving the perceived performance of an application. However, this method of caching can cause problems with data consistency. @@ -90,7 +82,6 @@ With GraphQL it is very common for the results of multiple queries to overlap. H ``` query { stories { id, text, likeCount } } - ``` and then later refetch one of the stories whose `likeCount` has since been incremented: @@ -98,7 +89,6 @@ and then later refetch one of the stories whose `likeCount` has since been incre ``` query { story(id: "123") { id, text, likeCount } } - ``` We'll now see different `likeCount`s depending on how the story is accessed. A view that uses the first query will see an outdated count, while a view using the second query will see the updated count. @@ -119,7 +109,6 @@ query { } } } - ``` And here's a possible response: @@ -134,13 +123,11 @@ query: { } } } - ``` Although the response is hierarchical, we'll cache it by flattening all the records. Here is an example of how Relay would cache this query response: ```javascript - Map { // `story(id: "1")` 1: Map { @@ -152,7 +139,6 @@ Map { name: 'Jan', }, }; - ``` This is only a simple example: in reality the cache must handle one-to-many associations and pagination (among other things). @@ -182,7 +168,6 @@ The first query was for a list of stories: ``` query { stories { id, text, likeCount } } - ``` With a normalized response cache, a record would be created for each story in the list. The `stories` field would store links to each of these records. @@ -192,7 +177,6 @@ The second query refetched the information for one of those stories: ``` query { story(id: "123") { id, text, likeCount } } - ``` When this response is normalized, Relay can detect that this result overlaps with existing data based on its `id`. Rather than create a new record, Relay will update the existing `123` record. The new `likeCount` is therefore available to _both_ queries, as well as any other query that might reference this story. @@ -215,7 +199,6 @@ query { } } } - ``` After initially fetching this story our cache might be as follows. Note that the story and comment both link to the same record as `author`: @@ -242,7 +225,6 @@ Map { author: Link(2), }, } - ``` The author of this story also commented on it — quite common. Now imagine that some other view fetches new information about the author, and her profile photo has changed to a new URI. Here's the _only_ part of our cached data that changes: @@ -256,7 +238,6 @@ Map { photo: 'http://.../photo2.jpg', }, } - ``` The value of the `photo` field has changed; and therefore the record `2` has also changed. And that's it. Nothing else in the _cache_ is affected. But clearly our _view_ needs to reflect the update: both instances of the author in the UI (as story author and comment author) need to show the new photo. @@ -273,7 +254,6 @@ ImmutableMap { }, 3: ImmutableMap // same as before } - ``` If we replace `2` with a new immutable record, we'll also get a new immutable instance of the cache object. However, records `1` and `3` are untouched. Because the data is normalized, we can't tell that `story`'s contents have changed just by looking at the `story` record alone. @@ -299,7 +279,6 @@ mutation StoryLike($storyID: String) { likeCount } } - ``` Notice that we're querying for data that _may_ have changed as a result of the mutation. An obvious question is: why can't the server just tell us what changed? The answer is: it's complicated. GraphQL abstracts over _any_ data storage layer (or an aggregation of multiple sources), and works with any programming language. Furthermore, the goal of GraphQL is to provide data in a form that is useful to product developers building a view. diff --git a/website/versioned_docs/version-v3.0.0/PrinciplesAndArchitecture-ThinkingInRelay.md b/website/versioned_docs/version-v3.0.0/PrinciplesAndArchitecture-ThinkingInRelay.md index d6f1572d5590b..4fb68372ec4b3 100644 --- a/website/versioned_docs/version-v3.0.0/PrinciplesAndArchitecture-ThinkingInRelay.md +++ b/website/versioned_docs/version-v3.0.0/PrinciplesAndArchitecture-ThinkingInRelay.md @@ -30,13 +30,11 @@ fragment Story_story on Story { photo } } - ``` And this fragment can then be used to define the Story container: ```javascript - const {createFragmentContainer, graphql} = require('react-relay'); // Plain React component. @@ -64,7 +62,6 @@ const StoryContainer = createFragmentContainer(Story, { In React, rendering a view requires two inputs: the _component_ to render, and a _root_ DOM (UI) node to render into. Rendering Relay containers is similar: we need a _container_ to render, and a _root_ in the graph from which to start our query. We also must ensure that the queries for the container are executed and may want to show a loading indicator while data is being fetched. Similar to `ReactDOM.render(component, domNode)`, Relay provides `` for this purpose. The `query` and `variables` define what data to fetch and `render` defines what to render. Here's how we might render ``: ```javascript - ReactDOM.render( { ); } } - ``` The above code is doing something very similar to our [previous example](#rendering-graphql-queries). However, we are now passing a `$userID` variable to the GraphQL query via the `variables` prop. This has a couple of important implications: @@ -228,7 +216,6 @@ Now that we know how to define and fetch queries, let's actually start building First, let's start at the bottom. Suppose that we want to render a component that simply displays a given todo item's text and completed state: ```javascript - // Todo.js import React from 'react'; @@ -258,7 +245,6 @@ export default class Todo extends React.Component { ); } } - ``` From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L107), we know that we can query this data on the `Todo` type. However, we don't want to have to send a separate query for each todo item; that would defeat the purpose of using GraphQL over a traditional REST API. We could manually query for these fields directly in our `QueryRenderer` query, but that would hurt re-usability: what if we want to query the same set of fields as part of a different query? Additionally, we wouldn't know which component needs the data we're querying, which is a problem Relay directly tries to address. @@ -266,18 +252,15 @@ From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/dat Instead, we can define a reusable [Fragment](http://graphql.org/learn/queries/#fragments), which allows us to define a set of fields on a type and reuse them within our queries wherever we need to: ```graphql - fragment TodoItemFragment on Todo { complete text } - ``` Our component can then use this fragment to declare its data dependency on the `Todo` GraphQL type: ```javascript - // Todo.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -337,7 +320,6 @@ Before proceeding, don't forget to run the Relay Compiler with `yarn relay`. Given that [Fragment Containers](./fragment-container) are just React components, we can compose them as such. We can even re-use fragment containers within other fragment containers. As an example, let's see how we would define a `TodoList` component that just renders a list of todo items, and whether all have been completed or not: ```javascript - // TodoList.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -396,7 +378,6 @@ export default createFragmentContainer( } `, ); - ``` As with the first fragment container we defined, `TodoList` declares it's data dependencies via a fragment. However, this component additionally re-uses the fragment previously defined by the `Todo` component, and passes the appropriate data when rendering the child `Todo` components (a.k.a. fragment containers). @@ -411,7 +392,6 @@ fragment containers do not directly fetch data. Instead, containers declare a sp A `QueryRenderer` rendering these fragment containers could look like the following: ```javascript - // ViewerTodoList.js import React from 'react'; import {graphql, QueryRenderer} from 'react-relay'; @@ -452,7 +432,6 @@ export default class ViewerTodoList extends React.Component { ); } } - ``` Check out our docs for [Fragment Containers](./fragment-container) for more details, and our guides on [Refetch](./refetch-container) and [Pagination](./pagination-container) for more advanced usage of containers. @@ -464,7 +443,6 @@ Now that we know how to query for and render data, let's move on to changing our From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L35), we know that we have some mutations available to us, so let's start by writing a mutation to change the `complete` status of a given todo item (i.e. mark or unmark it as done): ```graphql - mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { changeTodoStatus(input: $input) { todo { @@ -473,7 +451,6 @@ mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { } } } - ``` This mutation allows us to query back some data as a [result of the mutation](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L18), so we're going to query for the updated `complete` status on the todo item. @@ -481,7 +458,6 @@ This mutation allows us to query back some data as a [result of the mutation](ht In order to execute this mutation in Relay, we're going to write a new mutation using Relay's `commitMutation` api: ```javascript - // ChangeTodoStatusMutation.js import {graphql, commitMutation} from 'react-relay'; @@ -515,7 +491,6 @@ function commit( } export default {commit}; - ``` Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mutation to the server and, in our case, upon receiving a response it will automatically update the local data store with the latest data from the server. This also means that upon receiving the response, Relay will ensure that any components (i.e. containers) that depend on the updated data are re-rendered. @@ -523,7 +498,6 @@ Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mut In order to actually use this mutation in our component, we could update our `Todo` component in the following way: ```javascript - // Todo.js // ... @@ -557,7 +531,6 @@ In order to make the experience better, we can configure our mutation to do an o In Relay, there's a couple of options we can pass to `commitMutation` to enable optimistic updates. Let's see what that would look like in our `ChangeTodoStatusMutation`: ```javascript - // ChangeTodoStatusMutation.js // ... @@ -592,7 +565,6 @@ function commit( } export default {commit}; - ``` In the simplest case above, we just need to pass an `optimisticResponse` option, which should refer to an object having the same shape as the mutation response payload. When we pass this option, Relay will know to immediately update our local data with the optimistic response, and then update it with the actual server response or roll it back if an error occurs. diff --git a/website/versioned_docs/version-v4.0.0/Modern-ConvertingMutations.md b/website/versioned_docs/version-v4.0.0/Modern-ConvertingMutations.md index 08ad2e998cb2d..8f4bdc1d8e0d2 100644 --- a/website/versioned_docs/version-v4.0.0/Modern-ConvertingMutations.md +++ b/website/versioned_docs/version-v4.0.0/Modern-ConvertingMutations.md @@ -12,19 +12,16 @@ FatQueries in Relay Classic mutations was a concept that was confusing for a num Example of existing fat query: ```javascript - RelayClassic.QL` fragment on MarkReadNotificationResponsePayload @relay(pattern: true) { notification } `; - ``` Example of converted mutation query: ```javascript - graphql` mutation MarkReadNotificationMutation( $input: MarkReadNotificationData! @@ -37,7 +34,6 @@ graphql` } } `; - ``` ## Migrating Configs @@ -67,7 +63,6 @@ This is no longer needed in Compatibility Mode for neither environments. Simply Take this example of a simple mutation in Relay Classic: ```javascript - class LikeStoryMutation extends RelayClassic.Mutation { getMutation() { return RelayClassic.QL`mutation {likeStory}`; @@ -106,7 +101,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { `, }; } - ``` ### Converting `getMutation()` and `getFatQuery()` @@ -114,7 +108,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { We combine these two into a regular GraphQL mutation, which list out specific fields that needs to be updated. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story(data: $input) { @@ -126,7 +119,6 @@ const mutation = graphql` } } `; - ``` ### Converting `getConfigs()` @@ -138,13 +130,11 @@ As specified above, `FIELDS_CHANGE` configs can be omitted. To convert `getVariables()`, we take the return value from the original function and wrap it in an object that contains a property that matches the variable name for the mutation. In this case, the mutation has a `input` variable that is of type `LikeStoryData`. ```javascript - const variables = { input: { storyID: args.storyID } } - ``` ### Final Result @@ -152,7 +142,6 @@ const variables = { As you can see, our resulting mutation is a lot simpler and more like regular GraphQL than the Relay Classic version we started out with. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story { @@ -178,7 +167,6 @@ function commit(environment: CompatEnvironment, args) { variables, }); } - ``` See [Mutation](./mutations) for additional options on `commitMutation` for more complex mutations. diff --git a/website/versioned_docs/version-v4.0.0/Modern-FragmentContainer.md b/website/versioned_docs/version-v4.0.0/Modern-FragmentContainer.md index 423f446cbb054..6a40bbcfb5d0a 100644 --- a/website/versioned_docs/version-v4.0.0/Modern-FragmentContainer.md +++ b/website/versioned_docs/version-v4.0.0/Modern-FragmentContainer.md @@ -17,12 +17,10 @@ Table of Contents: `createFragmentContainer` has the following signature: ```javascript - createFragmentContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, ): ReactComponentClass; - ``` ### Arguments @@ -43,7 +41,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -58,7 +55,6 @@ To start, let's build the plain React version of a hypothetical `` c Here's a basic implementation of `` that ignores styling in order to highlight the functionality: ```javascript - // TodoItem.js class TodoItem extends React.Component { render() { @@ -78,7 +74,6 @@ class TodoItem extends React.Component { ); } } - ``` ### Data Dependencies With GraphQL @@ -86,7 +81,6 @@ class TodoItem extends React.Component { In Relay, data dependencies are described using [GraphQL](https://github.com/facebook/graphql). For ``, the dependency can be expressed as follows. Note that this exactly matches the shape that the component expected for the `item` prop. ```javascript - graphql` # This fragment only applies to objects of type 'Todo'. fragment TodoItem_item on Todo { @@ -102,7 +96,6 @@ graphql` Given the plain React component and a GraphQL fragment, we can now define a Fragment Container to specify this component's data requirements. Let's look at the code first and then see what's happening: ```javascript - // TodoItem.js import {createFragmentContainer, graphql} from 'react-relay'; @@ -120,7 +113,6 @@ export default createFragmentContainer(TodoItem, { } `, }); - ``` ## Container Composition @@ -134,7 +126,6 @@ Let's explore how this works via a `` component that composes the `< View composition is _exactly_ what you're used to — Relay containers are just standard React components. Here's the `` component: ```javascript - class TodoList extends React.Component { render() { // Expects a `list` with a string `title`, as well as the information @@ -151,7 +142,6 @@ class TodoList extends React.Component { ); } } - ``` ### Composing Fragments @@ -159,7 +149,6 @@ class TodoList extends React.Component { Fragment composition works similarly — a parent container's fragment composes the fragment for each of its children. In this case, `` needs to fetch information about the `Todo`s that are required by ``. ```javascript - class TodoList extends React.Component // as above export default createFragmentContainer(TodoList, { @@ -176,7 +165,6 @@ export default createFragmentContainer(TodoList, { } `, }); - ``` Note that when composing fragments, the type of the composed fragment must match the field on the parent in which it is embedded. For example, it wouldn't make sense to embed a fragment of type `Story` into a parent's field of type `User`. Relay and GraphQL will provide helpful error messages if you get this wrong (and if they aren't helpful, let us know!). @@ -190,7 +178,6 @@ When defining a fragment, you can use the [`@argumentDefinitions`](./graphql-in- For example, let's redefine our `TodoList_list` fragment to take some arguments using `@argumentDefinitions`: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -200,7 +187,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` Any arguments defined inside `@argumentDefinitions` will be local variables available inside the fragment's scope. However, a fragment can also reference global variables that were defined in the root query. @@ -212,11 +198,9 @@ In order to pass arguments to a fragment that has `@argumentDefinitions`, you ne Following our `TodoList_list` example, we would pass arguments to the fragment like so: ```graphql - query TodoListQuery($count: Int, $userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` ## Rendering Containers diff --git a/website/versioned_docs/version-v4.0.0/Modern-GraphQLInRelay.md b/website/versioned_docs/version-v4.0.0/Modern-GraphQLInRelay.md index 2db8e32cc7ed9..ae28027b32a20 100644 --- a/website/versioned_docs/version-v4.0.0/Modern-GraphQLInRelay.md +++ b/website/versioned_docs/version-v4.0.0/Modern-GraphQLInRelay.md @@ -14,7 +14,6 @@ Table of Contents: The `graphql` template tag provided by Relay serves as the mechanism to write queries, fragments, mutations or subscriptions in the [GraphQL](http://graphql.org/learn/) language. For example: ```javascript - import {graphql} from 'react-relay'; graphql` @@ -24,7 +23,6 @@ graphql` } } `; - ``` The result of using the `graphql` template tag is a `GraphQLTaggedNode`; a runtime representation of the GraphQL document which can be used to define [Query Renderers](./query-renderer), [Fragment Containers](./fragment-container), [Refetch Containers](./refetch-container), [Pagination Containers](./pagination-container), etc. @@ -42,11 +40,9 @@ Relay uses directives to add additional information to GraphQL documents, which `@arguments` is a directive used to pass arguments to a fragment that was defined using [`@argumentDefinitions`](#argumentdefinitions). For example: ```graphql - query TodoListQuery($userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -56,7 +52,6 @@ See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fr `@argumentDefinitions` is a directive used to specify arguments taken by a fragment. For example: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -66,7 +61,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -80,7 +74,6 @@ When using the [Pagination Container](./pagination-container), Relay expects con When defining a fragment for use with a Fragment container, you can use the `@relay(plural: true)` directive to indicate that container expects the prop for that fragment to be a list of items instead of a single item. A query or parent that spreads a `@relay(plural: true)` fragment should do so within a plural field (ie a field backed by a [GraphQL list](http://graphql.org/learn/schema/#lists-and-non-null). For example: ```javascript - // Plural fragment definition graphql` fragment TodoItems_items on TodoItem @relay(plural: true) { @@ -95,7 +88,6 @@ fragment TodoApp_app on App { ...TodoItem_items } } - ``` ### `@relay(mask: Boolean)` @@ -113,7 +105,6 @@ Keep in mind that it is typically considered an **anti-pattern** to create a sin In the example below, the `user` prop will include the data for `id` and `name` fields wherever `...Component_internUser` is included, instead of Relay's normal behavior to mask those fields: ```javascript - graphql` fragment Component_internUser on InternUser @relay(mask: false) { id @@ -141,7 +132,6 @@ export default createFragmentContainer( } `, ); - ``` ## Relay Compiler @@ -151,7 +141,6 @@ Relay uses the Relay Compiler to convert [`graphql`](#graphql) literals into gen A query like the following: ```javascript - graphql` fragment MyComponent on Type { field @@ -172,12 +161,10 @@ Relay Compiler supports the use of **persisted queries**, in which each version Persisted queries can be enabled by instructing Relay Compiler to emit metadata about each query, mutation, and subscription into a JSON file. The generated file will contain a mapping of query identifiers to query text, which you can then save to your server. To enable persisted queries, use the `--persist-output` flag to the compiler: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` Relay Compiler will then create the id => query text mapping in the path you specify. You can then use this complete @@ -194,7 +181,6 @@ See our relay-compiler section in our [Installation and Setup guide](./installat To use the Relay Compiler, you need either a .graphql or .json GraphQL schema file, describing your GraphQL server's API. Typically these files are local representations of a server source of truth and are not edited directly. For example, we might have a `schema.graphql` like: ```graphql - schema { query: Root } @@ -212,7 +198,6 @@ type WordDefinition { text: String image: String } - ``` ### Source files @@ -228,7 +213,6 @@ For example, given the two files: - `src/Components/DictionaryComponent.js` ```javascript - const DictionaryWordFragment = graphql` fragment DictionaryComponent_word on Word { id @@ -250,7 +234,6 @@ For example, given the two files: - `src/Queries/DictionaryQuery.js` ```javascript - const DictionaryQuery = graphql` query DictionaryQuery { dictionary { @@ -274,9 +257,7 @@ Typically you will not need to import your generated definitions. The [Relay Bab However the Relay Compiler also automatically generates [Flow](https://flow.org) types as [type comments](https://flow.org/en/docs/types/comments/). For example, you can import the generated Flow types like so: ```javascript - import type {DictionaryComponent_word} from './__generated__/DictionaryComponent_word.graphql'; - ``` ### Client schema extensions @@ -286,18 +267,15 @@ The Relay Compiler fully supports client-side schema extensions, which allows yo For example, let's create `./src/clientSchema.graphql` and define a new type called `Setting`: ```graphql - type Setting { name: String! active: Boolean! } - ``` Assuming the server schema `./schema.graphql`: ```graphql - schema { query: Root } @@ -305,17 +283,14 @@ schema { type Root { title: String! } - ``` We can then extend existing server types in the client schema `./src/clientSchema.graphql` with our new `Setting` type, like so: ```graphql - extend type Root { settings: [Setting] } - ``` Any fields specified in the client schema, can be fetched from the [Relay Store](./relay-store), by requesting it in a query. diff --git a/website/versioned_docs/version-v4.0.0/Modern-LocalStateManagement.md b/website/versioned_docs/version-v4.0.0/Modern-LocalStateManagement.md index 2f20f57000cc1..c97bfdb12b45f 100644 --- a/website/versioned_docs/version-v4.0.0/Modern-LocalStateManagement.md +++ b/website/versioned_docs/version-v4.0.0/Modern-LocalStateManagement.md @@ -24,23 +24,19 @@ It can even be used to extend an existing server schema. For example, we can create a new type called `Note`: ```graphql - type Note { ID: ID! title: String body: String } - ``` And then extend the server schema type `User`, with a list of `Note`, called `notes`. ```graphql - extend type User { notes: [Note] } - ``` ## Querying local state @@ -51,7 +47,6 @@ The field can be from the server schema, or it can be schema agnostic, like an i Here, we use a [QueryRenderer](./query-renderer) to get the current `User` via the `viewer` field, along with their id, name and the local list of notes. ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -97,7 +92,6 @@ const Example = (props) => { /> ); } - ``` ## Mutating local state @@ -111,7 +105,6 @@ To build upon the previous example, let's try creating, updating and deleting a ### Create ```javascript - import {commitLocalUpdate} from 'react-relay'; let tempID = 0; @@ -138,13 +131,11 @@ function createUserNote() { user.setLinkedRecords([...userNoteRecords, newNoteRecord], 'notes'); }); } - ``` ### Update ```javascript - import {commitLocalUpdate} from 'react-relay'; function updateUserNote(dataID, body, title) { @@ -155,13 +146,11 @@ function updateUserNote(dataID, body, title) { note.setValue(title, 'title') }); } - ``` ### Delete ```javascript - import {commitLocalUpdate} from 'react-relay'; function deleteUserNote(dataID) { @@ -179,7 +168,6 @@ function deleteUserNote(dataID) { user.setLinkedRecords(newUserNoteRecords, 'notes'); }); } - ``` ## Initial local state @@ -188,7 +176,6 @@ All new client-side schema fields default to `undefined` value. Often however, y You can use an updater function via `commitLocalUpdate` to prime local state. ```javascript - import {commitLocalUpdate} from 'react-relay'; commitLocalUpdate(environment, store => { @@ -197,5 +184,4 @@ commitLocalUpdate(environment, store => { // initialize user notes to an empty array. user.setLinkedRecords([], 'notes'); }); - ``` diff --git a/website/versioned_docs/version-v4.0.0/Modern-MigrationSetup.md b/website/versioned_docs/version-v4.0.0/Modern-MigrationSetup.md index 66f1145357e25..a89c0e178e0e5 100644 --- a/website/versioned_docs/version-v4.0.0/Modern-MigrationSetup.md +++ b/website/versioned_docs/version-v4.0.0/Modern-MigrationSetup.md @@ -13,13 +13,11 @@ With some additional configuration, the `"relay"` babel plugin can also translat Relay Classic `Relay.QL` literals. Most importantly, include a reference to your GraphQL Schema as either a json file or graphql schema file. ```javascript - { "plugins": [ ["relay", {"schema": "path/schema.graphql"}] ] } - ``` ## Set up babel-plugin-relay for "[compatibility mode](./relay-compat)" @@ -29,13 +27,11 @@ literals can be translated to be usable by _both_ runtimes if configured to use compatibility mode: ```javascript - { "plugins": [ ["relay", {"compat": true, "schema": "path/schema.graphql"}] ] } - ``` ## Additional Options @@ -47,7 +43,6 @@ thrown at runtime. When compiling code for production deployment, the plugin can be configured to immediately throw upon encountering a validation problem. The plugin can be further customized for different environments with the following options: ```javascript - { "plugins": [ ["relay", { @@ -56,5 +51,4 @@ When compiling code for production deployment, the plugin can be configured to i }] ] } - ``` diff --git a/website/versioned_docs/version-v4.0.0/Modern-Mutations.md b/website/versioned_docs/version-v4.0.0/Modern-Mutations.md index a2e0b285bf2c4..8da3bd999c701 100644 --- a/website/versioned_docs/version-v4.0.0/Modern-Mutations.md +++ b/website/versioned_docs/version-v4.0.0/Modern-Mutations.md @@ -17,7 +17,6 @@ Table of Contents: Use `commitMutation` to create and execute mutations. `commitMutation` has the following signature: ```javascript - commitMutation( environment: Environment, config: { @@ -31,7 +30,6 @@ commitMutation( configs?: Array, }, ); - ``` ### Arguments @@ -58,7 +56,6 @@ commitMutation( Example of a simple mutation: ```javascript - import {commitMutation, graphql} from 'react-relay'; const mutation = graphql` @@ -93,7 +90,6 @@ function markNotificationAsRead(environment, source, storyID) { }, ); } - ``` ## Optimistic Updates @@ -101,7 +97,6 @@ function markNotificationAsRead(environment, source, storyID) { To improve perceived responsiveness, you may wish to perform an "optimistic update", in which the client immediately updates to reflect the anticipated new value even before the response from the server has come back. The simplest way to do this is by providing an `optimisticResponse` and adding it to the `config` that we pass into `commitMutation`: ```javascript - const mutation = graphql` mutation MarkReadNotificationMutation( $input: MarkReadNotificationInput! @@ -130,7 +125,6 @@ commitMutation( variables, }, ); - ``` Another way to enable optimistic updates is via the `optimisticUpdater`, which can be used for more complicated update scenarios. Using `optimisticUpdater` is covered in the section [below](#using-updater-and-optimisticupdater). @@ -152,7 +146,6 @@ Given a deletedIDFieldName, Relay will remove the node(s) from the store. #### Example ```javascript - const mutation = graphql` mutation DestroyShipMutation($input: DestroyShipInput!) { destroyShip(input: $input) { @@ -170,7 +163,6 @@ const configs = [{ type: 'NODE_DELETE', deletedIDFieldName: 'destroyedShipId', }]; - ``` ### RANGE_ADD @@ -190,7 +182,6 @@ Given a parent, information about the connection, and the name of the newly crea #### Example ```javascript - const mutation = graphql` mutation AddShipMutation($input: AddShipInput!) { addShip(input: $input) { @@ -220,7 +211,6 @@ function commit(environment, factionId, name) { }], }); } - ``` ### RANGE_DELETE @@ -242,7 +232,6 @@ from the connection but leave the associated record(s) in the store. #### Example ```javascript - const mutation = graphql` mutation RemoveTagMutation($input: RemoveTagInput!) { removeTag(input: $input) { @@ -268,7 +257,6 @@ function commit(environment, todoId, tagId) { }], }); } - ``` ## Using updater and optimisticUpdater @@ -286,7 +274,6 @@ When you provide these functions, this is roughly what happens during the mutati Here are a quick example of adding a todo item to a Todo list using this [example schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L36): ```javascript - // AddTodoMutation.js import {commitMutation, graphql} from 'react-relay'; import {ConnectionHandler} from 'relay-runtime'; @@ -373,7 +360,6 @@ function commit(environment, text, user) { }, }); } - ``` For details on how to interact with the Relay Store, please refer to our Relay Store [docs](./relay-store). diff --git a/website/versioned_docs/version-v4.0.0/Modern-NetworkLayer.md b/website/versioned_docs/version-v4.0.0/Modern-NetworkLayer.md index fcd9fd4dd5e03..daa8c71294c59 100644 --- a/website/versioned_docs/version-v4.0.0/Modern-NetworkLayer.md +++ b/website/versioned_docs/version-v4.0.0/Modern-NetworkLayer.md @@ -8,7 +8,6 @@ In order to know how to access your GraphQL server, Relay Modern requires develo Currently the easiest way to create a network layer is via a helper from the `relay-runtime` package: ```javascript - import { Environment, Network, @@ -50,7 +49,6 @@ const environment = new Environment({ }); export default environment; - ``` Note that this is a basic example to help you get started. This example could be extended with additional features such as request/response caching (enabled e.g. when `cacheConfig.force` is false) and uploading form data for mutations (the `uploadables` parameter). @@ -62,7 +60,6 @@ Relay modern makes no assumptions about what to cache and will garbage collect a You have to implement your own cache strategy. A simple solution is to use `RelayQueryResponseCache`(an in-memory cache): ```javascript - import { Environment, Network, @@ -126,7 +123,6 @@ const environment = new Environment({ }); export default environment; - ``` ## Custom open-source implementations diff --git a/website/versioned_docs/version-v4.0.0/Modern-PaginationContainer.md b/website/versioned_docs/version-v4.0.0/Modern-PaginationContainer.md index cae9a1f4bd1cb..e3110d00bdf74 100644 --- a/website/versioned_docs/version-v4.0.0/Modern-PaginationContainer.md +++ b/website/versioned_docs/version-v4.0.0/Modern-PaginationContainer.md @@ -24,7 +24,6 @@ However, when [specifying connection fragments](#createpaginationcontainer) for The purpose of the `@connection` directive is to allow Relay to uniquely identify different connections under a parent type. The `@connection` directive takes 2 arguments that help identify the connection: ```graphql - @connection(key: String!, filters: [String]) ``` @@ -37,7 +36,6 @@ The purpose of the `@connection` directive is to allow Relay to uniquely identif Specifying just the `key`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and the value of `$orderBy` (given that no `filters` were provided) @@ -53,13 +51,11 @@ fragment Feed_user on User { } } } - ``` Specifying `key` and `filters`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and /only/ the value of `$searchTerm`, i.e. @@ -77,7 +73,6 @@ fragment Feed_user on User { } } } - ``` ## `createPaginationContainer` @@ -85,7 +80,6 @@ fragment Feed_user on User { `createPaginationContainer` has the following signature: ```javascript - createPaginationContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, @@ -113,7 +107,6 @@ type ConnectionData = { startCursor: ?string, }, }; - ``` ### Arguments @@ -134,7 +127,6 @@ type ConnectionData = { The Component resulting from `createPaginationContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -145,7 +137,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -160,7 +151,6 @@ type Props = { `hasMore` is a function available on the `relay` [prop](#available-props). This function indicates whether there are more pages to fetch from the server or not. ```javascript - hasMore: () => boolean, ``` @@ -170,7 +160,6 @@ hasMore: () => boolean, `isLoading` is a function available on the `relay` [prop](#available-props). This function indicates if a previous call to [`loadMore()`](#loadmore) is still pending. This is convenient for avoiding duplicate load calls. ```javascript - isLoading: () => boolean, ``` @@ -180,7 +169,6 @@ isLoading: () => boolean, `loadMore` is a function available on the `relay` [prop](#available-props). You can call `loadMore()` to fetch more items from the server based on the `connectionConfig` provided to the container. This will return null if there are no more items to fetch, otherwise it will fetch more items and return a Disposable that can be used to cancel the fetch. ```javascript - loadMore(pageSize: number, callback: ?(error: ?Error) => void): ?Disposable ``` @@ -195,7 +183,6 @@ loadMore(pageSize: number, callback: ?(error: ?Error) => void): ?Disposable `refetchConnection` is a function available on the `relay` [prop](#available-props). You can call `refetchConnection` to restart pagination on a connection from scratch, with optionally a completely new set of variables to pass to the pagination `query`. This is useful for example if you are paginating over a collection based on a userID and the userID changes, you'd want to start paginating over the new collection for the new user. ```javascript - refetchConnection:( totalCount: number, callback: (error: ?Error) => void, @@ -213,7 +200,6 @@ refetchConnection:( ## Pagination Example ```javascript - // Feed.js import {createPaginationContainer, graphql} from 'react-relay'; @@ -308,5 +294,4 @@ module.exports = createPaginationContainer( ` } ); - ``` diff --git a/website/versioned_docs/version-v4.0.0/Modern-PersistedQueries.md b/website/versioned_docs/version-v4.0.0/Modern-PersistedQueries.md index 137cc2e23220c..ec03b69ba09c3 100644 --- a/website/versioned_docs/version-v4.0.0/Modern-PersistedQueries.md +++ b/website/versioned_docs/version-v4.0.0/Modern-PersistedQueries.md @@ -17,12 +17,10 @@ The relay compiler supports persisted queries which is useful because: In your `npm` script in `package.json`, run the relay compiler using the `--persist-output` flag: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` The `--persist-ouput` flag does 3 things: @@ -31,8 +29,7 @@ The `--persist-ouput` flag does 3 things: For example without `--persist-output`, a generated `ConcreteRequest` might look like below: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -49,8 +46,7 @@ The `--persist-ouput` flag does 3 things: With `--persist-output ` this becomes: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -68,12 +64,10 @@ The `--persist-ouput` flag does 3 things: 2. It generates a JSON file at the `` you specify containing a mapping from query ids to the corresponding operation texts. -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./src/queryMaps/queryMap.json" } - ``` The example above writes the complete query map file to `./src/queryMaps/queryMap.json`. You need to ensure all the directories @@ -83,8 +77,7 @@ leading to the `queryMap.json` file exist. You'll need to modify your network layer fetch implementation to pass a documentId parameter in the POST body instead of a query parameter: -```js - +```javascript function fetchQuery(operation, variables,) { return fetch('/graphql', { method: 'POST', @@ -100,7 +93,6 @@ function fetchQuery(operation, variables,) { return response.json(); }); } - ``` ## Executing Persisted Queries on the Server @@ -116,13 +108,11 @@ the query map file in a common location accessible to both the client and the se For applications where the client and server projects are separate, one option is to have an additional npm run script to push the query map at compile time to a location accessible by your server: -```js - +```javascript "scripts": { "push-queries": "node ./pushQueries.js", "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-ouput && npm run push-queries" } - ``` Some possibilities of what you can do in `./pushQueries.js`: @@ -146,8 +136,7 @@ database technologies you use, so we'll just cover the most common and basic exa If you use `express-graphql` and have access to the query map file, you can import the `--persist-output` JSON file directly and perform the matching using the `matchQueryMiddleware` from [relay-compiler-plus](https://github.com/yusinto/relay-compiler-plus). -```js - +```javascript import Express from 'express'; import expressGraphql from 'express-graphql'; import {matchQueryMiddleware} from 'relay-compiler-plus'; @@ -158,7 +147,6 @@ const app = Express(); app.use('/graphql', matchQueryMiddleware(queryMapJson), expressGraphql({schema})); - ``` ## Using `--persist-output` and `--watch` diff --git a/website/versioned_docs/version-v4.0.0/Modern-QueryRenderer.md b/website/versioned_docs/version-v4.0.0/Modern-QueryRenderer.md index 6f64e88f9afea..17d0f0e18cdc0 100644 --- a/website/versioned_docs/version-v4.0.0/Modern-QueryRenderer.md +++ b/website/versioned_docs/version-v4.0.0/Modern-QueryRenderer.md @@ -23,7 +23,6 @@ However, a `QueryRenderer` will not start loading its data until it is mounted, ## Example ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -55,5 +54,4 @@ const Example = (props) => { /> ); } - ``` diff --git a/website/versioned_docs/version-v4.0.0/Modern-RefetchContainer.md b/website/versioned_docs/version-v4.0.0/Modern-RefetchContainer.md index 35814dd9d8703..f32b8eb32c704 100644 --- a/website/versioned_docs/version-v4.0.0/Modern-RefetchContainer.md +++ b/website/versioned_docs/version-v4.0.0/Modern-RefetchContainer.md @@ -16,13 +16,11 @@ Table of Contents: `createRefetchContainer` has the following signature: ```javascript - createRefetchContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, refetchQuery: GraphQLTaggedNode, ): ReactComponentClass; - ``` ### Arguments @@ -37,7 +35,6 @@ createRefetchContainer( The Component resulting from `createRefetchContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -45,7 +42,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -61,7 +57,6 @@ type Props = { `refetch` has the following signature: ```javascript - type RefetchOptions = { force?: boolean, }; @@ -101,7 +96,6 @@ Returns a `Disposable` on which you could call `dispose()` to cancel the refetch In this simple example, let's assume we want to fetch the latest data for a `TodoItem` from the server: ```javascript - // TodoItem.js import {createRefetchContainer, graphql} from 'react-relay'; @@ -145,7 +139,6 @@ export default createRefetchContainer( } ` ); - ``` ### Loading more data @@ -153,7 +146,6 @@ export default createRefetchContainer( In this example we are using a Refetch Container to fetch more stories in a story feed component. ```javascript - import {createRefetchContainer, graphql} from 'react-relay'; class FeedStories extends React.Component { @@ -209,5 +201,4 @@ export default createRefetchContainer( } `, ); - ``` diff --git a/website/versioned_docs/version-v4.0.0/Modern-RelayCompat.md b/website/versioned_docs/version-v4.0.0/Modern-RelayCompat.md index 36632d3a8f1a1..f47dbd845ba3e 100644 --- a/website/versioned_docs/version-v4.0.0/Modern-RelayCompat.md +++ b/website/versioned_docs/version-v4.0.0/Modern-RelayCompat.md @@ -31,7 +31,6 @@ Relay Modern. The components using Relay Compat can be referred to by both other Relay Modern and Relay Classic components. ```javascript - const {createFragmentContainer, graphql} = require('react-relay/compat'); class TodoItem extends React.Component { @@ -47,5 +46,4 @@ module.exports = createFragmentContainer(TodoItem, graphql` isComplete } `); - ``` diff --git a/website/versioned_docs/version-v4.0.0/Modern-RelayEnvironment.md b/website/versioned_docs/version-v4.0.0/Modern-RelayEnvironment.md index b356b5deecdc5..ed75bc69d1f86 100644 --- a/website/versioned_docs/version-v4.0.0/Modern-RelayEnvironment.md +++ b/website/versioned_docs/version-v4.0.0/Modern-RelayEnvironment.md @@ -12,7 +12,6 @@ Most applications will create a single Environment instance and use it throughou To create an environment instance in Relay Modern, use the `RelayModernEnvironment` class: ```javascript - const { Environment, Network, @@ -30,7 +29,6 @@ const environment = new Environment({ network, store, }); - ``` For more details on creating a Network, see the [NetworkLayer guide](./network-layer). @@ -44,7 +42,6 @@ The example above did not configure a `handlerProvider`, which means that a defa If you wish to provide your own `handlerProvider`, you can do so: ```javascript - const { ConnectionHandler, ViewerHandler, @@ -60,5 +57,4 @@ function handlerProvider(handle) { `handlerProvider: No handler provided for ${handle}` ); } - ``` diff --git a/website/versioned_docs/version-v4.0.0/Modern-RelayStore.md b/website/versioned_docs/version-v4.0.0/Modern-RelayStore.md index 8bc27098b205e..56b91d3036791 100644 --- a/website/versioned_docs/version-v4.0.0/Modern-RelayStore.md +++ b/website/versioned_docs/version-v4.0.0/Modern-RelayStore.md @@ -16,7 +16,6 @@ Table of Contents: The `RecordSourceSelectorProxy` is the type of the `store` that [`updater` functions](./mutations#using-updater-and-optimisticupdater) receive as an argument. The following is the `RecordSourceSelectorProxy` interface: ```javascript - interface RecordSourceSelectorProxy { create(dataID: string, typeName: string): RecordProxy; delete(dataID: string): void; @@ -25,7 +24,6 @@ interface RecordSourceSelectorProxy { getRootField(fieldName: string): ?RecordProxy; getPluralRootField(fieldName: string): ?Array; } - ``` ### `create(dataID: string, typeName: string): RecordProxy` @@ -35,9 +33,7 @@ Creates a new record in the store given a `dataID` and the `typeName` as defined #### Example ```javascript - const record = store.create(dataID, 'Todo'); - ``` ### `delete(dataID: string): void` @@ -47,9 +43,7 @@ Deletes a record from the store given its `dataID`. #### Example ```javascript - store.delete(dataID); - ``` ### `get(dataID: string): ?RecordProxy` @@ -59,9 +53,7 @@ Retrieves a record from the store given its `dataID`. Returns a [`RecordProxy`]( #### Example ```javascript - const record = store.get(dataID); - ``` ### `getRoot(): RecordProxy` @@ -73,20 +65,16 @@ Returns the [`RecordProxy`](#recordproxy) representing the root of the GraphQL d Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - // Represents root query const root = store.getRoot(); - ``` ### `getRootField(fieldName: string): ?RecordProxy` @@ -98,19 +86,15 @@ Retrieves a root field from the store given the `fieldName`, as defined by the G Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - const viewer = store.getRootField('viewer'); - ``` ### `getPluralRootField(fieldName: string): ?Array` @@ -122,19 +106,15 @@ Retrieves a root field that represents a collection from the store given the `fi Given the GraphQL document: ```graphql - nodes(first: 10) { # ... } - ``` Usage: ```javascript - const nodes = store.getPluralRootField('nodes'); - ``` ## RecordProxy @@ -142,7 +122,6 @@ const nodes = store.getPluralRootField('nodes'); The `RecordProxy` serves as an interface to mutate records: ```javascript - interface RecordProxy { copyFieldsFrom(sourceRecord: RecordProxy): void; getDataID(): string; @@ -167,7 +146,6 @@ interface RecordProxy { ): RecordProxy; setValue(value: mixed, name: string, arguments?: ?Object): RecordProxy; } - ``` ### `getDataID(): string` @@ -177,9 +155,7 @@ Returns the dataID of the current record. #### Example ```javascript - const id = record.getDataID(); - ``` ### `getType(): string` @@ -189,7 +165,6 @@ Gets the type of the current record, as defined by the GraphQL schema. #### Example ```javascript - const type = user.getType(); // User ``` @@ -203,20 +178,16 @@ Gets the value of a field in the current record given the field name. Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - const name = viewer.getValue('name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. @@ -226,20 +197,16 @@ Optionally, if the field takes arguments, you can pass a bag of `variables`. Given the GraphQL document: ```graphql - viewer { id name(arg: $arg) } - ``` Usage: ```javascript - const name = viewer.getValue('name', {arg: 'value'}); - ``` ### `getLinkedRecord(name: string, arguments?: ?Object): ?RecordProxy` @@ -251,23 +218,19 @@ Retrieves a record associated with the current record given the field name, as d Given the GraphQL document: ```graphql - rootField { viewer { id name } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -277,22 +240,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { viewer(arg: $arg) { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {arg: 'value'}); - ``` ### `getLinkedRecords(name: string, arguments?: ?Object): ?Array` @@ -304,22 +263,18 @@ Retrieves the set of records associated with the current record given the field Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const nodes = rootField.getLinkedRecords('nodes'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -329,22 +284,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { nodes(first: $count) { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {count: 10}); - ``` ### `getOrCreateLinkedRecord(name: string, typeName: string, arguments?: ?Object)` @@ -356,19 +307,16 @@ Retrieves the a record associated with the current record given the field name, Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = rootField.getOrCreateLinkedRecord('viewer', 'User'); // Will create if it doesn't exist @@ -383,28 +331,22 @@ Mutates the current record by setting a new value on the specified field. Return Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - viewer.setValue('New Name', 'name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. ```javascript - viewer.setValue('New Name', 'name', {arg: 'value'}); - ``` ### `copyFieldsFrom(sourceRecord: RecordProxy): void` @@ -414,7 +356,6 @@ Mutates the current record by copying the fields over from the passed in record #### Example ```javascript - const record = store.get(id1); const otherRecord = store.get(id2); record.copyFieldsFrom(otherRecord); // Mutates `record` @@ -430,19 +371,16 @@ Mutates the current record by setting a new linked record on the given the field Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = store.create(/* ... */)'' rootField.setLinkedRecord(newViewer, 'viewer'); // @@ -460,19 +398,16 @@ Mutates the current record by setting a new set of linked records on the given t Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newNode = store.create(/* ... */); const newNodes = [...rootField.getLinkedRecords('nodes'), newNode]; @@ -487,7 +422,6 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl `ConnectionHandler` is a utility module exposed by `relay-runtime` that aids in the manipulation of connections. `ConnectionHandler` exposes the following interface: ```javascript - interface ConnectionHandler { getConnection( record: RecordProxy, @@ -512,7 +446,6 @@ interface ConnectionHandler { ): void, deleteNode(connection: RecordProxy, nodeID: string): void } - ``` ### `getConnection(record: RecordProxy, key: string, filters?: ?Object)` @@ -522,7 +455,6 @@ Given a record and a connection key, and optionally a set of filters, `getConnec First, let's take a look at a plain connection: ```graphql - fragment FriendsFragment on User { friends(first: 10) { edges { @@ -532,26 +464,22 @@ fragment FriendsFragment on User { } } } - ``` Accessing a plain connection field like this is the same as other regular field: ```javascript - // The `friends` connection record can be accessed with: const user = store.get(userID); const friends = user && user.getLinkedRecord(user, 'friends'); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` In a [pagination container](./pagination-container), we usually annotate the actual connection field with `@connection` to tell Relay which part needs to be paginated: ```graphql - fragment FriendsFragment on User { friends(first: 10, orderby: "firstname") @connection( key: "FriendsFragment_friends", @@ -563,7 +491,6 @@ fragment FriendsFragment on User { } } } - ``` For connections like the above, `ConnectionHandler` helps us find the record: @@ -581,7 +508,6 @@ const friends = ConnectionHandler.getConnection( ); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` ### Edge creation and insertion @@ -611,7 +537,6 @@ ConnectionHandler.insertEdgeAfter(friends, edge); // No cursor provided, Insert the edge at the front: ConnectionHandler.insertEdgeBefore(friends, edge); - ``` ### `deleteNode(connection: RecordProxy, nodeID: string): void` @@ -625,5 +550,4 @@ Given a connection, deletes any edges whose id matches the given id. const user = store.get(userID); const friends = ConnectionHandler.getConnection(user, 'friends'); ConnectionHandler.deleteNode(friends, idToDelete); - ``` diff --git a/website/versioned_docs/version-v4.0.0/Modern-Subscriptions.md b/website/versioned_docs/version-v4.0.0/Modern-Subscriptions.md index 3521d610d6bc6..a104adde23e89 100644 --- a/website/versioned_docs/version-v4.0.0/Modern-Subscriptions.md +++ b/website/versioned_docs/version-v4.0.0/Modern-Subscriptions.md @@ -6,7 +6,6 @@ original_id: subscriptions Relay exposes the following APIs to create subscriptions. ```javascript - const {requestSubscription} = require('react-relay'); type Variables = {[name: string]: any}; @@ -27,7 +26,6 @@ requestSubscription( configs?: Array, }, ) => Disposable; - ``` The function returns a `Disposable` on which you could call `dispose()` to cancel the refetch. @@ -53,7 +51,6 @@ appropriate when you are only changing the properties of existing records that can be identified by their `id`: ```javascript - const { requestSubscription, graphql, @@ -87,7 +84,6 @@ requestSubscription( onError: error => console.error(error), } ); - ``` # Updating the client on each response @@ -97,7 +93,6 @@ Relay's in-memory cache when each subscription response is received. To do so, pass an `updater` function: ```javascript - const {ConnectionHandler} = require('relay-runtime'); requestSubscription( @@ -123,5 +118,4 @@ requestSubscription( }, }, ); - ``` diff --git a/website/versioned_docs/version-v4.0.0/Modern-TestingRelayComponents.md b/website/versioned_docs/version-v4.0.0/Modern-TestingRelayComponents.md index 7262fe61558f5..3c38262f29c51 100644 --- a/website/versioned_docs/version-v4.0.0/Modern-TestingRelayComponents.md +++ b/website/versioned_docs/version-v4.0.0/Modern-TestingRelayComponents.md @@ -65,7 +65,6 @@ MockPayloadGenerator may drastically simplify the process of creating and mainta Example of a simple Mock Resolver: ```javascript - { ID() { // Return mock value for a scalar filed with type ID @@ -76,13 +75,11 @@ Example of a simple Mock Resolver: return "Lorem Ipsum" } } - ``` It is possible to define more resolvers for Object types ```javascript - { // This will be the default values for User object in the query response User() { @@ -95,7 +92,6 @@ It is possible to define more resolvers for Object types }; }, } - ``` ### Mock Resolver Context @@ -103,7 +99,6 @@ It is possible to define more resolvers for Object types The first argument of the MockResolver is the object that contains Mock Resolver Context. It is possible to return dynamic values from mock resolvers based on the context - for instance, name or alias of the field, a path in the selection, arguments, or parent type. ```javascript - { String(context) { if (context.name === 'zip') { @@ -117,7 +112,6 @@ The first argument of the MockResolver is the object that contains Mock Resolver } } } - ``` ### ID Generation @@ -125,14 +119,12 @@ The first argument of the MockResolver is the object that contains Mock Resolver The second argument of the Mock Resolver its a function that will generate a sequence of integers, usefull to generate unique ids in the tests ```javascript - { // will generate strings "my-id-1", "my-id-2", etc. ID(_, generateId) { return `my-id-${generateId()}`; }, } - ``` ### @relay_test_operation @@ -142,7 +134,6 @@ Most of GraphQL type information for a specific field in the selection is not av Operation with the @relay_test_operation directive will have additional metadata that will contain GraphQL type info for fields in the operation's selection. And it will improve the quality of the generated data. You also will be able to define Mock resolvers for Scalar (not only ID and String) and Abstract types: ```javascript - { Float() { return 123.456; @@ -160,7 +151,6 @@ Operation with the @relay_test_operation directive will have additional metadata }; } } - ``` ## Examples @@ -170,7 +160,6 @@ Operation with the @relay_test_operation directive will have additional metadata Using `createMockEnvironment` and `MockPayloadGenerator` allows writing concise tests for components that are using Relay Containers and Renderers. Both those modules can be imported from `relay-test-utils` ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { @@ -223,7 +212,6 @@ test('Error State', () => { renderer.root.find(item => (item.props.testID = 'errorMessage')), ).toBeDefined(); }); - ``` ### Fragment Container Tests @@ -231,7 +219,6 @@ test('Error State', () => { Essentially, in the example above will `resolveMostRecentOperation` will generate data for all child fragment containers (pagination, refetch). But, usually the Root Components container may have many child fragment components and you may want to exercise a specific Fragment Container. The solution for that would be to wrap you fragment container with the QueryRenderer that renders a Query that's spreads fragments from you fragment container. ```javascript - test('Fragment Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -262,7 +249,6 @@ test('Fragment Container', () => { expect(renderer).toMatchSnapshot(); }); - ``` ### Pagination Container Test @@ -270,7 +256,6 @@ test('Fragment Container', () => { Essentially, tests for Pagination container are not different from Fragment Container tests. But we can do more here, we can actually see how the pagination works - we can assert the behavior of our components when performing pagination (load more, refetch). ```javascript - // Pagination Example test('Pagionation Container', () => { const environment = createMockEnvironment(); @@ -344,7 +329,6 @@ test('Pagionation Container', () => { We can use similar approach here with wrapping container with Query Renderer. And for the sake of completeness, we will add example here: ```javascript - test('Refetch Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -386,7 +370,6 @@ test('Refetch Container', () => { ); // expect(renderer).toMatchSnapshot(); }); - ``` ### Mutations @@ -394,7 +377,6 @@ test('Refetch Container', () => { Mutations itself are operations so we can test them independently (unit-test) for specific mutation, or in combination with the view from which this mutation is called. ```javascript - // Say, you have a mutation function function sendMutation(environment, onCompleted, onError, variables) commitMutation(environment, { @@ -417,7 +399,6 @@ test('it should send mutation', () => { ); expect(onCompleted).toBeCalled(); }); - ``` ### Subscription @@ -425,7 +406,6 @@ test('it should send mutation', () => { We can test subscription in a similar way we test mutations ```javascript - // Example subscribe function function subscribe(environment, onNext, onError, variables) requestSubscription(environment, { @@ -448,7 +428,6 @@ test('it should subscribe', () => { ); expect(onNext).toBeCalled(); }); - ``` ### Example with `queueOperationResolver` @@ -456,7 +435,6 @@ test('it should subscribe', () => { With `queueOpeararionResolver` it possible to define responses for operations that will be executed on the environment ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { diff --git a/website/versioned_docs/version-v4.0.0/Modern-TypeEmission.md b/website/versioned_docs/version-v4.0.0/Modern-TypeEmission.md index c6cad1e53d3b2..e3bb438428672 100644 --- a/website/versioned_docs/version-v4.0.0/Modern-TypeEmission.md +++ b/website/versioned_docs/version-v4.0.0/Modern-TypeEmission.md @@ -16,7 +16,6 @@ In this example the emitted type-information would require the variables object #### Flow ```javascript - /** * export type ExampleQueryVariables = {| * +artistID: string @@ -44,7 +43,6 @@ const variables: ExampleQueryVariables = { #### TypeScript ```javascript - /** * export type ExampleQueryVariables = { * readonly artistID: string @@ -79,7 +77,6 @@ In this example the emitted type-information describes the response data availab #### Flow ```javascript - /** * export type ExampleQueryResponse = {| * +artist: ?{| @@ -110,7 +107,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * export type ExampleQueryResponse = { * readonly artist?: { @@ -146,7 +142,6 @@ Similarly, in this example the emitted type-information describes the prop data #### Flow ```javascript - /** * export type ExampleFragment_artist = {| * +name: string @@ -172,7 +167,6 @@ export const ExampleFragment = createFragmentContainer( #### TypeScript ```javascript - /** * export type ExampleFragment_artist = { * readonly name: string @@ -206,7 +200,6 @@ Consider a component that composes the above fragment container example. In this #### Flow ```javascript - /** * import type { FragmentReference } from "relay-runtime"; * declare export opaque type ExampleFragment_artist$ref: FragmentReference; @@ -250,7 +243,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * declare const _ExampleFragment_artist$ref: unique symbol; * export type ExampleFragment_artist$ref = typeof _ExampleFragment_artist$ref; @@ -315,7 +307,6 @@ $ relay-compiler --artifactDirectory ./src/__generated__ […] ["relay", { "artifactDirectory": "./src/__generated__" }] ] } - ``` It is recommended to alias this directory in your module resolution configuration such that you don’t need to specify relative paths in your source files. This is what is also done in the above examples, where artifacts are imported from a `__generated__` alias, rather than relative paths like `../../../../__generated__`. diff --git a/website/versioned_docs/version-v4.0.0/Modern-UpgradingSetVariables.md b/website/versioned_docs/version-v4.0.0/Modern-UpgradingSetVariables.md index d5b086fafce20..ff73feec04f8b 100644 --- a/website/versioned_docs/version-v4.0.0/Modern-UpgradingSetVariables.md +++ b/website/versioned_docs/version-v4.0.0/Modern-UpgradingSetVariables.md @@ -36,7 +36,6 @@ fragment on User { # ... } } - ``` This should be upgraded to use a [`PaginationContainer`](./pagination-container). @@ -61,7 +60,6 @@ fragment on User { # ... } } - ``` This can be upgraded by using a [`RefetchContainer`](./refetch-container) which allows you to specify the exact query to use to fetch the new data. @@ -86,7 +84,6 @@ fragment on FeedbackTarget { # ... } } - ``` This can be upgraded by conditionally rendering a [`QueryRenderer`](./query-renderer) which will load the data once it is rendered. The code overhead of doing this is dramatically reduced with the new API. diff --git a/website/versioned_docs/version-v4.0.0/Modern-fetchQuery.md b/website/versioned_docs/version-v4.0.0/Modern-fetchQuery.md index e9dcf908db91a..d266ae9d7c67a 100644 --- a/website/versioned_docs/version-v4.0.0/Modern-fetchQuery.md +++ b/website/versioned_docs/version-v4.0.0/Modern-fetchQuery.md @@ -6,7 +6,6 @@ original_id: fetch-query You can use the `fetchQuery` function to imperatively make GraphQL Requests. This is useful for cases where you want to make requests outside of React but still utilize the Relay store and network layer. ```javascript - import {fetchQuery, graphql} from 'relay-runtime'; const query = graphql` @@ -25,7 +24,6 @@ fetchQuery(environment, query, variables) .then(data => { // access the graphql response }); - ``` ## Arguments diff --git a/website/versioned_docs/version-v4.0.0/PrinciplesAndArchitecture-Compiler.md b/website/versioned_docs/version-v4.0.0/PrinciplesAndArchitecture-Compiler.md index c195491682b1f..fcd0490cb724f 100644 --- a/website/versioned_docs/version-v4.0.0/PrinciplesAndArchitecture-Compiler.md +++ b/website/versioned_docs/version-v4.0.0/PrinciplesAndArchitecture-Compiler.md @@ -74,7 +74,6 @@ foo { # type FooType foo { id } - ``` - `SkipRedundantNodeTransform`: A more advanced version of flattening, this eliminates more complex cases of field duplication such as when a field is fetched both unconditionally and conditionally, or is fetched by two different sub-fragments. For example: @@ -97,7 +96,6 @@ foo { id } } - ``` - `GenerateRequisiteFieldTransform`: This optional, Relay-specific transform inserts `id` fields for globally identifiable objects and `__typename` fields wherever the type cannot be statically determined (e.g. for unions). diff --git a/website/versioned_docs/version-v4.0.0/PrinciplesAndArchitecture-Runtime.md b/website/versioned_docs/version-v4.0.0/PrinciplesAndArchitecture-Runtime.md index 9491d290c146f..e9221631a701d 100644 --- a/website/versioned_docs/version-v4.0.0/PrinciplesAndArchitecture-Runtime.md +++ b/website/versioned_docs/version-v4.0.0/PrinciplesAndArchitecture-Runtime.md @@ -77,7 +77,6 @@ RecordSource { city: 'Seattle', } } - ``` [1] Note that GraphQL itself does not impose this constraint, and Relay Runtime may also be used for schemas that do not conform to it. For example, both systems can be used to query a single denormalized table. However, many of the features that Relay Runtime provides, such as caching and normalization, work best when the data is represented as a normalized graph with stable identities for discrete pieces of information. diff --git a/website/versioned_docs/version-v4.0.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md b/website/versioned_docs/version-v4.0.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md index a8842ae084922..9ff8a7840df90 100644 --- a/website/versioned_docs/version-v4.0.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md +++ b/website/versioned_docs/version-v4.0.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md @@ -12,7 +12,6 @@ In this article we'll explore what it means to build a GraphQL client framework Imagine we have a simple application that fetches a list of stories, and some details about each one. Here's how that might look in resource-oriented REST: ```javascript - // Fetch the list of story IDs but not their details: rest.get('/stories').then(stories => // This resolves to a list of items with linked resources: @@ -25,13 +24,11 @@ rest.get('/stories').then(stories => // `[ { id: "...", text: "..." } ]` console.log(stories); }); - ``` Note that this approach requires _n+1_ requests to the server: 1 to fetch the list, and _n_ to fetch each item. With GraphQL we can fetch the same data in a single network request to the server (without creating a custom endpoint that we'd then have to maintain): ```javascript - graphql.get(`query { stories { id, text } }`).then( stories => { // A list of story items: @@ -39,7 +36,6 @@ graphql.get(`query { stories { id, text } }`).then( console.log(stories); } ); - ``` So far we're just using GraphQL as a more efficient version of typical REST approaches. Note two important benefits in the GraphQL version: @@ -56,7 +52,6 @@ Repeatedly refetching information from the server can get quite slow. For exampl In a resource-oriented REST system, we can maintain a **response cache** based on URIs: ```javascript - var _cache = new Map(); rest.get = uri => { if (!_cache.has(uri)) { @@ -64,13 +59,11 @@ rest.get = uri => { } return _cache.get(uri); }; - ``` Response-caching can also be applied to GraphQL. A basic approach would work similarly to the REST version. The text of the query itself can be used as a cache key: ```javascript - var _cache = new Map(); graphql.get = queryText => { if (!_cache.has(queryText)) { @@ -78,7 +71,6 @@ graphql.get = queryText => { } return _cache.get(queryText); }; - ``` Now, requests for previously cached data can be answered immediately without making a network request. This is a practical approach to improving the perceived performance of an application. However, this method of caching can cause problems with data consistency. @@ -90,7 +82,6 @@ With GraphQL it is very common for the results of multiple queries to overlap. H ``` query { stories { id, text, likeCount } } - ``` and then later refetch one of the stories whose `likeCount` has since been incremented: @@ -98,7 +89,6 @@ and then later refetch one of the stories whose `likeCount` has since been incre ``` query { story(id: "123") { id, text, likeCount } } - ``` We'll now see different `likeCount`s depending on how the story is accessed. A view that uses the first query will see an outdated count, while a view using the second query will see the updated count. @@ -119,7 +109,6 @@ query { } } } - ``` And here's a possible response: @@ -134,13 +123,11 @@ query: { } } } - ``` Although the response is hierarchical, we'll cache it by flattening all the records. Here is an example of how Relay would cache this query response: ```javascript - Map { // `story(id: "1")` 1: Map { @@ -152,7 +139,6 @@ Map { name: 'Jan', }, }; - ``` This is only a simple example: in reality the cache must handle one-to-many associations and pagination (among other things). @@ -182,7 +168,6 @@ The first query was for a list of stories: ``` query { stories { id, text, likeCount } } - ``` With a normalized response cache, a record would be created for each story in the list. The `stories` field would store links to each of these records. @@ -192,7 +177,6 @@ The second query refetched the information for one of those stories: ``` query { story(id: "123") { id, text, likeCount } } - ``` When this response is normalized, Relay can detect that this result overlaps with existing data based on its `id`. Rather than create a new record, Relay will update the existing `123` record. The new `likeCount` is therefore available to _both_ queries, as well as any other query that might reference this story. @@ -215,7 +199,6 @@ query { } } } - ``` After initially fetching this story our cache might be as follows. Note that the story and comment both link to the same record as `author`: @@ -242,7 +225,6 @@ Map { author: Link(2), }, } - ``` The author of this story also commented on it — quite common. Now imagine that some other view fetches new information about the author, and her profile photo has changed to a new URI. Here's the _only_ part of our cached data that changes: @@ -256,7 +238,6 @@ Map { photo: 'http://.../photo2.jpg', }, } - ``` The value of the `photo` field has changed; and therefore the record `2` has also changed. And that's it. Nothing else in the _cache_ is affected. But clearly our _view_ needs to reflect the update: both instances of the author in the UI (as story author and comment author) need to show the new photo. @@ -273,7 +254,6 @@ ImmutableMap { }, 3: ImmutableMap // same as before } - ``` If we replace `2` with a new immutable record, we'll also get a new immutable instance of the cache object. However, records `1` and `3` are untouched. Because the data is normalized, we can't tell that `story`'s contents have changed just by looking at the `story` record alone. @@ -299,7 +279,6 @@ mutation StoryLike($storyID: String) { likeCount } } - ``` Notice that we're querying for data that _may_ have changed as a result of the mutation. An obvious question is: why can't the server just tell us what changed? The answer is: it's complicated. GraphQL abstracts over _any_ data storage layer (or an aggregation of multiple sources), and works with any programming language. Furthermore, the goal of GraphQL is to provide data in a form that is useful to product developers building a view. diff --git a/website/versioned_docs/version-v4.0.0/PrinciplesAndArchitecture-ThinkingInRelay.md b/website/versioned_docs/version-v4.0.0/PrinciplesAndArchitecture-ThinkingInRelay.md index d6f1572d5590b..4fb68372ec4b3 100644 --- a/website/versioned_docs/version-v4.0.0/PrinciplesAndArchitecture-ThinkingInRelay.md +++ b/website/versioned_docs/version-v4.0.0/PrinciplesAndArchitecture-ThinkingInRelay.md @@ -30,13 +30,11 @@ fragment Story_story on Story { photo } } - ``` And this fragment can then be used to define the Story container: ```javascript - const {createFragmentContainer, graphql} = require('react-relay'); // Plain React component. @@ -64,7 +62,6 @@ const StoryContainer = createFragmentContainer(Story, { In React, rendering a view requires two inputs: the _component_ to render, and a _root_ DOM (UI) node to render into. Rendering Relay containers is similar: we need a _container_ to render, and a _root_ in the graph from which to start our query. We also must ensure that the queries for the container are executed and may want to show a loading indicator while data is being fetched. Similar to `ReactDOM.render(component, domNode)`, Relay provides `` for this purpose. The `query` and `variables` define what data to fetch and `render` defines what to render. Here's how we might render ``: ```javascript - ReactDOM.render( { ); } } - ``` The above code is doing something very similar to our [previous example](#rendering-graphql-queries). However, we are now passing a `$userID` variable to the GraphQL query via the `variables` prop. This has a couple of important implications: @@ -228,7 +216,6 @@ Now that we know how to define and fetch queries, let's actually start building First, let's start at the bottom. Suppose that we want to render a component that simply displays a given todo item's text and completed state: ```javascript - // Todo.js import React from 'react'; @@ -258,7 +245,6 @@ export default class Todo extends React.Component { ); } } - ``` From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L107), we know that we can query this data on the `Todo` type. However, we don't want to have to send a separate query for each todo item; that would defeat the purpose of using GraphQL over a traditional REST API. We could manually query for these fields directly in our `QueryRenderer` query, but that would hurt re-usability: what if we want to query the same set of fields as part of a different query? Additionally, we wouldn't know which component needs the data we're querying, which is a problem Relay directly tries to address. @@ -266,18 +252,15 @@ From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/dat Instead, we can define a reusable [Fragment](http://graphql.org/learn/queries/#fragments), which allows us to define a set of fields on a type and reuse them within our queries wherever we need to: ```graphql - fragment TodoItemFragment on Todo { complete text } - ``` Our component can then use this fragment to declare its data dependency on the `Todo` GraphQL type: ```javascript - // Todo.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -340,7 +323,6 @@ Before proceeding, don't forget to run the Relay Compiler with `yarn relay`. Given that [Fragment Containers](./fragment-container) are just React components, we can compose them as such. We can even re-use fragment containers within other fragment containers. As an example, let's see how we would define a `TodoList` component that just renders a list of todo items, and whether all have been completed or not: ```javascript - // TodoList.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -401,7 +383,6 @@ export default createFragmentContainer( `, }, ); - ``` As with the first fragment container we defined, `TodoList` declares it's data dependencies via a fragment. However, this component additionally re-uses the fragment previously defined by the `Todo` component, and passes the appropriate data when rendering the child `Todo` components (a.k.a. fragment containers). @@ -416,7 +397,6 @@ fragment containers do not directly fetch data. Instead, containers declare a sp A `QueryRenderer` rendering these fragment containers could look like the following: ```javascript - // ViewerTodoList.js import React from 'react'; import {graphql, QueryRenderer} from 'react-relay'; @@ -457,7 +437,6 @@ export default class ViewerTodoList extends React.Component { ); } } - ``` Check out our docs for [Fragment Containers](./fragment-container) for more details, and our guides on [Refetch](./refetch-container) and [Pagination](./pagination-container) for more advanced usage of containers. @@ -469,7 +448,6 @@ Now that we know how to query for and render data, let's move on to changing our From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L35), we know that we have some mutations available to us, so let's start by writing a mutation to change the `complete` status of a given todo item (i.e. mark or unmark it as done): ```graphql - mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { changeTodoStatus(input: $input) { todo { @@ -478,7 +456,6 @@ mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { } } } - ``` This mutation allows us to query back some data as a [result of the mutation](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L18), so we're going to query for the updated `complete` status on the todo item. @@ -486,7 +463,6 @@ This mutation allows us to query back some data as a [result of the mutation](ht In order to execute this mutation in Relay, we're going to write a new mutation using Relay's `commitMutation` api: ```javascript - // ChangeTodoStatusMutation.js import {graphql, commitMutation} from 'react-relay'; @@ -520,7 +496,6 @@ function commit( } export default {commit}; - ``` Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mutation to the server and, in our case, upon receiving a response it will automatically update the local data store with the latest data from the server. This also means that upon receiving the response, Relay will ensure that any components (i.e. containers) that depend on the updated data are re-rendered. @@ -528,7 +503,6 @@ Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mut In order to actually use this mutation in our component, we could update our `Todo` component in the following way: ```javascript - // Todo.js // ... @@ -562,7 +536,6 @@ In order to make the experience better, we can configure our mutation to do an o In Relay, there's a couple of options we can pass to `commitMutation` to enable optimistic updates. Let's see what that would look like in our `ChangeTodoStatusMutation`: ```javascript - // ChangeTodoStatusMutation.js // ... @@ -597,7 +570,6 @@ function commit( } export default {commit}; - ``` In the simplest case above, we just need to pass an `optimisticResponse` option, which should refer to an object having the same shape as the mutation response payload. When we pass this option, Relay will know to immediately update our local data with the optimistic response, and then update it with the actual server response or roll it back if an error occurs. diff --git a/website/versioned_docs/version-v5.0.0/Modern-ConvertingMutations.md b/website/versioned_docs/version-v5.0.0/Modern-ConvertingMutations.md index 08ad2e998cb2d..8f4bdc1d8e0d2 100644 --- a/website/versioned_docs/version-v5.0.0/Modern-ConvertingMutations.md +++ b/website/versioned_docs/version-v5.0.0/Modern-ConvertingMutations.md @@ -12,19 +12,16 @@ FatQueries in Relay Classic mutations was a concept that was confusing for a num Example of existing fat query: ```javascript - RelayClassic.QL` fragment on MarkReadNotificationResponsePayload @relay(pattern: true) { notification } `; - ``` Example of converted mutation query: ```javascript - graphql` mutation MarkReadNotificationMutation( $input: MarkReadNotificationData! @@ -37,7 +34,6 @@ graphql` } } `; - ``` ## Migrating Configs @@ -67,7 +63,6 @@ This is no longer needed in Compatibility Mode for neither environments. Simply Take this example of a simple mutation in Relay Classic: ```javascript - class LikeStoryMutation extends RelayClassic.Mutation { getMutation() { return RelayClassic.QL`mutation {likeStory}`; @@ -106,7 +101,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { `, }; } - ``` ### Converting `getMutation()` and `getFatQuery()` @@ -114,7 +108,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { We combine these two into a regular GraphQL mutation, which list out specific fields that needs to be updated. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story(data: $input) { @@ -126,7 +119,6 @@ const mutation = graphql` } } `; - ``` ### Converting `getConfigs()` @@ -138,13 +130,11 @@ As specified above, `FIELDS_CHANGE` configs can be omitted. To convert `getVariables()`, we take the return value from the original function and wrap it in an object that contains a property that matches the variable name for the mutation. In this case, the mutation has a `input` variable that is of type `LikeStoryData`. ```javascript - const variables = { input: { storyID: args.storyID } } - ``` ### Final Result @@ -152,7 +142,6 @@ const variables = { As you can see, our resulting mutation is a lot simpler and more like regular GraphQL than the Relay Classic version we started out with. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story { @@ -178,7 +167,6 @@ function commit(environment: CompatEnvironment, args) { variables, }); } - ``` See [Mutation](./mutations) for additional options on `commitMutation` for more complex mutations. diff --git a/website/versioned_docs/version-v5.0.0/Modern-FragmentContainer.md b/website/versioned_docs/version-v5.0.0/Modern-FragmentContainer.md index 423f446cbb054..6a40bbcfb5d0a 100644 --- a/website/versioned_docs/version-v5.0.0/Modern-FragmentContainer.md +++ b/website/versioned_docs/version-v5.0.0/Modern-FragmentContainer.md @@ -17,12 +17,10 @@ Table of Contents: `createFragmentContainer` has the following signature: ```javascript - createFragmentContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, ): ReactComponentClass; - ``` ### Arguments @@ -43,7 +41,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -58,7 +55,6 @@ To start, let's build the plain React version of a hypothetical `` c Here's a basic implementation of `` that ignores styling in order to highlight the functionality: ```javascript - // TodoItem.js class TodoItem extends React.Component { render() { @@ -78,7 +74,6 @@ class TodoItem extends React.Component { ); } } - ``` ### Data Dependencies With GraphQL @@ -86,7 +81,6 @@ class TodoItem extends React.Component { In Relay, data dependencies are described using [GraphQL](https://github.com/facebook/graphql). For ``, the dependency can be expressed as follows. Note that this exactly matches the shape that the component expected for the `item` prop. ```javascript - graphql` # This fragment only applies to objects of type 'Todo'. fragment TodoItem_item on Todo { @@ -102,7 +96,6 @@ graphql` Given the plain React component and a GraphQL fragment, we can now define a Fragment Container to specify this component's data requirements. Let's look at the code first and then see what's happening: ```javascript - // TodoItem.js import {createFragmentContainer, graphql} from 'react-relay'; @@ -120,7 +113,6 @@ export default createFragmentContainer(TodoItem, { } `, }); - ``` ## Container Composition @@ -134,7 +126,6 @@ Let's explore how this works via a `` component that composes the `< View composition is _exactly_ what you're used to — Relay containers are just standard React components. Here's the `` component: ```javascript - class TodoList extends React.Component { render() { // Expects a `list` with a string `title`, as well as the information @@ -151,7 +142,6 @@ class TodoList extends React.Component { ); } } - ``` ### Composing Fragments @@ -159,7 +149,6 @@ class TodoList extends React.Component { Fragment composition works similarly — a parent container's fragment composes the fragment for each of its children. In this case, `` needs to fetch information about the `Todo`s that are required by ``. ```javascript - class TodoList extends React.Component // as above export default createFragmentContainer(TodoList, { @@ -176,7 +165,6 @@ export default createFragmentContainer(TodoList, { } `, }); - ``` Note that when composing fragments, the type of the composed fragment must match the field on the parent in which it is embedded. For example, it wouldn't make sense to embed a fragment of type `Story` into a parent's field of type `User`. Relay and GraphQL will provide helpful error messages if you get this wrong (and if they aren't helpful, let us know!). @@ -190,7 +178,6 @@ When defining a fragment, you can use the [`@argumentDefinitions`](./graphql-in- For example, let's redefine our `TodoList_list` fragment to take some arguments using `@argumentDefinitions`: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -200,7 +187,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` Any arguments defined inside `@argumentDefinitions` will be local variables available inside the fragment's scope. However, a fragment can also reference global variables that were defined in the root query. @@ -212,11 +198,9 @@ In order to pass arguments to a fragment that has `@argumentDefinitions`, you ne Following our `TodoList_list` example, we would pass arguments to the fragment like so: ```graphql - query TodoListQuery($count: Int, $userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` ## Rendering Containers diff --git a/website/versioned_docs/version-v5.0.0/Modern-GraphQLInRelay.md b/website/versioned_docs/version-v5.0.0/Modern-GraphQLInRelay.md index 2db8e32cc7ed9..ae28027b32a20 100644 --- a/website/versioned_docs/version-v5.0.0/Modern-GraphQLInRelay.md +++ b/website/versioned_docs/version-v5.0.0/Modern-GraphQLInRelay.md @@ -14,7 +14,6 @@ Table of Contents: The `graphql` template tag provided by Relay serves as the mechanism to write queries, fragments, mutations or subscriptions in the [GraphQL](http://graphql.org/learn/) language. For example: ```javascript - import {graphql} from 'react-relay'; graphql` @@ -24,7 +23,6 @@ graphql` } } `; - ``` The result of using the `graphql` template tag is a `GraphQLTaggedNode`; a runtime representation of the GraphQL document which can be used to define [Query Renderers](./query-renderer), [Fragment Containers](./fragment-container), [Refetch Containers](./refetch-container), [Pagination Containers](./pagination-container), etc. @@ -42,11 +40,9 @@ Relay uses directives to add additional information to GraphQL documents, which `@arguments` is a directive used to pass arguments to a fragment that was defined using [`@argumentDefinitions`](#argumentdefinitions). For example: ```graphql - query TodoListQuery($userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -56,7 +52,6 @@ See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fr `@argumentDefinitions` is a directive used to specify arguments taken by a fragment. For example: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -66,7 +61,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -80,7 +74,6 @@ When using the [Pagination Container](./pagination-container), Relay expects con When defining a fragment for use with a Fragment container, you can use the `@relay(plural: true)` directive to indicate that container expects the prop for that fragment to be a list of items instead of a single item. A query or parent that spreads a `@relay(plural: true)` fragment should do so within a plural field (ie a field backed by a [GraphQL list](http://graphql.org/learn/schema/#lists-and-non-null). For example: ```javascript - // Plural fragment definition graphql` fragment TodoItems_items on TodoItem @relay(plural: true) { @@ -95,7 +88,6 @@ fragment TodoApp_app on App { ...TodoItem_items } } - ``` ### `@relay(mask: Boolean)` @@ -113,7 +105,6 @@ Keep in mind that it is typically considered an **anti-pattern** to create a sin In the example below, the `user` prop will include the data for `id` and `name` fields wherever `...Component_internUser` is included, instead of Relay's normal behavior to mask those fields: ```javascript - graphql` fragment Component_internUser on InternUser @relay(mask: false) { id @@ -141,7 +132,6 @@ export default createFragmentContainer( } `, ); - ``` ## Relay Compiler @@ -151,7 +141,6 @@ Relay uses the Relay Compiler to convert [`graphql`](#graphql) literals into gen A query like the following: ```javascript - graphql` fragment MyComponent on Type { field @@ -172,12 +161,10 @@ Relay Compiler supports the use of **persisted queries**, in which each version Persisted queries can be enabled by instructing Relay Compiler to emit metadata about each query, mutation, and subscription into a JSON file. The generated file will contain a mapping of query identifiers to query text, which you can then save to your server. To enable persisted queries, use the `--persist-output` flag to the compiler: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` Relay Compiler will then create the id => query text mapping in the path you specify. You can then use this complete @@ -194,7 +181,6 @@ See our relay-compiler section in our [Installation and Setup guide](./installat To use the Relay Compiler, you need either a .graphql or .json GraphQL schema file, describing your GraphQL server's API. Typically these files are local representations of a server source of truth and are not edited directly. For example, we might have a `schema.graphql` like: ```graphql - schema { query: Root } @@ -212,7 +198,6 @@ type WordDefinition { text: String image: String } - ``` ### Source files @@ -228,7 +213,6 @@ For example, given the two files: - `src/Components/DictionaryComponent.js` ```javascript - const DictionaryWordFragment = graphql` fragment DictionaryComponent_word on Word { id @@ -250,7 +234,6 @@ For example, given the two files: - `src/Queries/DictionaryQuery.js` ```javascript - const DictionaryQuery = graphql` query DictionaryQuery { dictionary { @@ -274,9 +257,7 @@ Typically you will not need to import your generated definitions. The [Relay Bab However the Relay Compiler also automatically generates [Flow](https://flow.org) types as [type comments](https://flow.org/en/docs/types/comments/). For example, you can import the generated Flow types like so: ```javascript - import type {DictionaryComponent_word} from './__generated__/DictionaryComponent_word.graphql'; - ``` ### Client schema extensions @@ -286,18 +267,15 @@ The Relay Compiler fully supports client-side schema extensions, which allows yo For example, let's create `./src/clientSchema.graphql` and define a new type called `Setting`: ```graphql - type Setting { name: String! active: Boolean! } - ``` Assuming the server schema `./schema.graphql`: ```graphql - schema { query: Root } @@ -305,17 +283,14 @@ schema { type Root { title: String! } - ``` We can then extend existing server types in the client schema `./src/clientSchema.graphql` with our new `Setting` type, like so: ```graphql - extend type Root { settings: [Setting] } - ``` Any fields specified in the client schema, can be fetched from the [Relay Store](./relay-store), by requesting it in a query. diff --git a/website/versioned_docs/version-v5.0.0/Modern-LocalStateManagement.md b/website/versioned_docs/version-v5.0.0/Modern-LocalStateManagement.md index 2f20f57000cc1..c97bfdb12b45f 100644 --- a/website/versioned_docs/version-v5.0.0/Modern-LocalStateManagement.md +++ b/website/versioned_docs/version-v5.0.0/Modern-LocalStateManagement.md @@ -24,23 +24,19 @@ It can even be used to extend an existing server schema. For example, we can create a new type called `Note`: ```graphql - type Note { ID: ID! title: String body: String } - ``` And then extend the server schema type `User`, with a list of `Note`, called `notes`. ```graphql - extend type User { notes: [Note] } - ``` ## Querying local state @@ -51,7 +47,6 @@ The field can be from the server schema, or it can be schema agnostic, like an i Here, we use a [QueryRenderer](./query-renderer) to get the current `User` via the `viewer` field, along with their id, name and the local list of notes. ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -97,7 +92,6 @@ const Example = (props) => { /> ); } - ``` ## Mutating local state @@ -111,7 +105,6 @@ To build upon the previous example, let's try creating, updating and deleting a ### Create ```javascript - import {commitLocalUpdate} from 'react-relay'; let tempID = 0; @@ -138,13 +131,11 @@ function createUserNote() { user.setLinkedRecords([...userNoteRecords, newNoteRecord], 'notes'); }); } - ``` ### Update ```javascript - import {commitLocalUpdate} from 'react-relay'; function updateUserNote(dataID, body, title) { @@ -155,13 +146,11 @@ function updateUserNote(dataID, body, title) { note.setValue(title, 'title') }); } - ``` ### Delete ```javascript - import {commitLocalUpdate} from 'react-relay'; function deleteUserNote(dataID) { @@ -179,7 +168,6 @@ function deleteUserNote(dataID) { user.setLinkedRecords(newUserNoteRecords, 'notes'); }); } - ``` ## Initial local state @@ -188,7 +176,6 @@ All new client-side schema fields default to `undefined` value. Often however, y You can use an updater function via `commitLocalUpdate` to prime local state. ```javascript - import {commitLocalUpdate} from 'react-relay'; commitLocalUpdate(environment, store => { @@ -197,5 +184,4 @@ commitLocalUpdate(environment, store => { // initialize user notes to an empty array. user.setLinkedRecords([], 'notes'); }); - ``` diff --git a/website/versioned_docs/version-v5.0.0/Modern-MigrationSetup.md b/website/versioned_docs/version-v5.0.0/Modern-MigrationSetup.md index 66f1145357e25..a89c0e178e0e5 100644 --- a/website/versioned_docs/version-v5.0.0/Modern-MigrationSetup.md +++ b/website/versioned_docs/version-v5.0.0/Modern-MigrationSetup.md @@ -13,13 +13,11 @@ With some additional configuration, the `"relay"` babel plugin can also translat Relay Classic `Relay.QL` literals. Most importantly, include a reference to your GraphQL Schema as either a json file or graphql schema file. ```javascript - { "plugins": [ ["relay", {"schema": "path/schema.graphql"}] ] } - ``` ## Set up babel-plugin-relay for "[compatibility mode](./relay-compat)" @@ -29,13 +27,11 @@ literals can be translated to be usable by _both_ runtimes if configured to use compatibility mode: ```javascript - { "plugins": [ ["relay", {"compat": true, "schema": "path/schema.graphql"}] ] } - ``` ## Additional Options @@ -47,7 +43,6 @@ thrown at runtime. When compiling code for production deployment, the plugin can be configured to immediately throw upon encountering a validation problem. The plugin can be further customized for different environments with the following options: ```javascript - { "plugins": [ ["relay", { @@ -56,5 +51,4 @@ When compiling code for production deployment, the plugin can be configured to i }] ] } - ``` diff --git a/website/versioned_docs/version-v5.0.0/Modern-Mutations.md b/website/versioned_docs/version-v5.0.0/Modern-Mutations.md index a2e0b285bf2c4..8da3bd999c701 100644 --- a/website/versioned_docs/version-v5.0.0/Modern-Mutations.md +++ b/website/versioned_docs/version-v5.0.0/Modern-Mutations.md @@ -17,7 +17,6 @@ Table of Contents: Use `commitMutation` to create and execute mutations. `commitMutation` has the following signature: ```javascript - commitMutation( environment: Environment, config: { @@ -31,7 +30,6 @@ commitMutation( configs?: Array, }, ); - ``` ### Arguments @@ -58,7 +56,6 @@ commitMutation( Example of a simple mutation: ```javascript - import {commitMutation, graphql} from 'react-relay'; const mutation = graphql` @@ -93,7 +90,6 @@ function markNotificationAsRead(environment, source, storyID) { }, ); } - ``` ## Optimistic Updates @@ -101,7 +97,6 @@ function markNotificationAsRead(environment, source, storyID) { To improve perceived responsiveness, you may wish to perform an "optimistic update", in which the client immediately updates to reflect the anticipated new value even before the response from the server has come back. The simplest way to do this is by providing an `optimisticResponse` and adding it to the `config` that we pass into `commitMutation`: ```javascript - const mutation = graphql` mutation MarkReadNotificationMutation( $input: MarkReadNotificationInput! @@ -130,7 +125,6 @@ commitMutation( variables, }, ); - ``` Another way to enable optimistic updates is via the `optimisticUpdater`, which can be used for more complicated update scenarios. Using `optimisticUpdater` is covered in the section [below](#using-updater-and-optimisticupdater). @@ -152,7 +146,6 @@ Given a deletedIDFieldName, Relay will remove the node(s) from the store. #### Example ```javascript - const mutation = graphql` mutation DestroyShipMutation($input: DestroyShipInput!) { destroyShip(input: $input) { @@ -170,7 +163,6 @@ const configs = [{ type: 'NODE_DELETE', deletedIDFieldName: 'destroyedShipId', }]; - ``` ### RANGE_ADD @@ -190,7 +182,6 @@ Given a parent, information about the connection, and the name of the newly crea #### Example ```javascript - const mutation = graphql` mutation AddShipMutation($input: AddShipInput!) { addShip(input: $input) { @@ -220,7 +211,6 @@ function commit(environment, factionId, name) { }], }); } - ``` ### RANGE_DELETE @@ -242,7 +232,6 @@ from the connection but leave the associated record(s) in the store. #### Example ```javascript - const mutation = graphql` mutation RemoveTagMutation($input: RemoveTagInput!) { removeTag(input: $input) { @@ -268,7 +257,6 @@ function commit(environment, todoId, tagId) { }], }); } - ``` ## Using updater and optimisticUpdater @@ -286,7 +274,6 @@ When you provide these functions, this is roughly what happens during the mutati Here are a quick example of adding a todo item to a Todo list using this [example schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L36): ```javascript - // AddTodoMutation.js import {commitMutation, graphql} from 'react-relay'; import {ConnectionHandler} from 'relay-runtime'; @@ -373,7 +360,6 @@ function commit(environment, text, user) { }, }); } - ``` For details on how to interact with the Relay Store, please refer to our Relay Store [docs](./relay-store). diff --git a/website/versioned_docs/version-v5.0.0/Modern-NetworkLayer.md b/website/versioned_docs/version-v5.0.0/Modern-NetworkLayer.md index fcd9fd4dd5e03..daa8c71294c59 100644 --- a/website/versioned_docs/version-v5.0.0/Modern-NetworkLayer.md +++ b/website/versioned_docs/version-v5.0.0/Modern-NetworkLayer.md @@ -8,7 +8,6 @@ In order to know how to access your GraphQL server, Relay Modern requires develo Currently the easiest way to create a network layer is via a helper from the `relay-runtime` package: ```javascript - import { Environment, Network, @@ -50,7 +49,6 @@ const environment = new Environment({ }); export default environment; - ``` Note that this is a basic example to help you get started. This example could be extended with additional features such as request/response caching (enabled e.g. when `cacheConfig.force` is false) and uploading form data for mutations (the `uploadables` parameter). @@ -62,7 +60,6 @@ Relay modern makes no assumptions about what to cache and will garbage collect a You have to implement your own cache strategy. A simple solution is to use `RelayQueryResponseCache`(an in-memory cache): ```javascript - import { Environment, Network, @@ -126,7 +123,6 @@ const environment = new Environment({ }); export default environment; - ``` ## Custom open-source implementations diff --git a/website/versioned_docs/version-v5.0.0/Modern-PaginationContainer.md b/website/versioned_docs/version-v5.0.0/Modern-PaginationContainer.md index 6ac3aac8cfb8e..57980d553af9b 100644 --- a/website/versioned_docs/version-v5.0.0/Modern-PaginationContainer.md +++ b/website/versioned_docs/version-v5.0.0/Modern-PaginationContainer.md @@ -24,7 +24,6 @@ However, when [specifying connection fragments](#createpaginationcontainer) for The purpose of the `@connection` directive is to allow Relay to uniquely identify different connections under a parent type. The `@connection` directive takes 2 arguments that help identify the connection: ```graphql - @connection(key: String!, filters: [String]) ``` @@ -37,7 +36,6 @@ The purpose of the `@connection` directive is to allow Relay to uniquely identif Specifying just the `key`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and the value of `$orderBy` (given that no `filters` were provided) @@ -53,13 +51,11 @@ fragment Feed_user on User { } } } - ``` Specifying `key` and `filters`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and /only/ the value of `$searchTerm`, i.e. @@ -77,7 +73,6 @@ fragment Feed_user on User { } } } - ``` ## `createPaginationContainer` @@ -85,7 +80,6 @@ fragment Feed_user on User { `createPaginationContainer` has the following signature: ```javascript - createPaginationContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, @@ -113,7 +107,6 @@ type ConnectionData = { startCursor: ?string, }, }; - ``` ### Arguments @@ -134,7 +127,6 @@ type ConnectionData = { The Component resulting from `createPaginationContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -145,7 +137,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -160,7 +151,6 @@ type Props = { `hasMore` is a function available on the `relay` [prop](#available-props). This function indicates whether there are more pages to fetch from the server or not. ```javascript - hasMore: () => boolean, ``` @@ -170,7 +160,6 @@ hasMore: () => boolean, `isLoading` is a function available on the `relay` [prop](#available-props). This function indicates if a previous call to [`loadMore()`](#loadmore) is still pending. This is convenient for avoiding duplicate load calls. ```javascript - isLoading: () => boolean, ``` @@ -180,7 +169,6 @@ isLoading: () => boolean, `loadMore` is a function available on the `relay` [prop](#available-props). You can call `loadMore()` to fetch more items from the server based on the `connectionConfig` provided to the container. This will return null if there are no more items to fetch, otherwise it will fetch more items and return a Disposable that can be used to cancel the fetch. ```javascript - loadMore( pageSize: number, callback: ?(error: ?Error) => void, @@ -201,7 +189,6 @@ loadMore( `refetchConnection` is a function available on the `relay` [prop](#available-props). You can call `refetchConnection` to restart pagination on a connection from scratch, with optionally a completely new set of variables to pass to the pagination `query`. This is useful for example if you are paginating over a collection based on a userID and the userID changes, you'd want to start paginating over the new collection for the new user. ```javascript - refetchConnection:( totalCount: number, callback: (error: ?Error) => void, @@ -219,7 +206,6 @@ refetchConnection:( ## Pagination Example ```javascript - // Feed.js import {createPaginationContainer, graphql} from 'react-relay'; @@ -314,5 +300,4 @@ module.exports = createPaginationContainer( ` } ); - ``` diff --git a/website/versioned_docs/version-v5.0.0/Modern-PersistedQueries.md b/website/versioned_docs/version-v5.0.0/Modern-PersistedQueries.md index 137cc2e23220c..ec03b69ba09c3 100644 --- a/website/versioned_docs/version-v5.0.0/Modern-PersistedQueries.md +++ b/website/versioned_docs/version-v5.0.0/Modern-PersistedQueries.md @@ -17,12 +17,10 @@ The relay compiler supports persisted queries which is useful because: In your `npm` script in `package.json`, run the relay compiler using the `--persist-output` flag: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` The `--persist-ouput` flag does 3 things: @@ -31,8 +29,7 @@ The `--persist-ouput` flag does 3 things: For example without `--persist-output`, a generated `ConcreteRequest` might look like below: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -49,8 +46,7 @@ The `--persist-ouput` flag does 3 things: With `--persist-output ` this becomes: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -68,12 +64,10 @@ The `--persist-ouput` flag does 3 things: 2. It generates a JSON file at the `` you specify containing a mapping from query ids to the corresponding operation texts. -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./src/queryMaps/queryMap.json" } - ``` The example above writes the complete query map file to `./src/queryMaps/queryMap.json`. You need to ensure all the directories @@ -83,8 +77,7 @@ leading to the `queryMap.json` file exist. You'll need to modify your network layer fetch implementation to pass a documentId parameter in the POST body instead of a query parameter: -```js - +```javascript function fetchQuery(operation, variables,) { return fetch('/graphql', { method: 'POST', @@ -100,7 +93,6 @@ function fetchQuery(operation, variables,) { return response.json(); }); } - ``` ## Executing Persisted Queries on the Server @@ -116,13 +108,11 @@ the query map file in a common location accessible to both the client and the se For applications where the client and server projects are separate, one option is to have an additional npm run script to push the query map at compile time to a location accessible by your server: -```js - +```javascript "scripts": { "push-queries": "node ./pushQueries.js", "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-ouput && npm run push-queries" } - ``` Some possibilities of what you can do in `./pushQueries.js`: @@ -146,8 +136,7 @@ database technologies you use, so we'll just cover the most common and basic exa If you use `express-graphql` and have access to the query map file, you can import the `--persist-output` JSON file directly and perform the matching using the `matchQueryMiddleware` from [relay-compiler-plus](https://github.com/yusinto/relay-compiler-plus). -```js - +```javascript import Express from 'express'; import expressGraphql from 'express-graphql'; import {matchQueryMiddleware} from 'relay-compiler-plus'; @@ -158,7 +147,6 @@ const app = Express(); app.use('/graphql', matchQueryMiddleware(queryMapJson), expressGraphql({schema})); - ``` ## Using `--persist-output` and `--watch` diff --git a/website/versioned_docs/version-v5.0.0/Modern-QueryRenderer.md b/website/versioned_docs/version-v5.0.0/Modern-QueryRenderer.md index d9e65689061cb..4211d47929fce 100644 --- a/website/versioned_docs/version-v5.0.0/Modern-QueryRenderer.md +++ b/website/versioned_docs/version-v5.0.0/Modern-QueryRenderer.md @@ -24,7 +24,6 @@ However, a `QueryRenderer` will not start loading its data until it is mounted, ## Example ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -56,5 +55,4 @@ const Example = (props) => { /> ); } - ``` diff --git a/website/versioned_docs/version-v5.0.0/Modern-RefetchContainer.md b/website/versioned_docs/version-v5.0.0/Modern-RefetchContainer.md index c2cc7c6bc3613..6e67b33af55a8 100644 --- a/website/versioned_docs/version-v5.0.0/Modern-RefetchContainer.md +++ b/website/versioned_docs/version-v5.0.0/Modern-RefetchContainer.md @@ -16,13 +16,11 @@ Table of Contents: `createRefetchContainer` has the following signature: ```javascript - createRefetchContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, refetchQuery: GraphQLTaggedNode, ): ReactComponentClass; - ``` ### Arguments @@ -37,7 +35,6 @@ createRefetchContainer( The Component resulting from `createRefetchContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -45,7 +42,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -61,7 +57,6 @@ type Props = { `refetch` has the following signature: ```javascript - type RefetchOptions = { force?: boolean, }; @@ -102,7 +97,6 @@ Returns a `Disposable` on which you could call `dispose()` to cancel the refetch In this simple example, let's assume we want to fetch the latest data for a `TodoItem` from the server: ```javascript - // TodoItem.js import {createRefetchContainer, graphql} from 'react-relay'; @@ -146,7 +140,6 @@ export default createRefetchContainer( } ` ); - ``` ### Loading more data @@ -154,7 +147,6 @@ export default createRefetchContainer( In this example we are using a Refetch Container to fetch more stories in a story feed component. ```javascript - import {createRefetchContainer, graphql} from 'react-relay'; class FeedStories extends React.Component { @@ -210,5 +202,4 @@ export default createRefetchContainer( } `, ); - ``` diff --git a/website/versioned_docs/version-v5.0.0/Modern-RelayCompat.md b/website/versioned_docs/version-v5.0.0/Modern-RelayCompat.md index 36632d3a8f1a1..f47dbd845ba3e 100644 --- a/website/versioned_docs/version-v5.0.0/Modern-RelayCompat.md +++ b/website/versioned_docs/version-v5.0.0/Modern-RelayCompat.md @@ -31,7 +31,6 @@ Relay Modern. The components using Relay Compat can be referred to by both other Relay Modern and Relay Classic components. ```javascript - const {createFragmentContainer, graphql} = require('react-relay/compat'); class TodoItem extends React.Component { @@ -47,5 +46,4 @@ module.exports = createFragmentContainer(TodoItem, graphql` isComplete } `); - ``` diff --git a/website/versioned_docs/version-v5.0.0/Modern-RelayEnvironment.md b/website/versioned_docs/version-v5.0.0/Modern-RelayEnvironment.md index e9ffff2f68d8f..80a318af0cd55 100644 --- a/website/versioned_docs/version-v5.0.0/Modern-RelayEnvironment.md +++ b/website/versioned_docs/version-v5.0.0/Modern-RelayEnvironment.md @@ -12,7 +12,6 @@ Most applications will create a single Environment instance and use it throughou To create an environment instance in Relay Modern, use the `RelayModernEnvironment` class: ```javascript - const { Environment, Network, @@ -30,7 +29,6 @@ const environment = new Environment({ network, store, }); - ``` For more details on creating a Network, see the [NetworkLayer guide](./network-layer). @@ -44,7 +42,6 @@ The example above did not configure a `handlerProvider`, which means that a defa If you wish to provide your own `handlerProvider`, you can do so: ```javascript - const { ConnectionHandler, ViewerHandler, @@ -60,5 +57,4 @@ function handlerProvider(handle) { `handlerProvider: No handler provided for ${handle}` ); } - ``` diff --git a/website/versioned_docs/version-v5.0.0/Modern-RelayStore.md b/website/versioned_docs/version-v5.0.0/Modern-RelayStore.md index 8bc27098b205e..56b91d3036791 100644 --- a/website/versioned_docs/version-v5.0.0/Modern-RelayStore.md +++ b/website/versioned_docs/version-v5.0.0/Modern-RelayStore.md @@ -16,7 +16,6 @@ Table of Contents: The `RecordSourceSelectorProxy` is the type of the `store` that [`updater` functions](./mutations#using-updater-and-optimisticupdater) receive as an argument. The following is the `RecordSourceSelectorProxy` interface: ```javascript - interface RecordSourceSelectorProxy { create(dataID: string, typeName: string): RecordProxy; delete(dataID: string): void; @@ -25,7 +24,6 @@ interface RecordSourceSelectorProxy { getRootField(fieldName: string): ?RecordProxy; getPluralRootField(fieldName: string): ?Array; } - ``` ### `create(dataID: string, typeName: string): RecordProxy` @@ -35,9 +33,7 @@ Creates a new record in the store given a `dataID` and the `typeName` as defined #### Example ```javascript - const record = store.create(dataID, 'Todo'); - ``` ### `delete(dataID: string): void` @@ -47,9 +43,7 @@ Deletes a record from the store given its `dataID`. #### Example ```javascript - store.delete(dataID); - ``` ### `get(dataID: string): ?RecordProxy` @@ -59,9 +53,7 @@ Retrieves a record from the store given its `dataID`. Returns a [`RecordProxy`]( #### Example ```javascript - const record = store.get(dataID); - ``` ### `getRoot(): RecordProxy` @@ -73,20 +65,16 @@ Returns the [`RecordProxy`](#recordproxy) representing the root of the GraphQL d Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - // Represents root query const root = store.getRoot(); - ``` ### `getRootField(fieldName: string): ?RecordProxy` @@ -98,19 +86,15 @@ Retrieves a root field from the store given the `fieldName`, as defined by the G Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - const viewer = store.getRootField('viewer'); - ``` ### `getPluralRootField(fieldName: string): ?Array` @@ -122,19 +106,15 @@ Retrieves a root field that represents a collection from the store given the `fi Given the GraphQL document: ```graphql - nodes(first: 10) { # ... } - ``` Usage: ```javascript - const nodes = store.getPluralRootField('nodes'); - ``` ## RecordProxy @@ -142,7 +122,6 @@ const nodes = store.getPluralRootField('nodes'); The `RecordProxy` serves as an interface to mutate records: ```javascript - interface RecordProxy { copyFieldsFrom(sourceRecord: RecordProxy): void; getDataID(): string; @@ -167,7 +146,6 @@ interface RecordProxy { ): RecordProxy; setValue(value: mixed, name: string, arguments?: ?Object): RecordProxy; } - ``` ### `getDataID(): string` @@ -177,9 +155,7 @@ Returns the dataID of the current record. #### Example ```javascript - const id = record.getDataID(); - ``` ### `getType(): string` @@ -189,7 +165,6 @@ Gets the type of the current record, as defined by the GraphQL schema. #### Example ```javascript - const type = user.getType(); // User ``` @@ -203,20 +178,16 @@ Gets the value of a field in the current record given the field name. Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - const name = viewer.getValue('name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. @@ -226,20 +197,16 @@ Optionally, if the field takes arguments, you can pass a bag of `variables`. Given the GraphQL document: ```graphql - viewer { id name(arg: $arg) } - ``` Usage: ```javascript - const name = viewer.getValue('name', {arg: 'value'}); - ``` ### `getLinkedRecord(name: string, arguments?: ?Object): ?RecordProxy` @@ -251,23 +218,19 @@ Retrieves a record associated with the current record given the field name, as d Given the GraphQL document: ```graphql - rootField { viewer { id name } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -277,22 +240,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { viewer(arg: $arg) { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {arg: 'value'}); - ``` ### `getLinkedRecords(name: string, arguments?: ?Object): ?Array` @@ -304,22 +263,18 @@ Retrieves the set of records associated with the current record given the field Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const nodes = rootField.getLinkedRecords('nodes'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -329,22 +284,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { nodes(first: $count) { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {count: 10}); - ``` ### `getOrCreateLinkedRecord(name: string, typeName: string, arguments?: ?Object)` @@ -356,19 +307,16 @@ Retrieves the a record associated with the current record given the field name, Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = rootField.getOrCreateLinkedRecord('viewer', 'User'); // Will create if it doesn't exist @@ -383,28 +331,22 @@ Mutates the current record by setting a new value on the specified field. Return Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - viewer.setValue('New Name', 'name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. ```javascript - viewer.setValue('New Name', 'name', {arg: 'value'}); - ``` ### `copyFieldsFrom(sourceRecord: RecordProxy): void` @@ -414,7 +356,6 @@ Mutates the current record by copying the fields over from the passed in record #### Example ```javascript - const record = store.get(id1); const otherRecord = store.get(id2); record.copyFieldsFrom(otherRecord); // Mutates `record` @@ -430,19 +371,16 @@ Mutates the current record by setting a new linked record on the given the field Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = store.create(/* ... */)'' rootField.setLinkedRecord(newViewer, 'viewer'); // @@ -460,19 +398,16 @@ Mutates the current record by setting a new set of linked records on the given t Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newNode = store.create(/* ... */); const newNodes = [...rootField.getLinkedRecords('nodes'), newNode]; @@ -487,7 +422,6 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl `ConnectionHandler` is a utility module exposed by `relay-runtime` that aids in the manipulation of connections. `ConnectionHandler` exposes the following interface: ```javascript - interface ConnectionHandler { getConnection( record: RecordProxy, @@ -512,7 +446,6 @@ interface ConnectionHandler { ): void, deleteNode(connection: RecordProxy, nodeID: string): void } - ``` ### `getConnection(record: RecordProxy, key: string, filters?: ?Object)` @@ -522,7 +455,6 @@ Given a record and a connection key, and optionally a set of filters, `getConnec First, let's take a look at a plain connection: ```graphql - fragment FriendsFragment on User { friends(first: 10) { edges { @@ -532,26 +464,22 @@ fragment FriendsFragment on User { } } } - ``` Accessing a plain connection field like this is the same as other regular field: ```javascript - // The `friends` connection record can be accessed with: const user = store.get(userID); const friends = user && user.getLinkedRecord(user, 'friends'); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` In a [pagination container](./pagination-container), we usually annotate the actual connection field with `@connection` to tell Relay which part needs to be paginated: ```graphql - fragment FriendsFragment on User { friends(first: 10, orderby: "firstname") @connection( key: "FriendsFragment_friends", @@ -563,7 +491,6 @@ fragment FriendsFragment on User { } } } - ``` For connections like the above, `ConnectionHandler` helps us find the record: @@ -581,7 +508,6 @@ const friends = ConnectionHandler.getConnection( ); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` ### Edge creation and insertion @@ -611,7 +537,6 @@ ConnectionHandler.insertEdgeAfter(friends, edge); // No cursor provided, Insert the edge at the front: ConnectionHandler.insertEdgeBefore(friends, edge); - ``` ### `deleteNode(connection: RecordProxy, nodeID: string): void` @@ -625,5 +550,4 @@ Given a connection, deletes any edges whose id matches the given id. const user = store.get(userID); const friends = ConnectionHandler.getConnection(user, 'friends'); ConnectionHandler.deleteNode(friends, idToDelete); - ``` diff --git a/website/versioned_docs/version-v5.0.0/Modern-Subscriptions.md b/website/versioned_docs/version-v5.0.0/Modern-Subscriptions.md index 802f1d02b06de..bd1c5fe2f350c 100644 --- a/website/versioned_docs/version-v5.0.0/Modern-Subscriptions.md +++ b/website/versioned_docs/version-v5.0.0/Modern-Subscriptions.md @@ -6,7 +6,6 @@ original_id: subscriptions Relay exposes the following APIs to create subscriptions. ```javascript - const {requestSubscription} = require('react-relay'); type Variables = {[name: string]: any}; @@ -27,7 +26,6 @@ requestSubscription( configs?: Array, }, ) => Disposable; - ``` The function returns a `Disposable` on which you could call `dispose()` to cancel the refetch. @@ -53,7 +51,6 @@ appropriate when you are only changing the properties of existing records that can be identified by their `id`: ```javascript - const { requestSubscription, graphql, @@ -87,7 +84,6 @@ requestSubscription( onError: error => console.error(error), } ); - ``` # Updating the client on each response @@ -97,7 +93,6 @@ Relay's in-memory cache when each subscription response is received. To do so, pass an `updater` function: ```javascript - const {ConnectionHandler} = require('relay-runtime'); requestSubscription( @@ -123,5 +118,4 @@ requestSubscription( }, }, ); - ``` diff --git a/website/versioned_docs/version-v5.0.0/Modern-TestingRelayComponents.md b/website/versioned_docs/version-v5.0.0/Modern-TestingRelayComponents.md index 4e5cf9e61a922..2916a65f56e06 100644 --- a/website/versioned_docs/version-v5.0.0/Modern-TestingRelayComponents.md +++ b/website/versioned_docs/version-v5.0.0/Modern-TestingRelayComponents.md @@ -65,7 +65,6 @@ MockPayloadGenerator may drastically simplify the process of creating and mainta Example of a simple Mock Resolver: ```javascript - { ID() { // Return mock value for a scalar filed with type ID @@ -76,13 +75,11 @@ Example of a simple Mock Resolver: return "Lorem Ipsum" } } - ``` It is possible to define more resolvers for Object types ```javascript - { // This will be the default values for User object in the query response User() { @@ -95,7 +92,6 @@ It is possible to define more resolvers for Object types }; }, } - ``` ### Mock Resolver Context @@ -103,7 +99,6 @@ It is possible to define more resolvers for Object types The first argument of the MockResolver is the object that contains Mock Resolver Context. It is possible to return dynamic values from mock resolvers based on the context - for instance, name or alias of the field, a path in the selection, arguments, or parent type. ```javascript - { String(context) { if (context.name === 'zip') { @@ -117,7 +112,6 @@ The first argument of the MockResolver is the object that contains Mock Resolver } } } - ``` ### ID Generation @@ -125,14 +119,12 @@ The first argument of the MockResolver is the object that contains Mock Resolver The second argument of the Mock Resolver its a function that will generate a sequence of integers, useful to generate unique ids in the tests ```javascript - { // will generate strings "my-id-1", "my-id-2", etc. ID(_, generateId) { return `my-id-${generateId()}`; }, } - ``` ### @relay_test_operation @@ -142,7 +134,6 @@ Most of GraphQL type information for a specific field in the selection is not av Operation with the @relay_test_operation directive will have additional metadata that will contain GraphQL type info for fields in the operation's selection. And it will improve the quality of the generated data. You also will be able to define Mock resolvers for Scalar (not only ID and String) and Abstract types: ```javascript - { Float() { return 123.456; @@ -160,7 +151,6 @@ Operation with the @relay_test_operation directive will have additional metadata }; } } - ``` ## Examples @@ -170,7 +160,6 @@ Operation with the @relay_test_operation directive will have additional metadata Using `createMockEnvironment` and `MockPayloadGenerator` allows writing concise tests for components that are using Relay Containers and Renderers. Both those modules can be imported from `relay-test-utils` ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { @@ -223,7 +212,6 @@ test('Error State', () => { renderer.root.find(item => (item.props.testID = 'errorMessage')), ).toBeDefined(); }); - ``` ### Fragment Container Tests @@ -231,7 +219,6 @@ test('Error State', () => { Essentially, in the example above will `resolveMostRecentOperation` will generate data for all child fragment containers (pagination, refetch). But, usually the Root Components container may have many child fragment components and you may want to exercise a specific Fragment Container. The solution for that would be to wrap you fragment container with the QueryRenderer that renders a Query that's spreads fragments from you fragment container. ```javascript - test('Fragment Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -262,7 +249,6 @@ test('Fragment Container', () => { expect(renderer).toMatchSnapshot(); }); - ``` ### Pagination Container Test @@ -270,7 +256,6 @@ test('Fragment Container', () => { Essentially, tests for Pagination container are not different from Fragment Container tests. But we can do more here, we can actually see how the pagination works - we can assert the behavior of our components when performing pagination (load more, refetch). ```javascript - // Pagination Example test('Pagination Container', () => { const environment = createMockEnvironment(); @@ -344,7 +329,6 @@ test('Pagination Container', () => { We can use similar approach here with wrapping container with Query Renderer. And for the sake of completeness, we will add example here: ```javascript - test('Refetch Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -386,7 +370,6 @@ test('Refetch Container', () => { ); // expect(renderer).toMatchSnapshot(); }); - ``` ### Mutations @@ -394,7 +377,6 @@ test('Refetch Container', () => { Mutations itself are operations so we can test them independently (unit-test) for specific mutation, or in combination with the view from which this mutation is called. ```javascript - // Say, you have a mutation function function sendMutation(environment, onCompleted, onError, variables) commitMutation(environment, { @@ -417,7 +399,6 @@ test('it should send mutation', () => { ); expect(onCompleted).toBeCalled(); }); - ``` ### Subscription @@ -425,7 +406,6 @@ test('it should send mutation', () => { We can test subscription in a similar way we test mutations ```javascript - // Example subscribe function function subscribe(environment, onNext, onError, variables) requestSubscription(environment, { @@ -448,7 +428,6 @@ test('it should subscribe', () => { ); expect(onNext).toBeCalled(); }); - ``` ### Example with `queueOperationResolver` @@ -456,7 +435,6 @@ test('it should subscribe', () => { With `queueOpeararionResolver` it possible to define responses for operations that will be executed on the environment ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { diff --git a/website/versioned_docs/version-v5.0.0/Modern-TypeEmission.md b/website/versioned_docs/version-v5.0.0/Modern-TypeEmission.md index 63614b869a322..4ff63e4a7d81b 100644 --- a/website/versioned_docs/version-v5.0.0/Modern-TypeEmission.md +++ b/website/versioned_docs/version-v5.0.0/Modern-TypeEmission.md @@ -16,7 +16,6 @@ In this example the emitted type-information would require the variables object #### Flow ```javascript - /** * export type ExampleQueryVariables = {| * +artistID: string @@ -44,7 +43,6 @@ const variables: ExampleQueryVariables = { #### TypeScript ```javascript - /** * export type ExampleQueryVariables = { * readonly artistID: string @@ -79,7 +77,6 @@ In this example the emitted type-information describes the response data availab #### Flow ```javascript - /** * export type ExampleQueryResponse = {| * +artist: ?{| @@ -110,7 +107,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * export type ExampleQueryResponse = { * readonly artist?: { @@ -146,7 +142,6 @@ Similarly, in this example the emitted type-information describes the prop data #### Flow ```javascript - /** * export type ExampleFragment_artist = {| * +name: string @@ -172,7 +167,6 @@ export const ExampleFragment = createFragmentContainer( #### TypeScript ```javascript - /** * export type ExampleFragment_artist = { * readonly name: string @@ -206,7 +200,6 @@ Consider a component that composes the above fragment container example. In this #### Flow ```javascript - /** * import type { FragmentReference } from "relay-runtime"; * declare export opaque type ExampleFragment_artist$ref: FragmentReference; @@ -250,7 +243,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * declare const _ExampleFragment_artist$ref: unique symbol; * export type ExampleFragment_artist$ref = typeof _ExampleFragment_artist$ref; @@ -315,7 +307,6 @@ $ relay-compiler --artifactDirectory ./src/__generated__ […] ["relay", { "artifactDirectory": "./src/__generated__" }] ] } - ``` It is recommended to alias this directory in your module resolution configuration such that you don’t need to specify relative paths in your source files. This is what is also done in the above examples, where artifacts are imported from a `__generated__` alias, rather than relative paths like `../../../../__generated__`. diff --git a/website/versioned_docs/version-v5.0.0/Modern-UpgradingSetVariables.md b/website/versioned_docs/version-v5.0.0/Modern-UpgradingSetVariables.md index d5b086fafce20..ff73feec04f8b 100644 --- a/website/versioned_docs/version-v5.0.0/Modern-UpgradingSetVariables.md +++ b/website/versioned_docs/version-v5.0.0/Modern-UpgradingSetVariables.md @@ -36,7 +36,6 @@ fragment on User { # ... } } - ``` This should be upgraded to use a [`PaginationContainer`](./pagination-container). @@ -61,7 +60,6 @@ fragment on User { # ... } } - ``` This can be upgraded by using a [`RefetchContainer`](./refetch-container) which allows you to specify the exact query to use to fetch the new data. @@ -86,7 +84,6 @@ fragment on FeedbackTarget { # ... } } - ``` This can be upgraded by conditionally rendering a [`QueryRenderer`](./query-renderer) which will load the data once it is rendered. The code overhead of doing this is dramatically reduced with the new API. diff --git a/website/versioned_docs/version-v5.0.0/Modern-fetchQuery.md b/website/versioned_docs/version-v5.0.0/Modern-fetchQuery.md index e9dcf908db91a..d266ae9d7c67a 100644 --- a/website/versioned_docs/version-v5.0.0/Modern-fetchQuery.md +++ b/website/versioned_docs/version-v5.0.0/Modern-fetchQuery.md @@ -6,7 +6,6 @@ original_id: fetch-query You can use the `fetchQuery` function to imperatively make GraphQL Requests. This is useful for cases where you want to make requests outside of React but still utilize the Relay store and network layer. ```javascript - import {fetchQuery, graphql} from 'relay-runtime'; const query = graphql` @@ -25,7 +24,6 @@ fetchQuery(environment, query, variables) .then(data => { // access the graphql response }); - ``` ## Arguments diff --git a/website/versioned_docs/version-v5.0.0/PrinciplesAndArchitecture-Compiler.md b/website/versioned_docs/version-v5.0.0/PrinciplesAndArchitecture-Compiler.md index c195491682b1f..fcd0490cb724f 100644 --- a/website/versioned_docs/version-v5.0.0/PrinciplesAndArchitecture-Compiler.md +++ b/website/versioned_docs/version-v5.0.0/PrinciplesAndArchitecture-Compiler.md @@ -74,7 +74,6 @@ foo { # type FooType foo { id } - ``` - `SkipRedundantNodeTransform`: A more advanced version of flattening, this eliminates more complex cases of field duplication such as when a field is fetched both unconditionally and conditionally, or is fetched by two different sub-fragments. For example: @@ -97,7 +96,6 @@ foo { id } } - ``` - `GenerateRequisiteFieldTransform`: This optional, Relay-specific transform inserts `id` fields for globally identifiable objects and `__typename` fields wherever the type cannot be statically determined (e.g. for unions). diff --git a/website/versioned_docs/version-v5.0.0/PrinciplesAndArchitecture-Runtime.md b/website/versioned_docs/version-v5.0.0/PrinciplesAndArchitecture-Runtime.md index 9491d290c146f..e9221631a701d 100644 --- a/website/versioned_docs/version-v5.0.0/PrinciplesAndArchitecture-Runtime.md +++ b/website/versioned_docs/version-v5.0.0/PrinciplesAndArchitecture-Runtime.md @@ -77,7 +77,6 @@ RecordSource { city: 'Seattle', } } - ``` [1] Note that GraphQL itself does not impose this constraint, and Relay Runtime may also be used for schemas that do not conform to it. For example, both systems can be used to query a single denormalized table. However, many of the features that Relay Runtime provides, such as caching and normalization, work best when the data is represented as a normalized graph with stable identities for discrete pieces of information. diff --git a/website/versioned_docs/version-v5.0.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md b/website/versioned_docs/version-v5.0.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md index a8842ae084922..9ff8a7840df90 100644 --- a/website/versioned_docs/version-v5.0.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md +++ b/website/versioned_docs/version-v5.0.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md @@ -12,7 +12,6 @@ In this article we'll explore what it means to build a GraphQL client framework Imagine we have a simple application that fetches a list of stories, and some details about each one. Here's how that might look in resource-oriented REST: ```javascript - // Fetch the list of story IDs but not their details: rest.get('/stories').then(stories => // This resolves to a list of items with linked resources: @@ -25,13 +24,11 @@ rest.get('/stories').then(stories => // `[ { id: "...", text: "..." } ]` console.log(stories); }); - ``` Note that this approach requires _n+1_ requests to the server: 1 to fetch the list, and _n_ to fetch each item. With GraphQL we can fetch the same data in a single network request to the server (without creating a custom endpoint that we'd then have to maintain): ```javascript - graphql.get(`query { stories { id, text } }`).then( stories => { // A list of story items: @@ -39,7 +36,6 @@ graphql.get(`query { stories { id, text } }`).then( console.log(stories); } ); - ``` So far we're just using GraphQL as a more efficient version of typical REST approaches. Note two important benefits in the GraphQL version: @@ -56,7 +52,6 @@ Repeatedly refetching information from the server can get quite slow. For exampl In a resource-oriented REST system, we can maintain a **response cache** based on URIs: ```javascript - var _cache = new Map(); rest.get = uri => { if (!_cache.has(uri)) { @@ -64,13 +59,11 @@ rest.get = uri => { } return _cache.get(uri); }; - ``` Response-caching can also be applied to GraphQL. A basic approach would work similarly to the REST version. The text of the query itself can be used as a cache key: ```javascript - var _cache = new Map(); graphql.get = queryText => { if (!_cache.has(queryText)) { @@ -78,7 +71,6 @@ graphql.get = queryText => { } return _cache.get(queryText); }; - ``` Now, requests for previously cached data can be answered immediately without making a network request. This is a practical approach to improving the perceived performance of an application. However, this method of caching can cause problems with data consistency. @@ -90,7 +82,6 @@ With GraphQL it is very common for the results of multiple queries to overlap. H ``` query { stories { id, text, likeCount } } - ``` and then later refetch one of the stories whose `likeCount` has since been incremented: @@ -98,7 +89,6 @@ and then later refetch one of the stories whose `likeCount` has since been incre ``` query { story(id: "123") { id, text, likeCount } } - ``` We'll now see different `likeCount`s depending on how the story is accessed. A view that uses the first query will see an outdated count, while a view using the second query will see the updated count. @@ -119,7 +109,6 @@ query { } } } - ``` And here's a possible response: @@ -134,13 +123,11 @@ query: { } } } - ``` Although the response is hierarchical, we'll cache it by flattening all the records. Here is an example of how Relay would cache this query response: ```javascript - Map { // `story(id: "1")` 1: Map { @@ -152,7 +139,6 @@ Map { name: 'Jan', }, }; - ``` This is only a simple example: in reality the cache must handle one-to-many associations and pagination (among other things). @@ -182,7 +168,6 @@ The first query was for a list of stories: ``` query { stories { id, text, likeCount } } - ``` With a normalized response cache, a record would be created for each story in the list. The `stories` field would store links to each of these records. @@ -192,7 +177,6 @@ The second query refetched the information for one of those stories: ``` query { story(id: "123") { id, text, likeCount } } - ``` When this response is normalized, Relay can detect that this result overlaps with existing data based on its `id`. Rather than create a new record, Relay will update the existing `123` record. The new `likeCount` is therefore available to _both_ queries, as well as any other query that might reference this story. @@ -215,7 +199,6 @@ query { } } } - ``` After initially fetching this story our cache might be as follows. Note that the story and comment both link to the same record as `author`: @@ -242,7 +225,6 @@ Map { author: Link(2), }, } - ``` The author of this story also commented on it — quite common. Now imagine that some other view fetches new information about the author, and her profile photo has changed to a new URI. Here's the _only_ part of our cached data that changes: @@ -256,7 +238,6 @@ Map { photo: 'http://.../photo2.jpg', }, } - ``` The value of the `photo` field has changed; and therefore the record `2` has also changed. And that's it. Nothing else in the _cache_ is affected. But clearly our _view_ needs to reflect the update: both instances of the author in the UI (as story author and comment author) need to show the new photo. @@ -273,7 +254,6 @@ ImmutableMap { }, 3: ImmutableMap // same as before } - ``` If we replace `2` with a new immutable record, we'll also get a new immutable instance of the cache object. However, records `1` and `3` are untouched. Because the data is normalized, we can't tell that `story`'s contents have changed just by looking at the `story` record alone. @@ -299,7 +279,6 @@ mutation StoryLike($storyID: String) { likeCount } } - ``` Notice that we're querying for data that _may_ have changed as a result of the mutation. An obvious question is: why can't the server just tell us what changed? The answer is: it's complicated. GraphQL abstracts over _any_ data storage layer (or an aggregation of multiple sources), and works with any programming language. Furthermore, the goal of GraphQL is to provide data in a form that is useful to product developers building a view. diff --git a/website/versioned_docs/version-v5.0.0/PrinciplesAndArchitecture-ThinkingInRelay.md b/website/versioned_docs/version-v5.0.0/PrinciplesAndArchitecture-ThinkingInRelay.md index d6f1572d5590b..4fb68372ec4b3 100644 --- a/website/versioned_docs/version-v5.0.0/PrinciplesAndArchitecture-ThinkingInRelay.md +++ b/website/versioned_docs/version-v5.0.0/PrinciplesAndArchitecture-ThinkingInRelay.md @@ -30,13 +30,11 @@ fragment Story_story on Story { photo } } - ``` And this fragment can then be used to define the Story container: ```javascript - const {createFragmentContainer, graphql} = require('react-relay'); // Plain React component. @@ -64,7 +62,6 @@ const StoryContainer = createFragmentContainer(Story, { In React, rendering a view requires two inputs: the _component_ to render, and a _root_ DOM (UI) node to render into. Rendering Relay containers is similar: we need a _container_ to render, and a _root_ in the graph from which to start our query. We also must ensure that the queries for the container are executed and may want to show a loading indicator while data is being fetched. Similar to `ReactDOM.render(component, domNode)`, Relay provides `` for this purpose. The `query` and `variables` define what data to fetch and `render` defines what to render. Here's how we might render ``: ```javascript - ReactDOM.render( { ); } } - ``` The above code is doing something very similar to our [previous example](#rendering-graphql-queries). However, we are now passing a `$userID` variable to the GraphQL query via the `variables` prop. This has a couple of important implications: @@ -228,7 +216,6 @@ Now that we know how to define and fetch queries, let's actually start building First, let's start at the bottom. Suppose that we want to render a component that simply displays a given todo item's text and completed state: ```javascript - // Todo.js import React from 'react'; @@ -258,7 +245,6 @@ export default class Todo extends React.Component { ); } } - ``` From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L107), we know that we can query this data on the `Todo` type. However, we don't want to have to send a separate query for each todo item; that would defeat the purpose of using GraphQL over a traditional REST API. We could manually query for these fields directly in our `QueryRenderer` query, but that would hurt re-usability: what if we want to query the same set of fields as part of a different query? Additionally, we wouldn't know which component needs the data we're querying, which is a problem Relay directly tries to address. @@ -266,18 +252,15 @@ From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/dat Instead, we can define a reusable [Fragment](http://graphql.org/learn/queries/#fragments), which allows us to define a set of fields on a type and reuse them within our queries wherever we need to: ```graphql - fragment TodoItemFragment on Todo { complete text } - ``` Our component can then use this fragment to declare its data dependency on the `Todo` GraphQL type: ```javascript - // Todo.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -340,7 +323,6 @@ Before proceeding, don't forget to run the Relay Compiler with `yarn relay`. Given that [Fragment Containers](./fragment-container) are just React components, we can compose them as such. We can even re-use fragment containers within other fragment containers. As an example, let's see how we would define a `TodoList` component that just renders a list of todo items, and whether all have been completed or not: ```javascript - // TodoList.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -401,7 +383,6 @@ export default createFragmentContainer( `, }, ); - ``` As with the first fragment container we defined, `TodoList` declares it's data dependencies via a fragment. However, this component additionally re-uses the fragment previously defined by the `Todo` component, and passes the appropriate data when rendering the child `Todo` components (a.k.a. fragment containers). @@ -416,7 +397,6 @@ fragment containers do not directly fetch data. Instead, containers declare a sp A `QueryRenderer` rendering these fragment containers could look like the following: ```javascript - // ViewerTodoList.js import React from 'react'; import {graphql, QueryRenderer} from 'react-relay'; @@ -457,7 +437,6 @@ export default class ViewerTodoList extends React.Component { ); } } - ``` Check out our docs for [Fragment Containers](./fragment-container) for more details, and our guides on [Refetch](./refetch-container) and [Pagination](./pagination-container) for more advanced usage of containers. @@ -469,7 +448,6 @@ Now that we know how to query for and render data, let's move on to changing our From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L35), we know that we have some mutations available to us, so let's start by writing a mutation to change the `complete` status of a given todo item (i.e. mark or unmark it as done): ```graphql - mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { changeTodoStatus(input: $input) { todo { @@ -478,7 +456,6 @@ mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { } } } - ``` This mutation allows us to query back some data as a [result of the mutation](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L18), so we're going to query for the updated `complete` status on the todo item. @@ -486,7 +463,6 @@ This mutation allows us to query back some data as a [result of the mutation](ht In order to execute this mutation in Relay, we're going to write a new mutation using Relay's `commitMutation` api: ```javascript - // ChangeTodoStatusMutation.js import {graphql, commitMutation} from 'react-relay'; @@ -520,7 +496,6 @@ function commit( } export default {commit}; - ``` Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mutation to the server and, in our case, upon receiving a response it will automatically update the local data store with the latest data from the server. This also means that upon receiving the response, Relay will ensure that any components (i.e. containers) that depend on the updated data are re-rendered. @@ -528,7 +503,6 @@ Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mut In order to actually use this mutation in our component, we could update our `Todo` component in the following way: ```javascript - // Todo.js // ... @@ -562,7 +536,6 @@ In order to make the experience better, we can configure our mutation to do an o In Relay, there's a couple of options we can pass to `commitMutation` to enable optimistic updates. Let's see what that would look like in our `ChangeTodoStatusMutation`: ```javascript - // ChangeTodoStatusMutation.js // ... @@ -597,7 +570,6 @@ function commit( } export default {commit}; - ``` In the simplest case above, we just need to pass an `optimisticResponse` option, which should refer to an object having the same shape as the mutation response payload. When we pass this option, Relay will know to immediately update our local data with the optimistic response, and then update it with the actual server response or roll it back if an error occurs. diff --git a/website/versioned_docs/version-v6.0.0/Modern-ConvertingMutations.md b/website/versioned_docs/version-v6.0.0/Modern-ConvertingMutations.md index 08ad2e998cb2d..8f4bdc1d8e0d2 100644 --- a/website/versioned_docs/version-v6.0.0/Modern-ConvertingMutations.md +++ b/website/versioned_docs/version-v6.0.0/Modern-ConvertingMutations.md @@ -12,19 +12,16 @@ FatQueries in Relay Classic mutations was a concept that was confusing for a num Example of existing fat query: ```javascript - RelayClassic.QL` fragment on MarkReadNotificationResponsePayload @relay(pattern: true) { notification } `; - ``` Example of converted mutation query: ```javascript - graphql` mutation MarkReadNotificationMutation( $input: MarkReadNotificationData! @@ -37,7 +34,6 @@ graphql` } } `; - ``` ## Migrating Configs @@ -67,7 +63,6 @@ This is no longer needed in Compatibility Mode for neither environments. Simply Take this example of a simple mutation in Relay Classic: ```javascript - class LikeStoryMutation extends RelayClassic.Mutation { getMutation() { return RelayClassic.QL`mutation {likeStory}`; @@ -106,7 +101,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { `, }; } - ``` ### Converting `getMutation()` and `getFatQuery()` @@ -114,7 +108,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { We combine these two into a regular GraphQL mutation, which list out specific fields that needs to be updated. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story(data: $input) { @@ -126,7 +119,6 @@ const mutation = graphql` } } `; - ``` ### Converting `getConfigs()` @@ -138,13 +130,11 @@ As specified above, `FIELDS_CHANGE` configs can be omitted. To convert `getVariables()`, we take the return value from the original function and wrap it in an object that contains a property that matches the variable name for the mutation. In this case, the mutation has a `input` variable that is of type `LikeStoryData`. ```javascript - const variables = { input: { storyID: args.storyID } } - ``` ### Final Result @@ -152,7 +142,6 @@ const variables = { As you can see, our resulting mutation is a lot simpler and more like regular GraphQL than the Relay Classic version we started out with. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story { @@ -178,7 +167,6 @@ function commit(environment: CompatEnvironment, args) { variables, }); } - ``` See [Mutation](./mutations) for additional options on `commitMutation` for more complex mutations. diff --git a/website/versioned_docs/version-v6.0.0/Modern-FragmentContainer.md b/website/versioned_docs/version-v6.0.0/Modern-FragmentContainer.md index 423f446cbb054..6a40bbcfb5d0a 100644 --- a/website/versioned_docs/version-v6.0.0/Modern-FragmentContainer.md +++ b/website/versioned_docs/version-v6.0.0/Modern-FragmentContainer.md @@ -17,12 +17,10 @@ Table of Contents: `createFragmentContainer` has the following signature: ```javascript - createFragmentContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, ): ReactComponentClass; - ``` ### Arguments @@ -43,7 +41,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -58,7 +55,6 @@ To start, let's build the plain React version of a hypothetical `` c Here's a basic implementation of `` that ignores styling in order to highlight the functionality: ```javascript - // TodoItem.js class TodoItem extends React.Component { render() { @@ -78,7 +74,6 @@ class TodoItem extends React.Component { ); } } - ``` ### Data Dependencies With GraphQL @@ -86,7 +81,6 @@ class TodoItem extends React.Component { In Relay, data dependencies are described using [GraphQL](https://github.com/facebook/graphql). For ``, the dependency can be expressed as follows. Note that this exactly matches the shape that the component expected for the `item` prop. ```javascript - graphql` # This fragment only applies to objects of type 'Todo'. fragment TodoItem_item on Todo { @@ -102,7 +96,6 @@ graphql` Given the plain React component and a GraphQL fragment, we can now define a Fragment Container to specify this component's data requirements. Let's look at the code first and then see what's happening: ```javascript - // TodoItem.js import {createFragmentContainer, graphql} from 'react-relay'; @@ -120,7 +113,6 @@ export default createFragmentContainer(TodoItem, { } `, }); - ``` ## Container Composition @@ -134,7 +126,6 @@ Let's explore how this works via a `` component that composes the `< View composition is _exactly_ what you're used to — Relay containers are just standard React components. Here's the `` component: ```javascript - class TodoList extends React.Component { render() { // Expects a `list` with a string `title`, as well as the information @@ -151,7 +142,6 @@ class TodoList extends React.Component { ); } } - ``` ### Composing Fragments @@ -159,7 +149,6 @@ class TodoList extends React.Component { Fragment composition works similarly — a parent container's fragment composes the fragment for each of its children. In this case, `` needs to fetch information about the `Todo`s that are required by ``. ```javascript - class TodoList extends React.Component // as above export default createFragmentContainer(TodoList, { @@ -176,7 +165,6 @@ export default createFragmentContainer(TodoList, { } `, }); - ``` Note that when composing fragments, the type of the composed fragment must match the field on the parent in which it is embedded. For example, it wouldn't make sense to embed a fragment of type `Story` into a parent's field of type `User`. Relay and GraphQL will provide helpful error messages if you get this wrong (and if they aren't helpful, let us know!). @@ -190,7 +178,6 @@ When defining a fragment, you can use the [`@argumentDefinitions`](./graphql-in- For example, let's redefine our `TodoList_list` fragment to take some arguments using `@argumentDefinitions`: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -200,7 +187,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` Any arguments defined inside `@argumentDefinitions` will be local variables available inside the fragment's scope. However, a fragment can also reference global variables that were defined in the root query. @@ -212,11 +198,9 @@ In order to pass arguments to a fragment that has `@argumentDefinitions`, you ne Following our `TodoList_list` example, we would pass arguments to the fragment like so: ```graphql - query TodoListQuery($count: Int, $userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` ## Rendering Containers diff --git a/website/versioned_docs/version-v6.0.0/Modern-GraphQLInRelay.md b/website/versioned_docs/version-v6.0.0/Modern-GraphQLInRelay.md index 71ee31bcccc83..1b26a80334a46 100644 --- a/website/versioned_docs/version-v6.0.0/Modern-GraphQLInRelay.md +++ b/website/versioned_docs/version-v6.0.0/Modern-GraphQLInRelay.md @@ -14,7 +14,6 @@ Table of Contents: The `graphql` template tag provided by Relay serves as the mechanism to write queries, fragments, mutations or subscriptions in the [GraphQL](http://graphql.org/learn/) language. For example: ```javascript - import {graphql} from 'react-relay'; graphql` @@ -24,7 +23,6 @@ graphql` } } `; - ``` The result of using the `graphql` template tag is a `GraphQLTaggedNode`; a runtime representation of the GraphQL document which can be used to define [Query Renderers](./query-renderer), [Fragment Containers](./fragment-container), [Refetch Containers](./refetch-container), [Pagination Containers](./pagination-container), etc. @@ -42,11 +40,9 @@ Relay uses directives to add additional information to GraphQL documents, which `@arguments` is a directive used to pass arguments to a fragment that was defined using [`@argumentDefinitions`](#argumentdefinitions). For example: ```graphql - query TodoListQuery($userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -56,7 +52,6 @@ See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fr `@argumentDefinitions` is a directive used to specify arguments taken by a fragment. For example: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -66,7 +61,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -80,7 +74,6 @@ When using the [Pagination Container](./pagination-container), Relay expects con When defining a fragment for use with a Fragment container, you can use the `@relay(plural: true)` directive to indicate that container expects the prop for that fragment to be a list of items instead of a single item. A query or parent that spreads a `@relay(plural: true)` fragment should do so within a plural field (ie a field backed by a [GraphQL list](http://graphql.org/learn/schema/#lists-and-non-null). For example: ```javascript - // Plural fragment definition graphql` fragment TodoItems_items on TodoItem @relay(plural: true) { @@ -95,7 +88,6 @@ fragment TodoApp_app on App { ...TodoItem_items } } - ``` ### `@inline` @@ -107,7 +99,6 @@ Non-React functions can also take advantage of data masking. A fragment can be d In the example below, the function `processItemData` is called from a React component. It requires an item object with a specific set of fields. All React components that use this function should spread the `processItemData_item` fragment to ensure all of the correct item data is loaded for this function. ```javascript - import {graphql, readInlineData} from 'react-relay'; // non-React function called from React @@ -127,11 +118,9 @@ function processItemData(itemRef) { creatorName: item.creator.name }); } - ``` ```javascript - // React Component function MyComponent({item}) { function handleClick() { @@ -151,7 +140,6 @@ export default createFragmentContainer(MyComponent, { } ` }); - ``` ### `@relay(mask: Boolean)` @@ -169,7 +157,6 @@ Keep in mind that it is typically considered an **anti-pattern** to create a sin In the example below, the `user` prop will include the data for `id` and `name` fields wherever `...Component_internUser` is included, instead of Relay's normal behavior to mask those fields: ```javascript - graphql` fragment Component_internUser on InternUser @relay(mask: false) { id @@ -197,7 +184,6 @@ export default createFragmentContainer( } `, ); - ``` ## Relay Compiler @@ -207,7 +193,6 @@ Relay uses the Relay Compiler to convert [`graphql`](#graphql) literals into gen A query like the following: ```javascript - graphql` fragment MyComponent on Type { field @@ -228,12 +213,10 @@ Relay Compiler supports the use of **persisted queries**, in which each version Persisted queries can be enabled by instructing Relay Compiler to emit metadata about each query, mutation, and subscription into a JSON file. The generated file will contain a mapping of query identifiers to query text, which you can then save to your server. To enable persisted queries, use the `--persist-output` flag to the compiler: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` Relay Compiler will then create the id => query text mapping in the path you specify. You can then use this complete @@ -250,7 +233,6 @@ See our relay-compiler section in our [Installation and Setup guide](./installat To use the Relay Compiler, you need either a .graphql or .json GraphQL schema file, describing your GraphQL server's API. Typically these files are local representations of a server source of truth and are not edited directly. For example, we might have a `schema.graphql` like: ```graphql - schema { query: Root } @@ -268,7 +250,6 @@ type WordDefinition { text: String image: String } - ``` ### Source files @@ -284,7 +265,6 @@ For example, given the two files: - `src/Components/DictionaryComponent.js` ```javascript - const DictionaryWordFragment = graphql` fragment DictionaryComponent_word on Word { id @@ -306,7 +286,6 @@ For example, given the two files: - `src/Queries/DictionaryQuery.js` ```javascript - const DictionaryQuery = graphql` query DictionaryQuery { dictionary { @@ -330,9 +309,7 @@ Typically you will not need to import your generated definitions. The [Relay Bab However the Relay Compiler also automatically generates [Flow](https://flow.org) types as [type comments](https://flow.org/en/docs/types/comments/). For example, you can import the generated Flow types like so: ```javascript - import type {DictionaryComponent_word} from './__generated__/DictionaryComponent_word.graphql'; - ``` ### Client schema extensions @@ -342,7 +319,6 @@ The Relay Compiler fully supports client-side schema extensions, which allows yo For example, assuming the server schema `./schema.graphql`: ```graphql - schema { query: Root } @@ -350,28 +326,23 @@ schema { type Root { title: String! } - ``` We can create a `./src/clientSchema.graphql` and define a new type called `Setting`: ```graphql - type Setting { name: String! active: Boolean! } - ``` We can then extend existing server types in the client schema `./src/clientSchema.graphql` with our new `Setting` type, like so: ```graphql - extend type Root { settings: [Setting] } - ``` Any fields specified in the client schema, can be fetched from the [Relay Store](./relay-store), by selecting it in a query or fragment. diff --git a/website/versioned_docs/version-v6.0.0/Modern-LocalStateManagement.md b/website/versioned_docs/version-v6.0.0/Modern-LocalStateManagement.md index 3121ff98c482e..7308c050a4507 100644 --- a/website/versioned_docs/version-v6.0.0/Modern-LocalStateManagement.md +++ b/website/versioned_docs/version-v6.0.0/Modern-LocalStateManagement.md @@ -24,23 +24,19 @@ It can even be used to extend an existing server schema. For example, we can create a new type called `Note`: ```graphql - type Note { ID: ID! title: String body: String } - ``` And then extend the server schema type `User`, with a list of `Note`, called `notes`. ```graphql - extend type User { notes: [Note] } - ``` ## Querying local state @@ -51,7 +47,6 @@ The field can be from the server schema, or it can be schema agnostic, like an i Here, we use a [QueryRenderer](./query-renderer) to get the current `User` via the `viewer` field, along with their id, name and the local list of notes. ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -97,7 +92,6 @@ const Example = (props) => { /> ); } - ``` ## Mutating local state @@ -111,7 +105,6 @@ To build upon the previous example, let's try creating, updating and deleting a ### Create ```javascript - import {commitLocalUpdate} from 'react-relay'; let tempID = 0; @@ -131,7 +124,6 @@ function createUserNote() { user.setLinkedRecords([...userNoteRecords, newNoteRecord], 'notes'); }); } - ``` Note that since this record will be rendered by the `ExampleQuery` in our `QueryRenderer`, the QueryRenderer will automatically retain this data so it isn't garbage collected. @@ -139,20 +131,17 @@ Note that since this record will be rendered by the `ExampleQuery` in our `Query If no component is rendering the local data and you want to manually retain it, you can do so by calling `environment.retain()`: ```javascript - // Tell Relay to retain the record so it isn't garbage collected environment.retain({ dataID, variables: {}, node: { selections: [] } }); - ``` ### Update ```javascript - import {commitLocalUpdate} from 'react-relay'; function updateUserNote(dataID, body, title) { @@ -163,13 +152,11 @@ function updateUserNote(dataID, body, title) { note.setValue(title, 'title') }); } - ``` ### Delete ```javascript - import {commitLocalUpdate} from 'react-relay'; function deleteUserNote(dataID) { @@ -187,7 +174,6 @@ function deleteUserNote(dataID) { user.setLinkedRecords(newUserNoteRecords, 'notes'); }); } - ``` ## Initial local state @@ -196,7 +182,6 @@ All new client-side schema fields default to `undefined` value. Often however, y You can use an updater function via `commitLocalUpdate` to prime local state. ```javascript - import {commitLocalUpdate} from 'react-relay'; commitLocalUpdate(environment, store => { @@ -205,5 +190,4 @@ commitLocalUpdate(environment, store => { // initialize user notes to an empty array. user.setLinkedRecords([], 'notes'); }); - ``` diff --git a/website/versioned_docs/version-v6.0.0/Modern-MigrationSetup.md b/website/versioned_docs/version-v6.0.0/Modern-MigrationSetup.md index 66f1145357e25..a89c0e178e0e5 100644 --- a/website/versioned_docs/version-v6.0.0/Modern-MigrationSetup.md +++ b/website/versioned_docs/version-v6.0.0/Modern-MigrationSetup.md @@ -13,13 +13,11 @@ With some additional configuration, the `"relay"` babel plugin can also translat Relay Classic `Relay.QL` literals. Most importantly, include a reference to your GraphQL Schema as either a json file or graphql schema file. ```javascript - { "plugins": [ ["relay", {"schema": "path/schema.graphql"}] ] } - ``` ## Set up babel-plugin-relay for "[compatibility mode](./relay-compat)" @@ -29,13 +27,11 @@ literals can be translated to be usable by _both_ runtimes if configured to use compatibility mode: ```javascript - { "plugins": [ ["relay", {"compat": true, "schema": "path/schema.graphql"}] ] } - ``` ## Additional Options @@ -47,7 +43,6 @@ thrown at runtime. When compiling code for production deployment, the plugin can be configured to immediately throw upon encountering a validation problem. The plugin can be further customized for different environments with the following options: ```javascript - { "plugins": [ ["relay", { @@ -56,5 +51,4 @@ When compiling code for production deployment, the plugin can be configured to i }] ] } - ``` diff --git a/website/versioned_docs/version-v6.0.0/Modern-Mutations.md b/website/versioned_docs/version-v6.0.0/Modern-Mutations.md index a2e0b285bf2c4..8da3bd999c701 100644 --- a/website/versioned_docs/version-v6.0.0/Modern-Mutations.md +++ b/website/versioned_docs/version-v6.0.0/Modern-Mutations.md @@ -17,7 +17,6 @@ Table of Contents: Use `commitMutation` to create and execute mutations. `commitMutation` has the following signature: ```javascript - commitMutation( environment: Environment, config: { @@ -31,7 +30,6 @@ commitMutation( configs?: Array, }, ); - ``` ### Arguments @@ -58,7 +56,6 @@ commitMutation( Example of a simple mutation: ```javascript - import {commitMutation, graphql} from 'react-relay'; const mutation = graphql` @@ -93,7 +90,6 @@ function markNotificationAsRead(environment, source, storyID) { }, ); } - ``` ## Optimistic Updates @@ -101,7 +97,6 @@ function markNotificationAsRead(environment, source, storyID) { To improve perceived responsiveness, you may wish to perform an "optimistic update", in which the client immediately updates to reflect the anticipated new value even before the response from the server has come back. The simplest way to do this is by providing an `optimisticResponse` and adding it to the `config` that we pass into `commitMutation`: ```javascript - const mutation = graphql` mutation MarkReadNotificationMutation( $input: MarkReadNotificationInput! @@ -130,7 +125,6 @@ commitMutation( variables, }, ); - ``` Another way to enable optimistic updates is via the `optimisticUpdater`, which can be used for more complicated update scenarios. Using `optimisticUpdater` is covered in the section [below](#using-updater-and-optimisticupdater). @@ -152,7 +146,6 @@ Given a deletedIDFieldName, Relay will remove the node(s) from the store. #### Example ```javascript - const mutation = graphql` mutation DestroyShipMutation($input: DestroyShipInput!) { destroyShip(input: $input) { @@ -170,7 +163,6 @@ const configs = [{ type: 'NODE_DELETE', deletedIDFieldName: 'destroyedShipId', }]; - ``` ### RANGE_ADD @@ -190,7 +182,6 @@ Given a parent, information about the connection, and the name of the newly crea #### Example ```javascript - const mutation = graphql` mutation AddShipMutation($input: AddShipInput!) { addShip(input: $input) { @@ -220,7 +211,6 @@ function commit(environment, factionId, name) { }], }); } - ``` ### RANGE_DELETE @@ -242,7 +232,6 @@ from the connection but leave the associated record(s) in the store. #### Example ```javascript - const mutation = graphql` mutation RemoveTagMutation($input: RemoveTagInput!) { removeTag(input: $input) { @@ -268,7 +257,6 @@ function commit(environment, todoId, tagId) { }], }); } - ``` ## Using updater and optimisticUpdater @@ -286,7 +274,6 @@ When you provide these functions, this is roughly what happens during the mutati Here are a quick example of adding a todo item to a Todo list using this [example schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L36): ```javascript - // AddTodoMutation.js import {commitMutation, graphql} from 'react-relay'; import {ConnectionHandler} from 'relay-runtime'; @@ -373,7 +360,6 @@ function commit(environment, text, user) { }, }); } - ``` For details on how to interact with the Relay Store, please refer to our Relay Store [docs](./relay-store). diff --git a/website/versioned_docs/version-v6.0.0/Modern-NetworkLayer.md b/website/versioned_docs/version-v6.0.0/Modern-NetworkLayer.md index fcd9fd4dd5e03..daa8c71294c59 100644 --- a/website/versioned_docs/version-v6.0.0/Modern-NetworkLayer.md +++ b/website/versioned_docs/version-v6.0.0/Modern-NetworkLayer.md @@ -8,7 +8,6 @@ In order to know how to access your GraphQL server, Relay Modern requires develo Currently the easiest way to create a network layer is via a helper from the `relay-runtime` package: ```javascript - import { Environment, Network, @@ -50,7 +49,6 @@ const environment = new Environment({ }); export default environment; - ``` Note that this is a basic example to help you get started. This example could be extended with additional features such as request/response caching (enabled e.g. when `cacheConfig.force` is false) and uploading form data for mutations (the `uploadables` parameter). @@ -62,7 +60,6 @@ Relay modern makes no assumptions about what to cache and will garbage collect a You have to implement your own cache strategy. A simple solution is to use `RelayQueryResponseCache`(an in-memory cache): ```javascript - import { Environment, Network, @@ -126,7 +123,6 @@ const environment = new Environment({ }); export default environment; - ``` ## Custom open-source implementations diff --git a/website/versioned_docs/version-v6.0.0/Modern-PaginationContainer.md b/website/versioned_docs/version-v6.0.0/Modern-PaginationContainer.md index 6ac3aac8cfb8e..57980d553af9b 100644 --- a/website/versioned_docs/version-v6.0.0/Modern-PaginationContainer.md +++ b/website/versioned_docs/version-v6.0.0/Modern-PaginationContainer.md @@ -24,7 +24,6 @@ However, when [specifying connection fragments](#createpaginationcontainer) for The purpose of the `@connection` directive is to allow Relay to uniquely identify different connections under a parent type. The `@connection` directive takes 2 arguments that help identify the connection: ```graphql - @connection(key: String!, filters: [String]) ``` @@ -37,7 +36,6 @@ The purpose of the `@connection` directive is to allow Relay to uniquely identif Specifying just the `key`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and the value of `$orderBy` (given that no `filters` were provided) @@ -53,13 +51,11 @@ fragment Feed_user on User { } } } - ``` Specifying `key` and `filters`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and /only/ the value of `$searchTerm`, i.e. @@ -77,7 +73,6 @@ fragment Feed_user on User { } } } - ``` ## `createPaginationContainer` @@ -85,7 +80,6 @@ fragment Feed_user on User { `createPaginationContainer` has the following signature: ```javascript - createPaginationContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, @@ -113,7 +107,6 @@ type ConnectionData = { startCursor: ?string, }, }; - ``` ### Arguments @@ -134,7 +127,6 @@ type ConnectionData = { The Component resulting from `createPaginationContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -145,7 +137,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -160,7 +151,6 @@ type Props = { `hasMore` is a function available on the `relay` [prop](#available-props). This function indicates whether there are more pages to fetch from the server or not. ```javascript - hasMore: () => boolean, ``` @@ -170,7 +160,6 @@ hasMore: () => boolean, `isLoading` is a function available on the `relay` [prop](#available-props). This function indicates if a previous call to [`loadMore()`](#loadmore) is still pending. This is convenient for avoiding duplicate load calls. ```javascript - isLoading: () => boolean, ``` @@ -180,7 +169,6 @@ isLoading: () => boolean, `loadMore` is a function available on the `relay` [prop](#available-props). You can call `loadMore()` to fetch more items from the server based on the `connectionConfig` provided to the container. This will return null if there are no more items to fetch, otherwise it will fetch more items and return a Disposable that can be used to cancel the fetch. ```javascript - loadMore( pageSize: number, callback: ?(error: ?Error) => void, @@ -201,7 +189,6 @@ loadMore( `refetchConnection` is a function available on the `relay` [prop](#available-props). You can call `refetchConnection` to restart pagination on a connection from scratch, with optionally a completely new set of variables to pass to the pagination `query`. This is useful for example if you are paginating over a collection based on a userID and the userID changes, you'd want to start paginating over the new collection for the new user. ```javascript - refetchConnection:( totalCount: number, callback: (error: ?Error) => void, @@ -219,7 +206,6 @@ refetchConnection:( ## Pagination Example ```javascript - // Feed.js import {createPaginationContainer, graphql} from 'react-relay'; @@ -314,5 +300,4 @@ module.exports = createPaginationContainer( ` } ); - ``` diff --git a/website/versioned_docs/version-v6.0.0/Modern-PersistedQueries.md b/website/versioned_docs/version-v6.0.0/Modern-PersistedQueries.md index 137cc2e23220c..ec03b69ba09c3 100644 --- a/website/versioned_docs/version-v6.0.0/Modern-PersistedQueries.md +++ b/website/versioned_docs/version-v6.0.0/Modern-PersistedQueries.md @@ -17,12 +17,10 @@ The relay compiler supports persisted queries which is useful because: In your `npm` script in `package.json`, run the relay compiler using the `--persist-output` flag: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` The `--persist-ouput` flag does 3 things: @@ -31,8 +29,7 @@ The `--persist-ouput` flag does 3 things: For example without `--persist-output`, a generated `ConcreteRequest` might look like below: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -49,8 +46,7 @@ The `--persist-ouput` flag does 3 things: With `--persist-output ` this becomes: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -68,12 +64,10 @@ The `--persist-ouput` flag does 3 things: 2. It generates a JSON file at the `` you specify containing a mapping from query ids to the corresponding operation texts. -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./src/queryMaps/queryMap.json" } - ``` The example above writes the complete query map file to `./src/queryMaps/queryMap.json`. You need to ensure all the directories @@ -83,8 +77,7 @@ leading to the `queryMap.json` file exist. You'll need to modify your network layer fetch implementation to pass a documentId parameter in the POST body instead of a query parameter: -```js - +```javascript function fetchQuery(operation, variables,) { return fetch('/graphql', { method: 'POST', @@ -100,7 +93,6 @@ function fetchQuery(operation, variables,) { return response.json(); }); } - ``` ## Executing Persisted Queries on the Server @@ -116,13 +108,11 @@ the query map file in a common location accessible to both the client and the se For applications where the client and server projects are separate, one option is to have an additional npm run script to push the query map at compile time to a location accessible by your server: -```js - +```javascript "scripts": { "push-queries": "node ./pushQueries.js", "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-ouput && npm run push-queries" } - ``` Some possibilities of what you can do in `./pushQueries.js`: @@ -146,8 +136,7 @@ database technologies you use, so we'll just cover the most common and basic exa If you use `express-graphql` and have access to the query map file, you can import the `--persist-output` JSON file directly and perform the matching using the `matchQueryMiddleware` from [relay-compiler-plus](https://github.com/yusinto/relay-compiler-plus). -```js - +```javascript import Express from 'express'; import expressGraphql from 'express-graphql'; import {matchQueryMiddleware} from 'relay-compiler-plus'; @@ -158,7 +147,6 @@ const app = Express(); app.use('/graphql', matchQueryMiddleware(queryMapJson), expressGraphql({schema})); - ``` ## Using `--persist-output` and `--watch` diff --git a/website/versioned_docs/version-v6.0.0/Modern-QueryRenderer.md b/website/versioned_docs/version-v6.0.0/Modern-QueryRenderer.md index cf6c37f3d9a4d..b621ef9986bf1 100644 --- a/website/versioned_docs/version-v6.0.0/Modern-QueryRenderer.md +++ b/website/versioned_docs/version-v6.0.0/Modern-QueryRenderer.md @@ -24,7 +24,6 @@ However, a `QueryRenderer` will not start loading its data until it is mounted, ## Example ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -56,5 +55,4 @@ const Example = (props) => { /> ); } - ``` diff --git a/website/versioned_docs/version-v6.0.0/Modern-RefetchContainer.md b/website/versioned_docs/version-v6.0.0/Modern-RefetchContainer.md index 7ce0d14e45417..51c2c44db8941 100644 --- a/website/versioned_docs/version-v6.0.0/Modern-RefetchContainer.md +++ b/website/versioned_docs/version-v6.0.0/Modern-RefetchContainer.md @@ -16,13 +16,11 @@ Table of Contents: `createRefetchContainer` has the following signature: ```javascript - createRefetchContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, refetchQuery: GraphQLTaggedNode, ): ReactComponentClass; - ``` ### Arguments @@ -37,7 +35,6 @@ createRefetchContainer( The Component resulting from `createRefetchContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -45,7 +42,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -61,7 +57,6 @@ type Props = { `refetch` has the following signature: ```javascript - type RefetchOptions = { force?: boolean, }; @@ -102,7 +97,6 @@ Returns a `Disposable` on which you could call `dispose()` to cancel the refetch In this simple example, let's assume we want to fetch the latest data for a `TodoItem` from the server: ```javascript - // TodoItem.js import {createRefetchContainer, graphql} from 'react-relay'; @@ -148,7 +142,6 @@ export default createRefetchContainer( } ` ); - ``` ### Loading more data @@ -156,7 +149,6 @@ export default createRefetchContainer( In this example we are using a Refetch Container to fetch more stories in a story feed component. ```javascript - import {createRefetchContainer, graphql} from 'react-relay'; class FeedStories extends React.Component { @@ -212,5 +204,4 @@ export default createRefetchContainer( } `, ); - ``` diff --git a/website/versioned_docs/version-v6.0.0/Modern-RelayCompat.md b/website/versioned_docs/version-v6.0.0/Modern-RelayCompat.md index 36632d3a8f1a1..f47dbd845ba3e 100644 --- a/website/versioned_docs/version-v6.0.0/Modern-RelayCompat.md +++ b/website/versioned_docs/version-v6.0.0/Modern-RelayCompat.md @@ -31,7 +31,6 @@ Relay Modern. The components using Relay Compat can be referred to by both other Relay Modern and Relay Classic components. ```javascript - const {createFragmentContainer, graphql} = require('react-relay/compat'); class TodoItem extends React.Component { @@ -47,5 +46,4 @@ module.exports = createFragmentContainer(TodoItem, graphql` isComplete } `); - ``` diff --git a/website/versioned_docs/version-v6.0.0/Modern-RelayEnvironment.md b/website/versioned_docs/version-v6.0.0/Modern-RelayEnvironment.md index 27d90b2fc4fe1..99e728bce740d 100644 --- a/website/versioned_docs/version-v6.0.0/Modern-RelayEnvironment.md +++ b/website/versioned_docs/version-v6.0.0/Modern-RelayEnvironment.md @@ -12,7 +12,6 @@ Most applications will create a single Environment instance and use it throughou To create an environment instance in Relay Modern, use the `RelayModernEnvironment` class: ```javascript - const { Environment, Network, @@ -30,7 +29,6 @@ const environment = new Environment({ network, store, }); - ``` For more details on creating a Network, see the [NetworkLayer guide](./network-layer). @@ -44,7 +42,6 @@ The example above did not configure a `handlerProvider`, which means that a defa If you wish to provide your own `handlerProvider`, you can do so: ```javascript - const { ConnectionHandler, } = require('relay-runtime'); @@ -58,5 +55,4 @@ function handlerProvider(handle) { `handlerProvider: No handler provided for ${handle}` ); } - ``` diff --git a/website/versioned_docs/version-v6.0.0/Modern-RelayStore.md b/website/versioned_docs/version-v6.0.0/Modern-RelayStore.md index 8bc27098b205e..56b91d3036791 100644 --- a/website/versioned_docs/version-v6.0.0/Modern-RelayStore.md +++ b/website/versioned_docs/version-v6.0.0/Modern-RelayStore.md @@ -16,7 +16,6 @@ Table of Contents: The `RecordSourceSelectorProxy` is the type of the `store` that [`updater` functions](./mutations#using-updater-and-optimisticupdater) receive as an argument. The following is the `RecordSourceSelectorProxy` interface: ```javascript - interface RecordSourceSelectorProxy { create(dataID: string, typeName: string): RecordProxy; delete(dataID: string): void; @@ -25,7 +24,6 @@ interface RecordSourceSelectorProxy { getRootField(fieldName: string): ?RecordProxy; getPluralRootField(fieldName: string): ?Array; } - ``` ### `create(dataID: string, typeName: string): RecordProxy` @@ -35,9 +33,7 @@ Creates a new record in the store given a `dataID` and the `typeName` as defined #### Example ```javascript - const record = store.create(dataID, 'Todo'); - ``` ### `delete(dataID: string): void` @@ -47,9 +43,7 @@ Deletes a record from the store given its `dataID`. #### Example ```javascript - store.delete(dataID); - ``` ### `get(dataID: string): ?RecordProxy` @@ -59,9 +53,7 @@ Retrieves a record from the store given its `dataID`. Returns a [`RecordProxy`]( #### Example ```javascript - const record = store.get(dataID); - ``` ### `getRoot(): RecordProxy` @@ -73,20 +65,16 @@ Returns the [`RecordProxy`](#recordproxy) representing the root of the GraphQL d Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - // Represents root query const root = store.getRoot(); - ``` ### `getRootField(fieldName: string): ?RecordProxy` @@ -98,19 +86,15 @@ Retrieves a root field from the store given the `fieldName`, as defined by the G Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - const viewer = store.getRootField('viewer'); - ``` ### `getPluralRootField(fieldName: string): ?Array` @@ -122,19 +106,15 @@ Retrieves a root field that represents a collection from the store given the `fi Given the GraphQL document: ```graphql - nodes(first: 10) { # ... } - ``` Usage: ```javascript - const nodes = store.getPluralRootField('nodes'); - ``` ## RecordProxy @@ -142,7 +122,6 @@ const nodes = store.getPluralRootField('nodes'); The `RecordProxy` serves as an interface to mutate records: ```javascript - interface RecordProxy { copyFieldsFrom(sourceRecord: RecordProxy): void; getDataID(): string; @@ -167,7 +146,6 @@ interface RecordProxy { ): RecordProxy; setValue(value: mixed, name: string, arguments?: ?Object): RecordProxy; } - ``` ### `getDataID(): string` @@ -177,9 +155,7 @@ Returns the dataID of the current record. #### Example ```javascript - const id = record.getDataID(); - ``` ### `getType(): string` @@ -189,7 +165,6 @@ Gets the type of the current record, as defined by the GraphQL schema. #### Example ```javascript - const type = user.getType(); // User ``` @@ -203,20 +178,16 @@ Gets the value of a field in the current record given the field name. Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - const name = viewer.getValue('name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. @@ -226,20 +197,16 @@ Optionally, if the field takes arguments, you can pass a bag of `variables`. Given the GraphQL document: ```graphql - viewer { id name(arg: $arg) } - ``` Usage: ```javascript - const name = viewer.getValue('name', {arg: 'value'}); - ``` ### `getLinkedRecord(name: string, arguments?: ?Object): ?RecordProxy` @@ -251,23 +218,19 @@ Retrieves a record associated with the current record given the field name, as d Given the GraphQL document: ```graphql - rootField { viewer { id name } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -277,22 +240,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { viewer(arg: $arg) { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {arg: 'value'}); - ``` ### `getLinkedRecords(name: string, arguments?: ?Object): ?Array` @@ -304,22 +263,18 @@ Retrieves the set of records associated with the current record given the field Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const nodes = rootField.getLinkedRecords('nodes'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -329,22 +284,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { nodes(first: $count) { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {count: 10}); - ``` ### `getOrCreateLinkedRecord(name: string, typeName: string, arguments?: ?Object)` @@ -356,19 +307,16 @@ Retrieves the a record associated with the current record given the field name, Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = rootField.getOrCreateLinkedRecord('viewer', 'User'); // Will create if it doesn't exist @@ -383,28 +331,22 @@ Mutates the current record by setting a new value on the specified field. Return Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - viewer.setValue('New Name', 'name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. ```javascript - viewer.setValue('New Name', 'name', {arg: 'value'}); - ``` ### `copyFieldsFrom(sourceRecord: RecordProxy): void` @@ -414,7 +356,6 @@ Mutates the current record by copying the fields over from the passed in record #### Example ```javascript - const record = store.get(id1); const otherRecord = store.get(id2); record.copyFieldsFrom(otherRecord); // Mutates `record` @@ -430,19 +371,16 @@ Mutates the current record by setting a new linked record on the given the field Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = store.create(/* ... */)'' rootField.setLinkedRecord(newViewer, 'viewer'); // @@ -460,19 +398,16 @@ Mutates the current record by setting a new set of linked records on the given t Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newNode = store.create(/* ... */); const newNodes = [...rootField.getLinkedRecords('nodes'), newNode]; @@ -487,7 +422,6 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl `ConnectionHandler` is a utility module exposed by `relay-runtime` that aids in the manipulation of connections. `ConnectionHandler` exposes the following interface: ```javascript - interface ConnectionHandler { getConnection( record: RecordProxy, @@ -512,7 +446,6 @@ interface ConnectionHandler { ): void, deleteNode(connection: RecordProxy, nodeID: string): void } - ``` ### `getConnection(record: RecordProxy, key: string, filters?: ?Object)` @@ -522,7 +455,6 @@ Given a record and a connection key, and optionally a set of filters, `getConnec First, let's take a look at a plain connection: ```graphql - fragment FriendsFragment on User { friends(first: 10) { edges { @@ -532,26 +464,22 @@ fragment FriendsFragment on User { } } } - ``` Accessing a plain connection field like this is the same as other regular field: ```javascript - // The `friends` connection record can be accessed with: const user = store.get(userID); const friends = user && user.getLinkedRecord(user, 'friends'); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` In a [pagination container](./pagination-container), we usually annotate the actual connection field with `@connection` to tell Relay which part needs to be paginated: ```graphql - fragment FriendsFragment on User { friends(first: 10, orderby: "firstname") @connection( key: "FriendsFragment_friends", @@ -563,7 +491,6 @@ fragment FriendsFragment on User { } } } - ``` For connections like the above, `ConnectionHandler` helps us find the record: @@ -581,7 +508,6 @@ const friends = ConnectionHandler.getConnection( ); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` ### Edge creation and insertion @@ -611,7 +537,6 @@ ConnectionHandler.insertEdgeAfter(friends, edge); // No cursor provided, Insert the edge at the front: ConnectionHandler.insertEdgeBefore(friends, edge); - ``` ### `deleteNode(connection: RecordProxy, nodeID: string): void` @@ -625,5 +550,4 @@ Given a connection, deletes any edges whose id matches the given id. const user = store.get(userID); const friends = ConnectionHandler.getConnection(user, 'friends'); ConnectionHandler.deleteNode(friends, idToDelete); - ``` diff --git a/website/versioned_docs/version-v6.0.0/Modern-Subscriptions.md b/website/versioned_docs/version-v6.0.0/Modern-Subscriptions.md index 802f1d02b06de..bd1c5fe2f350c 100644 --- a/website/versioned_docs/version-v6.0.0/Modern-Subscriptions.md +++ b/website/versioned_docs/version-v6.0.0/Modern-Subscriptions.md @@ -6,7 +6,6 @@ original_id: subscriptions Relay exposes the following APIs to create subscriptions. ```javascript - const {requestSubscription} = require('react-relay'); type Variables = {[name: string]: any}; @@ -27,7 +26,6 @@ requestSubscription( configs?: Array, }, ) => Disposable; - ``` The function returns a `Disposable` on which you could call `dispose()` to cancel the refetch. @@ -53,7 +51,6 @@ appropriate when you are only changing the properties of existing records that can be identified by their `id`: ```javascript - const { requestSubscription, graphql, @@ -87,7 +84,6 @@ requestSubscription( onError: error => console.error(error), } ); - ``` # Updating the client on each response @@ -97,7 +93,6 @@ Relay's in-memory cache when each subscription response is received. To do so, pass an `updater` function: ```javascript - const {ConnectionHandler} = require('relay-runtime'); requestSubscription( @@ -123,5 +118,4 @@ requestSubscription( }, }, ); - ``` diff --git a/website/versioned_docs/version-v6.0.0/Modern-TestingRelayComponents.md b/website/versioned_docs/version-v6.0.0/Modern-TestingRelayComponents.md index 4e5cf9e61a922..2916a65f56e06 100644 --- a/website/versioned_docs/version-v6.0.0/Modern-TestingRelayComponents.md +++ b/website/versioned_docs/version-v6.0.0/Modern-TestingRelayComponents.md @@ -65,7 +65,6 @@ MockPayloadGenerator may drastically simplify the process of creating and mainta Example of a simple Mock Resolver: ```javascript - { ID() { // Return mock value for a scalar filed with type ID @@ -76,13 +75,11 @@ Example of a simple Mock Resolver: return "Lorem Ipsum" } } - ``` It is possible to define more resolvers for Object types ```javascript - { // This will be the default values for User object in the query response User() { @@ -95,7 +92,6 @@ It is possible to define more resolvers for Object types }; }, } - ``` ### Mock Resolver Context @@ -103,7 +99,6 @@ It is possible to define more resolvers for Object types The first argument of the MockResolver is the object that contains Mock Resolver Context. It is possible to return dynamic values from mock resolvers based on the context - for instance, name or alias of the field, a path in the selection, arguments, or parent type. ```javascript - { String(context) { if (context.name === 'zip') { @@ -117,7 +112,6 @@ The first argument of the MockResolver is the object that contains Mock Resolver } } } - ``` ### ID Generation @@ -125,14 +119,12 @@ The first argument of the MockResolver is the object that contains Mock Resolver The second argument of the Mock Resolver its a function that will generate a sequence of integers, useful to generate unique ids in the tests ```javascript - { // will generate strings "my-id-1", "my-id-2", etc. ID(_, generateId) { return `my-id-${generateId()}`; }, } - ``` ### @relay_test_operation @@ -142,7 +134,6 @@ Most of GraphQL type information for a specific field in the selection is not av Operation with the @relay_test_operation directive will have additional metadata that will contain GraphQL type info for fields in the operation's selection. And it will improve the quality of the generated data. You also will be able to define Mock resolvers for Scalar (not only ID and String) and Abstract types: ```javascript - { Float() { return 123.456; @@ -160,7 +151,6 @@ Operation with the @relay_test_operation directive will have additional metadata }; } } - ``` ## Examples @@ -170,7 +160,6 @@ Operation with the @relay_test_operation directive will have additional metadata Using `createMockEnvironment` and `MockPayloadGenerator` allows writing concise tests for components that are using Relay Containers and Renderers. Both those modules can be imported from `relay-test-utils` ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { @@ -223,7 +212,6 @@ test('Error State', () => { renderer.root.find(item => (item.props.testID = 'errorMessage')), ).toBeDefined(); }); - ``` ### Fragment Container Tests @@ -231,7 +219,6 @@ test('Error State', () => { Essentially, in the example above will `resolveMostRecentOperation` will generate data for all child fragment containers (pagination, refetch). But, usually the Root Components container may have many child fragment components and you may want to exercise a specific Fragment Container. The solution for that would be to wrap you fragment container with the QueryRenderer that renders a Query that's spreads fragments from you fragment container. ```javascript - test('Fragment Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -262,7 +249,6 @@ test('Fragment Container', () => { expect(renderer).toMatchSnapshot(); }); - ``` ### Pagination Container Test @@ -270,7 +256,6 @@ test('Fragment Container', () => { Essentially, tests for Pagination container are not different from Fragment Container tests. But we can do more here, we can actually see how the pagination works - we can assert the behavior of our components when performing pagination (load more, refetch). ```javascript - // Pagination Example test('Pagination Container', () => { const environment = createMockEnvironment(); @@ -344,7 +329,6 @@ test('Pagination Container', () => { We can use similar approach here with wrapping container with Query Renderer. And for the sake of completeness, we will add example here: ```javascript - test('Refetch Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -386,7 +370,6 @@ test('Refetch Container', () => { ); // expect(renderer).toMatchSnapshot(); }); - ``` ### Mutations @@ -394,7 +377,6 @@ test('Refetch Container', () => { Mutations itself are operations so we can test them independently (unit-test) for specific mutation, or in combination with the view from which this mutation is called. ```javascript - // Say, you have a mutation function function sendMutation(environment, onCompleted, onError, variables) commitMutation(environment, { @@ -417,7 +399,6 @@ test('it should send mutation', () => { ); expect(onCompleted).toBeCalled(); }); - ``` ### Subscription @@ -425,7 +406,6 @@ test('it should send mutation', () => { We can test subscription in a similar way we test mutations ```javascript - // Example subscribe function function subscribe(environment, onNext, onError, variables) requestSubscription(environment, { @@ -448,7 +428,6 @@ test('it should subscribe', () => { ); expect(onNext).toBeCalled(); }); - ``` ### Example with `queueOperationResolver` @@ -456,7 +435,6 @@ test('it should subscribe', () => { With `queueOpeararionResolver` it possible to define responses for operations that will be executed on the environment ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { diff --git a/website/versioned_docs/version-v6.0.0/Modern-TypeEmission.md b/website/versioned_docs/version-v6.0.0/Modern-TypeEmission.md index 63614b869a322..4ff63e4a7d81b 100644 --- a/website/versioned_docs/version-v6.0.0/Modern-TypeEmission.md +++ b/website/versioned_docs/version-v6.0.0/Modern-TypeEmission.md @@ -16,7 +16,6 @@ In this example the emitted type-information would require the variables object #### Flow ```javascript - /** * export type ExampleQueryVariables = {| * +artistID: string @@ -44,7 +43,6 @@ const variables: ExampleQueryVariables = { #### TypeScript ```javascript - /** * export type ExampleQueryVariables = { * readonly artistID: string @@ -79,7 +77,6 @@ In this example the emitted type-information describes the response data availab #### Flow ```javascript - /** * export type ExampleQueryResponse = {| * +artist: ?{| @@ -110,7 +107,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * export type ExampleQueryResponse = { * readonly artist?: { @@ -146,7 +142,6 @@ Similarly, in this example the emitted type-information describes the prop data #### Flow ```javascript - /** * export type ExampleFragment_artist = {| * +name: string @@ -172,7 +167,6 @@ export const ExampleFragment = createFragmentContainer( #### TypeScript ```javascript - /** * export type ExampleFragment_artist = { * readonly name: string @@ -206,7 +200,6 @@ Consider a component that composes the above fragment container example. In this #### Flow ```javascript - /** * import type { FragmentReference } from "relay-runtime"; * declare export opaque type ExampleFragment_artist$ref: FragmentReference; @@ -250,7 +243,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * declare const _ExampleFragment_artist$ref: unique symbol; * export type ExampleFragment_artist$ref = typeof _ExampleFragment_artist$ref; @@ -315,7 +307,6 @@ $ relay-compiler --artifactDirectory ./src/__generated__ […] ["relay", { "artifactDirectory": "./src/__generated__" }] ] } - ``` It is recommended to alias this directory in your module resolution configuration such that you don’t need to specify relative paths in your source files. This is what is also done in the above examples, where artifacts are imported from a `__generated__` alias, rather than relative paths like `../../../../__generated__`. diff --git a/website/versioned_docs/version-v6.0.0/Modern-UpgradingSetVariables.md b/website/versioned_docs/version-v6.0.0/Modern-UpgradingSetVariables.md index d5b086fafce20..ff73feec04f8b 100644 --- a/website/versioned_docs/version-v6.0.0/Modern-UpgradingSetVariables.md +++ b/website/versioned_docs/version-v6.0.0/Modern-UpgradingSetVariables.md @@ -36,7 +36,6 @@ fragment on User { # ... } } - ``` This should be upgraded to use a [`PaginationContainer`](./pagination-container). @@ -61,7 +60,6 @@ fragment on User { # ... } } - ``` This can be upgraded by using a [`RefetchContainer`](./refetch-container) which allows you to specify the exact query to use to fetch the new data. @@ -86,7 +84,6 @@ fragment on FeedbackTarget { # ... } } - ``` This can be upgraded by conditionally rendering a [`QueryRenderer`](./query-renderer) which will load the data once it is rendered. The code overhead of doing this is dramatically reduced with the new API. diff --git a/website/versioned_docs/version-v6.0.0/Modern-fetchQuery.md b/website/versioned_docs/version-v6.0.0/Modern-fetchQuery.md index e9dcf908db91a..d266ae9d7c67a 100644 --- a/website/versioned_docs/version-v6.0.0/Modern-fetchQuery.md +++ b/website/versioned_docs/version-v6.0.0/Modern-fetchQuery.md @@ -6,7 +6,6 @@ original_id: fetch-query You can use the `fetchQuery` function to imperatively make GraphQL Requests. This is useful for cases where you want to make requests outside of React but still utilize the Relay store and network layer. ```javascript - import {fetchQuery, graphql} from 'relay-runtime'; const query = graphql` @@ -25,7 +24,6 @@ fetchQuery(environment, query, variables) .then(data => { // access the graphql response }); - ``` ## Arguments diff --git a/website/versioned_docs/version-v6.0.0/PrinciplesAndArchitecture-Compiler.md b/website/versioned_docs/version-v6.0.0/PrinciplesAndArchitecture-Compiler.md index c195491682b1f..fcd0490cb724f 100644 --- a/website/versioned_docs/version-v6.0.0/PrinciplesAndArchitecture-Compiler.md +++ b/website/versioned_docs/version-v6.0.0/PrinciplesAndArchitecture-Compiler.md @@ -74,7 +74,6 @@ foo { # type FooType foo { id } - ``` - `SkipRedundantNodeTransform`: A more advanced version of flattening, this eliminates more complex cases of field duplication such as when a field is fetched both unconditionally and conditionally, or is fetched by two different sub-fragments. For example: @@ -97,7 +96,6 @@ foo { id } } - ``` - `GenerateRequisiteFieldTransform`: This optional, Relay-specific transform inserts `id` fields for globally identifiable objects and `__typename` fields wherever the type cannot be statically determined (e.g. for unions). diff --git a/website/versioned_docs/version-v6.0.0/PrinciplesAndArchitecture-Runtime.md b/website/versioned_docs/version-v6.0.0/PrinciplesAndArchitecture-Runtime.md index 9491d290c146f..e9221631a701d 100644 --- a/website/versioned_docs/version-v6.0.0/PrinciplesAndArchitecture-Runtime.md +++ b/website/versioned_docs/version-v6.0.0/PrinciplesAndArchitecture-Runtime.md @@ -77,7 +77,6 @@ RecordSource { city: 'Seattle', } } - ``` [1] Note that GraphQL itself does not impose this constraint, and Relay Runtime may also be used for schemas that do not conform to it. For example, both systems can be used to query a single denormalized table. However, many of the features that Relay Runtime provides, such as caching and normalization, work best when the data is represented as a normalized graph with stable identities for discrete pieces of information. diff --git a/website/versioned_docs/version-v6.0.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md b/website/versioned_docs/version-v6.0.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md index a8842ae084922..9ff8a7840df90 100644 --- a/website/versioned_docs/version-v6.0.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md +++ b/website/versioned_docs/version-v6.0.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md @@ -12,7 +12,6 @@ In this article we'll explore what it means to build a GraphQL client framework Imagine we have a simple application that fetches a list of stories, and some details about each one. Here's how that might look in resource-oriented REST: ```javascript - // Fetch the list of story IDs but not their details: rest.get('/stories').then(stories => // This resolves to a list of items with linked resources: @@ -25,13 +24,11 @@ rest.get('/stories').then(stories => // `[ { id: "...", text: "..." } ]` console.log(stories); }); - ``` Note that this approach requires _n+1_ requests to the server: 1 to fetch the list, and _n_ to fetch each item. With GraphQL we can fetch the same data in a single network request to the server (without creating a custom endpoint that we'd then have to maintain): ```javascript - graphql.get(`query { stories { id, text } }`).then( stories => { // A list of story items: @@ -39,7 +36,6 @@ graphql.get(`query { stories { id, text } }`).then( console.log(stories); } ); - ``` So far we're just using GraphQL as a more efficient version of typical REST approaches. Note two important benefits in the GraphQL version: @@ -56,7 +52,6 @@ Repeatedly refetching information from the server can get quite slow. For exampl In a resource-oriented REST system, we can maintain a **response cache** based on URIs: ```javascript - var _cache = new Map(); rest.get = uri => { if (!_cache.has(uri)) { @@ -64,13 +59,11 @@ rest.get = uri => { } return _cache.get(uri); }; - ``` Response-caching can also be applied to GraphQL. A basic approach would work similarly to the REST version. The text of the query itself can be used as a cache key: ```javascript - var _cache = new Map(); graphql.get = queryText => { if (!_cache.has(queryText)) { @@ -78,7 +71,6 @@ graphql.get = queryText => { } return _cache.get(queryText); }; - ``` Now, requests for previously cached data can be answered immediately without making a network request. This is a practical approach to improving the perceived performance of an application. However, this method of caching can cause problems with data consistency. @@ -90,7 +82,6 @@ With GraphQL it is very common for the results of multiple queries to overlap. H ``` query { stories { id, text, likeCount } } - ``` and then later refetch one of the stories whose `likeCount` has since been incremented: @@ -98,7 +89,6 @@ and then later refetch one of the stories whose `likeCount` has since been incre ``` query { story(id: "123") { id, text, likeCount } } - ``` We'll now see different `likeCount`s depending on how the story is accessed. A view that uses the first query will see an outdated count, while a view using the second query will see the updated count. @@ -119,7 +109,6 @@ query { } } } - ``` And here's a possible response: @@ -134,13 +123,11 @@ query: { } } } - ``` Although the response is hierarchical, we'll cache it by flattening all the records. Here is an example of how Relay would cache this query response: ```javascript - Map { // `story(id: "1")` 1: Map { @@ -152,7 +139,6 @@ Map { name: 'Jan', }, }; - ``` This is only a simple example: in reality the cache must handle one-to-many associations and pagination (among other things). @@ -182,7 +168,6 @@ The first query was for a list of stories: ``` query { stories { id, text, likeCount } } - ``` With a normalized response cache, a record would be created for each story in the list. The `stories` field would store links to each of these records. @@ -192,7 +177,6 @@ The second query refetched the information for one of those stories: ``` query { story(id: "123") { id, text, likeCount } } - ``` When this response is normalized, Relay can detect that this result overlaps with existing data based on its `id`. Rather than create a new record, Relay will update the existing `123` record. The new `likeCount` is therefore available to _both_ queries, as well as any other query that might reference this story. @@ -215,7 +199,6 @@ query { } } } - ``` After initially fetching this story our cache might be as follows. Note that the story and comment both link to the same record as `author`: @@ -242,7 +225,6 @@ Map { author: Link(2), }, } - ``` The author of this story also commented on it — quite common. Now imagine that some other view fetches new information about the author, and her profile photo has changed to a new URI. Here's the _only_ part of our cached data that changes: @@ -256,7 +238,6 @@ Map { photo: 'http://.../photo2.jpg', }, } - ``` The value of the `photo` field has changed; and therefore the record `2` has also changed. And that's it. Nothing else in the _cache_ is affected. But clearly our _view_ needs to reflect the update: both instances of the author in the UI (as story author and comment author) need to show the new photo. @@ -273,7 +254,6 @@ ImmutableMap { }, 3: ImmutableMap // same as before } - ``` If we replace `2` with a new immutable record, we'll also get a new immutable instance of the cache object. However, records `1` and `3` are untouched. Because the data is normalized, we can't tell that `story`'s contents have changed just by looking at the `story` record alone. @@ -299,7 +279,6 @@ mutation StoryLike($storyID: String) { likeCount } } - ``` Notice that we're querying for data that _may_ have changed as a result of the mutation. An obvious question is: why can't the server just tell us what changed? The answer is: it's complicated. GraphQL abstracts over _any_ data storage layer (or an aggregation of multiple sources), and works with any programming language. Furthermore, the goal of GraphQL is to provide data in a form that is useful to product developers building a view. diff --git a/website/versioned_docs/version-v6.0.0/PrinciplesAndArchitecture-ThinkingInRelay.md b/website/versioned_docs/version-v6.0.0/PrinciplesAndArchitecture-ThinkingInRelay.md index d6f1572d5590b..4fb68372ec4b3 100644 --- a/website/versioned_docs/version-v6.0.0/PrinciplesAndArchitecture-ThinkingInRelay.md +++ b/website/versioned_docs/version-v6.0.0/PrinciplesAndArchitecture-ThinkingInRelay.md @@ -30,13 +30,11 @@ fragment Story_story on Story { photo } } - ``` And this fragment can then be used to define the Story container: ```javascript - const {createFragmentContainer, graphql} = require('react-relay'); // Plain React component. @@ -64,7 +62,6 @@ const StoryContainer = createFragmentContainer(Story, { In React, rendering a view requires two inputs: the _component_ to render, and a _root_ DOM (UI) node to render into. Rendering Relay containers is similar: we need a _container_ to render, and a _root_ in the graph from which to start our query. We also must ensure that the queries for the container are executed and may want to show a loading indicator while data is being fetched. Similar to `ReactDOM.render(component, domNode)`, Relay provides `` for this purpose. The `query` and `variables` define what data to fetch and `render` defines what to render. Here's how we might render ``: ```javascript - ReactDOM.render( { ); } } - ``` The above code is doing something very similar to our [previous example](#rendering-graphql-queries). However, we are now passing a `$userID` variable to the GraphQL query via the `variables` prop. This has a couple of important implications: @@ -228,7 +216,6 @@ Now that we know how to define and fetch queries, let's actually start building First, let's start at the bottom. Suppose that we want to render a component that simply displays a given todo item's text and completed state: ```javascript - // Todo.js import React from 'react'; @@ -258,7 +245,6 @@ export default class Todo extends React.Component { ); } } - ``` From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L107), we know that we can query this data on the `Todo` type. However, we don't want to have to send a separate query for each todo item; that would defeat the purpose of using GraphQL over a traditional REST API. We could manually query for these fields directly in our `QueryRenderer` query, but that would hurt re-usability: what if we want to query the same set of fields as part of a different query? Additionally, we wouldn't know which component needs the data we're querying, which is a problem Relay directly tries to address. @@ -266,18 +252,15 @@ From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/dat Instead, we can define a reusable [Fragment](http://graphql.org/learn/queries/#fragments), which allows us to define a set of fields on a type and reuse them within our queries wherever we need to: ```graphql - fragment TodoItemFragment on Todo { complete text } - ``` Our component can then use this fragment to declare its data dependency on the `Todo` GraphQL type: ```javascript - // Todo.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -340,7 +323,6 @@ Before proceeding, don't forget to run the Relay Compiler with `yarn relay`. Given that [Fragment Containers](./fragment-container) are just React components, we can compose them as such. We can even re-use fragment containers within other fragment containers. As an example, let's see how we would define a `TodoList` component that just renders a list of todo items, and whether all have been completed or not: ```javascript - // TodoList.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -401,7 +383,6 @@ export default createFragmentContainer( `, }, ); - ``` As with the first fragment container we defined, `TodoList` declares it's data dependencies via a fragment. However, this component additionally re-uses the fragment previously defined by the `Todo` component, and passes the appropriate data when rendering the child `Todo` components (a.k.a. fragment containers). @@ -416,7 +397,6 @@ fragment containers do not directly fetch data. Instead, containers declare a sp A `QueryRenderer` rendering these fragment containers could look like the following: ```javascript - // ViewerTodoList.js import React from 'react'; import {graphql, QueryRenderer} from 'react-relay'; @@ -457,7 +437,6 @@ export default class ViewerTodoList extends React.Component { ); } } - ``` Check out our docs for [Fragment Containers](./fragment-container) for more details, and our guides on [Refetch](./refetch-container) and [Pagination](./pagination-container) for more advanced usage of containers. @@ -469,7 +448,6 @@ Now that we know how to query for and render data, let's move on to changing our From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L35), we know that we have some mutations available to us, so let's start by writing a mutation to change the `complete` status of a given todo item (i.e. mark or unmark it as done): ```graphql - mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { changeTodoStatus(input: $input) { todo { @@ -478,7 +456,6 @@ mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { } } } - ``` This mutation allows us to query back some data as a [result of the mutation](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L18), so we're going to query for the updated `complete` status on the todo item. @@ -486,7 +463,6 @@ This mutation allows us to query back some data as a [result of the mutation](ht In order to execute this mutation in Relay, we're going to write a new mutation using Relay's `commitMutation` api: ```javascript - // ChangeTodoStatusMutation.js import {graphql, commitMutation} from 'react-relay'; @@ -520,7 +496,6 @@ function commit( } export default {commit}; - ``` Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mutation to the server and, in our case, upon receiving a response it will automatically update the local data store with the latest data from the server. This also means that upon receiving the response, Relay will ensure that any components (i.e. containers) that depend on the updated data are re-rendered. @@ -528,7 +503,6 @@ Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mut In order to actually use this mutation in our component, we could update our `Todo` component in the following way: ```javascript - // Todo.js // ... @@ -562,7 +536,6 @@ In order to make the experience better, we can configure our mutation to do an o In Relay, there's a couple of options we can pass to `commitMutation` to enable optimistic updates. Let's see what that would look like in our `ChangeTodoStatusMutation`: ```javascript - // ChangeTodoStatusMutation.js // ... @@ -597,7 +570,6 @@ function commit( } export default {commit}; - ``` In the simplest case above, we just need to pass an `optimisticResponse` option, which should refer to an object having the same shape as the mutation response payload. When we pass this option, Relay will know to immediately update our local data with the optimistic response, and then update it with the actual server response or roll it back if an error occurs. diff --git a/website/versioned_docs/version-v7.0.0/Modern-ConvertingMutations.md b/website/versioned_docs/version-v7.0.0/Modern-ConvertingMutations.md index 08ad2e998cb2d..8f4bdc1d8e0d2 100644 --- a/website/versioned_docs/version-v7.0.0/Modern-ConvertingMutations.md +++ b/website/versioned_docs/version-v7.0.0/Modern-ConvertingMutations.md @@ -12,19 +12,16 @@ FatQueries in Relay Classic mutations was a concept that was confusing for a num Example of existing fat query: ```javascript - RelayClassic.QL` fragment on MarkReadNotificationResponsePayload @relay(pattern: true) { notification } `; - ``` Example of converted mutation query: ```javascript - graphql` mutation MarkReadNotificationMutation( $input: MarkReadNotificationData! @@ -37,7 +34,6 @@ graphql` } } `; - ``` ## Migrating Configs @@ -67,7 +63,6 @@ This is no longer needed in Compatibility Mode for neither environments. Simply Take this example of a simple mutation in Relay Classic: ```javascript - class LikeStoryMutation extends RelayClassic.Mutation { getMutation() { return RelayClassic.QL`mutation {likeStory}`; @@ -106,7 +101,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { `, }; } - ``` ### Converting `getMutation()` and `getFatQuery()` @@ -114,7 +108,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { We combine these two into a regular GraphQL mutation, which list out specific fields that needs to be updated. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story(data: $input) { @@ -126,7 +119,6 @@ const mutation = graphql` } } `; - ``` ### Converting `getConfigs()` @@ -138,13 +130,11 @@ As specified above, `FIELDS_CHANGE` configs can be omitted. To convert `getVariables()`, we take the return value from the original function and wrap it in an object that contains a property that matches the variable name for the mutation. In this case, the mutation has a `input` variable that is of type `LikeStoryData`. ```javascript - const variables = { input: { storyID: args.storyID } } - ``` ### Final Result @@ -152,7 +142,6 @@ const variables = { As you can see, our resulting mutation is a lot simpler and more like regular GraphQL than the Relay Classic version we started out with. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story { @@ -178,7 +167,6 @@ function commit(environment: CompatEnvironment, args) { variables, }); } - ``` See [Mutation](./mutations) for additional options on `commitMutation` for more complex mutations. diff --git a/website/versioned_docs/version-v7.0.0/Modern-FragmentContainer.md b/website/versioned_docs/version-v7.0.0/Modern-FragmentContainer.md index 423f446cbb054..6a40bbcfb5d0a 100644 --- a/website/versioned_docs/version-v7.0.0/Modern-FragmentContainer.md +++ b/website/versioned_docs/version-v7.0.0/Modern-FragmentContainer.md @@ -17,12 +17,10 @@ Table of Contents: `createFragmentContainer` has the following signature: ```javascript - createFragmentContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, ): ReactComponentClass; - ``` ### Arguments @@ -43,7 +41,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -58,7 +55,6 @@ To start, let's build the plain React version of a hypothetical `` c Here's a basic implementation of `` that ignores styling in order to highlight the functionality: ```javascript - // TodoItem.js class TodoItem extends React.Component { render() { @@ -78,7 +74,6 @@ class TodoItem extends React.Component { ); } } - ``` ### Data Dependencies With GraphQL @@ -86,7 +81,6 @@ class TodoItem extends React.Component { In Relay, data dependencies are described using [GraphQL](https://github.com/facebook/graphql). For ``, the dependency can be expressed as follows. Note that this exactly matches the shape that the component expected for the `item` prop. ```javascript - graphql` # This fragment only applies to objects of type 'Todo'. fragment TodoItem_item on Todo { @@ -102,7 +96,6 @@ graphql` Given the plain React component and a GraphQL fragment, we can now define a Fragment Container to specify this component's data requirements. Let's look at the code first and then see what's happening: ```javascript - // TodoItem.js import {createFragmentContainer, graphql} from 'react-relay'; @@ -120,7 +113,6 @@ export default createFragmentContainer(TodoItem, { } `, }); - ``` ## Container Composition @@ -134,7 +126,6 @@ Let's explore how this works via a `` component that composes the `< View composition is _exactly_ what you're used to — Relay containers are just standard React components. Here's the `` component: ```javascript - class TodoList extends React.Component { render() { // Expects a `list` with a string `title`, as well as the information @@ -151,7 +142,6 @@ class TodoList extends React.Component { ); } } - ``` ### Composing Fragments @@ -159,7 +149,6 @@ class TodoList extends React.Component { Fragment composition works similarly — a parent container's fragment composes the fragment for each of its children. In this case, `` needs to fetch information about the `Todo`s that are required by ``. ```javascript - class TodoList extends React.Component // as above export default createFragmentContainer(TodoList, { @@ -176,7 +165,6 @@ export default createFragmentContainer(TodoList, { } `, }); - ``` Note that when composing fragments, the type of the composed fragment must match the field on the parent in which it is embedded. For example, it wouldn't make sense to embed a fragment of type `Story` into a parent's field of type `User`. Relay and GraphQL will provide helpful error messages if you get this wrong (and if they aren't helpful, let us know!). @@ -190,7 +178,6 @@ When defining a fragment, you can use the [`@argumentDefinitions`](./graphql-in- For example, let's redefine our `TodoList_list` fragment to take some arguments using `@argumentDefinitions`: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -200,7 +187,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` Any arguments defined inside `@argumentDefinitions` will be local variables available inside the fragment's scope. However, a fragment can also reference global variables that were defined in the root query. @@ -212,11 +198,9 @@ In order to pass arguments to a fragment that has `@argumentDefinitions`, you ne Following our `TodoList_list` example, we would pass arguments to the fragment like so: ```graphql - query TodoListQuery($count: Int, $userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` ## Rendering Containers diff --git a/website/versioned_docs/version-v7.0.0/Modern-GraphQLInRelay.md b/website/versioned_docs/version-v7.0.0/Modern-GraphQLInRelay.md index ef06043a7d364..9fc598b6949fe 100644 --- a/website/versioned_docs/version-v7.0.0/Modern-GraphQLInRelay.md +++ b/website/versioned_docs/version-v7.0.0/Modern-GraphQLInRelay.md @@ -14,7 +14,6 @@ Table of Contents: The `graphql` template tag provided by Relay serves as the mechanism to write queries, fragments, mutations or subscriptions in the [GraphQL](http://graphql.org/learn/) language. For example: ```javascript - import {graphql} from 'react-relay'; graphql` @@ -24,7 +23,6 @@ graphql` } } `; - ``` The result of using the `graphql` template tag is a `GraphQLTaggedNode`; a runtime representation of the GraphQL document which can be used to define [Query Renderers](./query-renderer), [Fragment Containers](./fragment-container), [Refetch Containers](./refetch-container), [Pagination Containers](./pagination-container), etc. @@ -42,11 +40,9 @@ Relay uses directives to add additional information to GraphQL documents, which `@arguments` is a directive used to pass arguments to a fragment that was defined using [`@argumentDefinitions`](#argumentdefinitions). For example: ```graphql - query TodoListQuery($userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -56,7 +52,6 @@ See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fr `@argumentDefinitions` is a directive used to specify arguments taken by a fragment. For example: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -66,7 +61,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -80,7 +74,6 @@ When using the [Pagination Container](./pagination-container), Relay expects con When defining a fragment for use with a Fragment container, you can use the `@relay(plural: true)` directive to indicate that container expects the prop for that fragment to be a list of items instead of a single item. A query or parent that spreads a `@relay(plural: true)` fragment should do so within a plural field (ie a field backed by a [GraphQL list](http://graphql.org/learn/schema/#lists-and-non-null). For example: ```javascript - // Plural fragment definition graphql` fragment TodoItems_items on TodoItem @relay(plural: true) { @@ -95,7 +88,6 @@ fragment TodoApp_app on App { ...TodoItem_items } } - ``` ### `@inline` @@ -107,7 +99,6 @@ Non-React functions can also take advantage of data masking. A fragment can be d In the example below, the function `processItemData` is called from a React component. It requires an item object with a specific set of fields. All React components that use this function should spread the `processItemData_item` fragment to ensure all of the correct item data is loaded for this function. ```javascript - import {graphql, readInlineData} from 'react-relay'; // non-React function called from React @@ -127,11 +118,9 @@ function processItemData(itemRef) { creatorName: item.creator.name }); } - ``` ```javascript - // React Component function MyComponent({item}) { function handleClick() { @@ -151,7 +140,6 @@ export default createFragmentContainer(MyComponent, { } ` }); - ``` ### `@relay(mask: Boolean)` @@ -169,7 +157,6 @@ Keep in mind that it is typically considered an **anti-pattern** to create a sin In the example below, the `user` prop will include the data for `id` and `name` fields wherever `...Component_internUser` is included, instead of Relay's normal behavior to mask those fields: ```javascript - graphql` fragment Component_internUser on InternUser @relay(mask: false) { id @@ -197,7 +184,6 @@ export default createFragmentContainer( } `, ); - ``` ## Relay Compiler @@ -207,7 +193,6 @@ Relay uses the Relay Compiler to convert [`graphql`](#graphql) literals into gen A query like the following: ```javascript - graphql` fragment MyComponent on Type { field @@ -228,12 +213,10 @@ Relay Compiler supports the use of **persisted queries**, in which each version Persisted queries can be enabled by instructing Relay Compiler to emit metadata about each query, mutation, and subscription into a JSON file. The generated file will contain a mapping of query identifiers to query text, which you can then save to your server. To enable persisted queries, use the `--persist-output` flag to the compiler: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` Relay Compiler will then create the id => query text mapping in the path you specify. You can then use this complete @@ -250,7 +233,6 @@ See our relay-compiler section in our [Installation and Setup guide](./installat To use the Relay Compiler, you need either a .graphql or .json GraphQL schema file, describing your GraphQL server's API. Typically these files are local representations of a server source of truth and are not edited directly. For example, we might have a `schema.graphql` like: ```graphql - schema { query: Root } @@ -268,7 +250,6 @@ type WordDefinition { text: String image: String } - ``` ### Source files @@ -284,7 +265,6 @@ For example, given the two files: - `src/Components/DictionaryComponent.js` ```javascript - const DictionaryWordFragment = graphql` fragment DictionaryComponent_word on Word { id @@ -306,7 +286,6 @@ For example, given the two files: - `src/Queries/DictionaryQuery.js` ```javascript - const DictionaryQuery = graphql` query DictionaryQuery { dictionary { @@ -330,9 +309,7 @@ Typically you will not need to import your generated definitions. The [Relay Bab However the Relay Compiler also automatically generates [Flow](https://flow.org) types as [type comments](https://flow.org/en/docs/types/comments/). For example, you can import the generated Flow types like so: ```javascript - import type {DictionaryComponent_word} from './__generated__/DictionaryComponent_word.graphql'; - ``` ### Client schema extensions @@ -342,7 +319,6 @@ The Relay Compiler fully supports client-side schema extensions, which allows yo For example, assuming the server schema `./schema.graphql`: ```graphql - schema { query: Root } @@ -350,28 +326,23 @@ schema { type Root { title: String! } - ``` We can create a `./src/clientSchema.graphql` and define a new type called `Setting`: ```graphql - type Setting { name: String! active: Boolean! } - ``` We can then extend existing server types in the client schema `./src/clientSchema.graphql` with our new `Setting` type, like so: ```graphql - extend type Root { settings: [Setting] } - ``` Any fields specified in the client schema, can be fetched from the [Relay Store](./relay-store), by selecting it in a query or fragment. diff --git a/website/versioned_docs/version-v7.0.0/Modern-LocalStateManagement.md b/website/versioned_docs/version-v7.0.0/Modern-LocalStateManagement.md index 3121ff98c482e..7308c050a4507 100644 --- a/website/versioned_docs/version-v7.0.0/Modern-LocalStateManagement.md +++ b/website/versioned_docs/version-v7.0.0/Modern-LocalStateManagement.md @@ -24,23 +24,19 @@ It can even be used to extend an existing server schema. For example, we can create a new type called `Note`: ```graphql - type Note { ID: ID! title: String body: String } - ``` And then extend the server schema type `User`, with a list of `Note`, called `notes`. ```graphql - extend type User { notes: [Note] } - ``` ## Querying local state @@ -51,7 +47,6 @@ The field can be from the server schema, or it can be schema agnostic, like an i Here, we use a [QueryRenderer](./query-renderer) to get the current `User` via the `viewer` field, along with their id, name and the local list of notes. ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -97,7 +92,6 @@ const Example = (props) => { /> ); } - ``` ## Mutating local state @@ -111,7 +105,6 @@ To build upon the previous example, let's try creating, updating and deleting a ### Create ```javascript - import {commitLocalUpdate} from 'react-relay'; let tempID = 0; @@ -131,7 +124,6 @@ function createUserNote() { user.setLinkedRecords([...userNoteRecords, newNoteRecord], 'notes'); }); } - ``` Note that since this record will be rendered by the `ExampleQuery` in our `QueryRenderer`, the QueryRenderer will automatically retain this data so it isn't garbage collected. @@ -139,20 +131,17 @@ Note that since this record will be rendered by the `ExampleQuery` in our `Query If no component is rendering the local data and you want to manually retain it, you can do so by calling `environment.retain()`: ```javascript - // Tell Relay to retain the record so it isn't garbage collected environment.retain({ dataID, variables: {}, node: { selections: [] } }); - ``` ### Update ```javascript - import {commitLocalUpdate} from 'react-relay'; function updateUserNote(dataID, body, title) { @@ -163,13 +152,11 @@ function updateUserNote(dataID, body, title) { note.setValue(title, 'title') }); } - ``` ### Delete ```javascript - import {commitLocalUpdate} from 'react-relay'; function deleteUserNote(dataID) { @@ -187,7 +174,6 @@ function deleteUserNote(dataID) { user.setLinkedRecords(newUserNoteRecords, 'notes'); }); } - ``` ## Initial local state @@ -196,7 +182,6 @@ All new client-side schema fields default to `undefined` value. Often however, y You can use an updater function via `commitLocalUpdate` to prime local state. ```javascript - import {commitLocalUpdate} from 'react-relay'; commitLocalUpdate(environment, store => { @@ -205,5 +190,4 @@ commitLocalUpdate(environment, store => { // initialize user notes to an empty array. user.setLinkedRecords([], 'notes'); }); - ``` diff --git a/website/versioned_docs/version-v7.0.0/Modern-MigrationSetup.md b/website/versioned_docs/version-v7.0.0/Modern-MigrationSetup.md index 66f1145357e25..a89c0e178e0e5 100644 --- a/website/versioned_docs/version-v7.0.0/Modern-MigrationSetup.md +++ b/website/versioned_docs/version-v7.0.0/Modern-MigrationSetup.md @@ -13,13 +13,11 @@ With some additional configuration, the `"relay"` babel plugin can also translat Relay Classic `Relay.QL` literals. Most importantly, include a reference to your GraphQL Schema as either a json file or graphql schema file. ```javascript - { "plugins": [ ["relay", {"schema": "path/schema.graphql"}] ] } - ``` ## Set up babel-plugin-relay for "[compatibility mode](./relay-compat)" @@ -29,13 +27,11 @@ literals can be translated to be usable by _both_ runtimes if configured to use compatibility mode: ```javascript - { "plugins": [ ["relay", {"compat": true, "schema": "path/schema.graphql"}] ] } - ``` ## Additional Options @@ -47,7 +43,6 @@ thrown at runtime. When compiling code for production deployment, the plugin can be configured to immediately throw upon encountering a validation problem. The plugin can be further customized for different environments with the following options: ```javascript - { "plugins": [ ["relay", { @@ -56,5 +51,4 @@ When compiling code for production deployment, the plugin can be configured to i }] ] } - ``` diff --git a/website/versioned_docs/version-v7.0.0/Modern-Mutations.md b/website/versioned_docs/version-v7.0.0/Modern-Mutations.md index a2e0b285bf2c4..8da3bd999c701 100644 --- a/website/versioned_docs/version-v7.0.0/Modern-Mutations.md +++ b/website/versioned_docs/version-v7.0.0/Modern-Mutations.md @@ -17,7 +17,6 @@ Table of Contents: Use `commitMutation` to create and execute mutations. `commitMutation` has the following signature: ```javascript - commitMutation( environment: Environment, config: { @@ -31,7 +30,6 @@ commitMutation( configs?: Array, }, ); - ``` ### Arguments @@ -58,7 +56,6 @@ commitMutation( Example of a simple mutation: ```javascript - import {commitMutation, graphql} from 'react-relay'; const mutation = graphql` @@ -93,7 +90,6 @@ function markNotificationAsRead(environment, source, storyID) { }, ); } - ``` ## Optimistic Updates @@ -101,7 +97,6 @@ function markNotificationAsRead(environment, source, storyID) { To improve perceived responsiveness, you may wish to perform an "optimistic update", in which the client immediately updates to reflect the anticipated new value even before the response from the server has come back. The simplest way to do this is by providing an `optimisticResponse` and adding it to the `config` that we pass into `commitMutation`: ```javascript - const mutation = graphql` mutation MarkReadNotificationMutation( $input: MarkReadNotificationInput! @@ -130,7 +125,6 @@ commitMutation( variables, }, ); - ``` Another way to enable optimistic updates is via the `optimisticUpdater`, which can be used for more complicated update scenarios. Using `optimisticUpdater` is covered in the section [below](#using-updater-and-optimisticupdater). @@ -152,7 +146,6 @@ Given a deletedIDFieldName, Relay will remove the node(s) from the store. #### Example ```javascript - const mutation = graphql` mutation DestroyShipMutation($input: DestroyShipInput!) { destroyShip(input: $input) { @@ -170,7 +163,6 @@ const configs = [{ type: 'NODE_DELETE', deletedIDFieldName: 'destroyedShipId', }]; - ``` ### RANGE_ADD @@ -190,7 +182,6 @@ Given a parent, information about the connection, and the name of the newly crea #### Example ```javascript - const mutation = graphql` mutation AddShipMutation($input: AddShipInput!) { addShip(input: $input) { @@ -220,7 +211,6 @@ function commit(environment, factionId, name) { }], }); } - ``` ### RANGE_DELETE @@ -242,7 +232,6 @@ from the connection but leave the associated record(s) in the store. #### Example ```javascript - const mutation = graphql` mutation RemoveTagMutation($input: RemoveTagInput!) { removeTag(input: $input) { @@ -268,7 +257,6 @@ function commit(environment, todoId, tagId) { }], }); } - ``` ## Using updater and optimisticUpdater @@ -286,7 +274,6 @@ When you provide these functions, this is roughly what happens during the mutati Here are a quick example of adding a todo item to a Todo list using this [example schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L36): ```javascript - // AddTodoMutation.js import {commitMutation, graphql} from 'react-relay'; import {ConnectionHandler} from 'relay-runtime'; @@ -373,7 +360,6 @@ function commit(environment, text, user) { }, }); } - ``` For details on how to interact with the Relay Store, please refer to our Relay Store [docs](./relay-store). diff --git a/website/versioned_docs/version-v7.0.0/Modern-NetworkLayer.md b/website/versioned_docs/version-v7.0.0/Modern-NetworkLayer.md index 9dddd36d6c235..c9e069b812b01 100644 --- a/website/versioned_docs/version-v7.0.0/Modern-NetworkLayer.md +++ b/website/versioned_docs/version-v7.0.0/Modern-NetworkLayer.md @@ -8,7 +8,6 @@ In order to know how to access your GraphQL server, Relay Modern requires develo Currently the easiest way to create a network layer is via a helper from the `relay-runtime` package: ```javascript - import { Environment, Network, @@ -50,7 +49,6 @@ const environment = new Environment({ }); export default environment; - ``` Note that this is a basic example to help you get started. This example could be extended with additional features such as request/response caching (enabled e.g. when `cacheConfig.force` is false) and uploading form data for mutations (the `uploadables` parameter). @@ -62,7 +60,6 @@ Relay modern makes no assumptions about what to cache and will garbage collect a You have to implement your own cache strategy. A simple solution is to use `QueryResponseCache` (an in-memory cache): ```javascript - import { Environment, Network, @@ -126,7 +123,6 @@ const environment = new Environment({ }); export default environment; - ``` ## Custom open-source implementations diff --git a/website/versioned_docs/version-v7.0.0/Modern-PaginationContainer.md b/website/versioned_docs/version-v7.0.0/Modern-PaginationContainer.md index 6ac3aac8cfb8e..57980d553af9b 100644 --- a/website/versioned_docs/version-v7.0.0/Modern-PaginationContainer.md +++ b/website/versioned_docs/version-v7.0.0/Modern-PaginationContainer.md @@ -24,7 +24,6 @@ However, when [specifying connection fragments](#createpaginationcontainer) for The purpose of the `@connection` directive is to allow Relay to uniquely identify different connections under a parent type. The `@connection` directive takes 2 arguments that help identify the connection: ```graphql - @connection(key: String!, filters: [String]) ``` @@ -37,7 +36,6 @@ The purpose of the `@connection` directive is to allow Relay to uniquely identif Specifying just the `key`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and the value of `$orderBy` (given that no `filters` were provided) @@ -53,13 +51,11 @@ fragment Feed_user on User { } } } - ``` Specifying `key` and `filters`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and /only/ the value of `$searchTerm`, i.e. @@ -77,7 +73,6 @@ fragment Feed_user on User { } } } - ``` ## `createPaginationContainer` @@ -85,7 +80,6 @@ fragment Feed_user on User { `createPaginationContainer` has the following signature: ```javascript - createPaginationContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, @@ -113,7 +107,6 @@ type ConnectionData = { startCursor: ?string, }, }; - ``` ### Arguments @@ -134,7 +127,6 @@ type ConnectionData = { The Component resulting from `createPaginationContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -145,7 +137,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -160,7 +151,6 @@ type Props = { `hasMore` is a function available on the `relay` [prop](#available-props). This function indicates whether there are more pages to fetch from the server or not. ```javascript - hasMore: () => boolean, ``` @@ -170,7 +160,6 @@ hasMore: () => boolean, `isLoading` is a function available on the `relay` [prop](#available-props). This function indicates if a previous call to [`loadMore()`](#loadmore) is still pending. This is convenient for avoiding duplicate load calls. ```javascript - isLoading: () => boolean, ``` @@ -180,7 +169,6 @@ isLoading: () => boolean, `loadMore` is a function available on the `relay` [prop](#available-props). You can call `loadMore()` to fetch more items from the server based on the `connectionConfig` provided to the container. This will return null if there are no more items to fetch, otherwise it will fetch more items and return a Disposable that can be used to cancel the fetch. ```javascript - loadMore( pageSize: number, callback: ?(error: ?Error) => void, @@ -201,7 +189,6 @@ loadMore( `refetchConnection` is a function available on the `relay` [prop](#available-props). You can call `refetchConnection` to restart pagination on a connection from scratch, with optionally a completely new set of variables to pass to the pagination `query`. This is useful for example if you are paginating over a collection based on a userID and the userID changes, you'd want to start paginating over the new collection for the new user. ```javascript - refetchConnection:( totalCount: number, callback: (error: ?Error) => void, @@ -219,7 +206,6 @@ refetchConnection:( ## Pagination Example ```javascript - // Feed.js import {createPaginationContainer, graphql} from 'react-relay'; @@ -314,5 +300,4 @@ module.exports = createPaginationContainer( ` } ); - ``` diff --git a/website/versioned_docs/version-v7.0.0/Modern-PersistedQueries.md b/website/versioned_docs/version-v7.0.0/Modern-PersistedQueries.md index 137cc2e23220c..ec03b69ba09c3 100644 --- a/website/versioned_docs/version-v7.0.0/Modern-PersistedQueries.md +++ b/website/versioned_docs/version-v7.0.0/Modern-PersistedQueries.md @@ -17,12 +17,10 @@ The relay compiler supports persisted queries which is useful because: In your `npm` script in `package.json`, run the relay compiler using the `--persist-output` flag: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` The `--persist-ouput` flag does 3 things: @@ -31,8 +29,7 @@ The `--persist-ouput` flag does 3 things: For example without `--persist-output`, a generated `ConcreteRequest` might look like below: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -49,8 +46,7 @@ The `--persist-ouput` flag does 3 things: With `--persist-output ` this becomes: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -68,12 +64,10 @@ The `--persist-ouput` flag does 3 things: 2. It generates a JSON file at the `` you specify containing a mapping from query ids to the corresponding operation texts. -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./src/queryMaps/queryMap.json" } - ``` The example above writes the complete query map file to `./src/queryMaps/queryMap.json`. You need to ensure all the directories @@ -83,8 +77,7 @@ leading to the `queryMap.json` file exist. You'll need to modify your network layer fetch implementation to pass a documentId parameter in the POST body instead of a query parameter: -```js - +```javascript function fetchQuery(operation, variables,) { return fetch('/graphql', { method: 'POST', @@ -100,7 +93,6 @@ function fetchQuery(operation, variables,) { return response.json(); }); } - ``` ## Executing Persisted Queries on the Server @@ -116,13 +108,11 @@ the query map file in a common location accessible to both the client and the se For applications where the client and server projects are separate, one option is to have an additional npm run script to push the query map at compile time to a location accessible by your server: -```js - +```javascript "scripts": { "push-queries": "node ./pushQueries.js", "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-ouput && npm run push-queries" } - ``` Some possibilities of what you can do in `./pushQueries.js`: @@ -146,8 +136,7 @@ database technologies you use, so we'll just cover the most common and basic exa If you use `express-graphql` and have access to the query map file, you can import the `--persist-output` JSON file directly and perform the matching using the `matchQueryMiddleware` from [relay-compiler-plus](https://github.com/yusinto/relay-compiler-plus). -```js - +```javascript import Express from 'express'; import expressGraphql from 'express-graphql'; import {matchQueryMiddleware} from 'relay-compiler-plus'; @@ -158,7 +147,6 @@ const app = Express(); app.use('/graphql', matchQueryMiddleware(queryMapJson), expressGraphql({schema})); - ``` ## Using `--persist-output` and `--watch` diff --git a/website/versioned_docs/version-v7.0.0/Modern-QueryRenderer.md b/website/versioned_docs/version-v7.0.0/Modern-QueryRenderer.md index cf6c37f3d9a4d..b621ef9986bf1 100644 --- a/website/versioned_docs/version-v7.0.0/Modern-QueryRenderer.md +++ b/website/versioned_docs/version-v7.0.0/Modern-QueryRenderer.md @@ -24,7 +24,6 @@ However, a `QueryRenderer` will not start loading its data until it is mounted, ## Example ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -56,5 +55,4 @@ const Example = (props) => { /> ); } - ``` diff --git a/website/versioned_docs/version-v7.0.0/Modern-RefetchContainer.md b/website/versioned_docs/version-v7.0.0/Modern-RefetchContainer.md index 7ce0d14e45417..51c2c44db8941 100644 --- a/website/versioned_docs/version-v7.0.0/Modern-RefetchContainer.md +++ b/website/versioned_docs/version-v7.0.0/Modern-RefetchContainer.md @@ -16,13 +16,11 @@ Table of Contents: `createRefetchContainer` has the following signature: ```javascript - createRefetchContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, refetchQuery: GraphQLTaggedNode, ): ReactComponentClass; - ``` ### Arguments @@ -37,7 +35,6 @@ createRefetchContainer( The Component resulting from `createRefetchContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -45,7 +42,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -61,7 +57,6 @@ type Props = { `refetch` has the following signature: ```javascript - type RefetchOptions = { force?: boolean, }; @@ -102,7 +97,6 @@ Returns a `Disposable` on which you could call `dispose()` to cancel the refetch In this simple example, let's assume we want to fetch the latest data for a `TodoItem` from the server: ```javascript - // TodoItem.js import {createRefetchContainer, graphql} from 'react-relay'; @@ -148,7 +142,6 @@ export default createRefetchContainer( } ` ); - ``` ### Loading more data @@ -156,7 +149,6 @@ export default createRefetchContainer( In this example we are using a Refetch Container to fetch more stories in a story feed component. ```javascript - import {createRefetchContainer, graphql} from 'react-relay'; class FeedStories extends React.Component { @@ -212,5 +204,4 @@ export default createRefetchContainer( } `, ); - ``` diff --git a/website/versioned_docs/version-v7.0.0/Modern-RelayCompat.md b/website/versioned_docs/version-v7.0.0/Modern-RelayCompat.md index 36632d3a8f1a1..f47dbd845ba3e 100644 --- a/website/versioned_docs/version-v7.0.0/Modern-RelayCompat.md +++ b/website/versioned_docs/version-v7.0.0/Modern-RelayCompat.md @@ -31,7 +31,6 @@ Relay Modern. The components using Relay Compat can be referred to by both other Relay Modern and Relay Classic components. ```javascript - const {createFragmentContainer, graphql} = require('react-relay/compat'); class TodoItem extends React.Component { @@ -47,5 +46,4 @@ module.exports = createFragmentContainer(TodoItem, graphql` isComplete } `); - ``` diff --git a/website/versioned_docs/version-v7.0.0/Modern-RelayEnvironment.md b/website/versioned_docs/version-v7.0.0/Modern-RelayEnvironment.md index 27d90b2fc4fe1..99e728bce740d 100644 --- a/website/versioned_docs/version-v7.0.0/Modern-RelayEnvironment.md +++ b/website/versioned_docs/version-v7.0.0/Modern-RelayEnvironment.md @@ -12,7 +12,6 @@ Most applications will create a single Environment instance and use it throughou To create an environment instance in Relay Modern, use the `RelayModernEnvironment` class: ```javascript - const { Environment, Network, @@ -30,7 +29,6 @@ const environment = new Environment({ network, store, }); - ``` For more details on creating a Network, see the [NetworkLayer guide](./network-layer). @@ -44,7 +42,6 @@ The example above did not configure a `handlerProvider`, which means that a defa If you wish to provide your own `handlerProvider`, you can do so: ```javascript - const { ConnectionHandler, } = require('relay-runtime'); @@ -58,5 +55,4 @@ function handlerProvider(handle) { `handlerProvider: No handler provided for ${handle}` ); } - ``` diff --git a/website/versioned_docs/version-v7.0.0/Modern-RelayStore.md b/website/versioned_docs/version-v7.0.0/Modern-RelayStore.md index 8bc27098b205e..56b91d3036791 100644 --- a/website/versioned_docs/version-v7.0.0/Modern-RelayStore.md +++ b/website/versioned_docs/version-v7.0.0/Modern-RelayStore.md @@ -16,7 +16,6 @@ Table of Contents: The `RecordSourceSelectorProxy` is the type of the `store` that [`updater` functions](./mutations#using-updater-and-optimisticupdater) receive as an argument. The following is the `RecordSourceSelectorProxy` interface: ```javascript - interface RecordSourceSelectorProxy { create(dataID: string, typeName: string): RecordProxy; delete(dataID: string): void; @@ -25,7 +24,6 @@ interface RecordSourceSelectorProxy { getRootField(fieldName: string): ?RecordProxy; getPluralRootField(fieldName: string): ?Array; } - ``` ### `create(dataID: string, typeName: string): RecordProxy` @@ -35,9 +33,7 @@ Creates a new record in the store given a `dataID` and the `typeName` as defined #### Example ```javascript - const record = store.create(dataID, 'Todo'); - ``` ### `delete(dataID: string): void` @@ -47,9 +43,7 @@ Deletes a record from the store given its `dataID`. #### Example ```javascript - store.delete(dataID); - ``` ### `get(dataID: string): ?RecordProxy` @@ -59,9 +53,7 @@ Retrieves a record from the store given its `dataID`. Returns a [`RecordProxy`]( #### Example ```javascript - const record = store.get(dataID); - ``` ### `getRoot(): RecordProxy` @@ -73,20 +65,16 @@ Returns the [`RecordProxy`](#recordproxy) representing the root of the GraphQL d Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - // Represents root query const root = store.getRoot(); - ``` ### `getRootField(fieldName: string): ?RecordProxy` @@ -98,19 +86,15 @@ Retrieves a root field from the store given the `fieldName`, as defined by the G Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - const viewer = store.getRootField('viewer'); - ``` ### `getPluralRootField(fieldName: string): ?Array` @@ -122,19 +106,15 @@ Retrieves a root field that represents a collection from the store given the `fi Given the GraphQL document: ```graphql - nodes(first: 10) { # ... } - ``` Usage: ```javascript - const nodes = store.getPluralRootField('nodes'); - ``` ## RecordProxy @@ -142,7 +122,6 @@ const nodes = store.getPluralRootField('nodes'); The `RecordProxy` serves as an interface to mutate records: ```javascript - interface RecordProxy { copyFieldsFrom(sourceRecord: RecordProxy): void; getDataID(): string; @@ -167,7 +146,6 @@ interface RecordProxy { ): RecordProxy; setValue(value: mixed, name: string, arguments?: ?Object): RecordProxy; } - ``` ### `getDataID(): string` @@ -177,9 +155,7 @@ Returns the dataID of the current record. #### Example ```javascript - const id = record.getDataID(); - ``` ### `getType(): string` @@ -189,7 +165,6 @@ Gets the type of the current record, as defined by the GraphQL schema. #### Example ```javascript - const type = user.getType(); // User ``` @@ -203,20 +178,16 @@ Gets the value of a field in the current record given the field name. Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - const name = viewer.getValue('name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. @@ -226,20 +197,16 @@ Optionally, if the field takes arguments, you can pass a bag of `variables`. Given the GraphQL document: ```graphql - viewer { id name(arg: $arg) } - ``` Usage: ```javascript - const name = viewer.getValue('name', {arg: 'value'}); - ``` ### `getLinkedRecord(name: string, arguments?: ?Object): ?RecordProxy` @@ -251,23 +218,19 @@ Retrieves a record associated with the current record given the field name, as d Given the GraphQL document: ```graphql - rootField { viewer { id name } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -277,22 +240,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { viewer(arg: $arg) { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {arg: 'value'}); - ``` ### `getLinkedRecords(name: string, arguments?: ?Object): ?Array` @@ -304,22 +263,18 @@ Retrieves the set of records associated with the current record given the field Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const nodes = rootField.getLinkedRecords('nodes'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -329,22 +284,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { nodes(first: $count) { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {count: 10}); - ``` ### `getOrCreateLinkedRecord(name: string, typeName: string, arguments?: ?Object)` @@ -356,19 +307,16 @@ Retrieves the a record associated with the current record given the field name, Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = rootField.getOrCreateLinkedRecord('viewer', 'User'); // Will create if it doesn't exist @@ -383,28 +331,22 @@ Mutates the current record by setting a new value on the specified field. Return Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - viewer.setValue('New Name', 'name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. ```javascript - viewer.setValue('New Name', 'name', {arg: 'value'}); - ``` ### `copyFieldsFrom(sourceRecord: RecordProxy): void` @@ -414,7 +356,6 @@ Mutates the current record by copying the fields over from the passed in record #### Example ```javascript - const record = store.get(id1); const otherRecord = store.get(id2); record.copyFieldsFrom(otherRecord); // Mutates `record` @@ -430,19 +371,16 @@ Mutates the current record by setting a new linked record on the given the field Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = store.create(/* ... */)'' rootField.setLinkedRecord(newViewer, 'viewer'); // @@ -460,19 +398,16 @@ Mutates the current record by setting a new set of linked records on the given t Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newNode = store.create(/* ... */); const newNodes = [...rootField.getLinkedRecords('nodes'), newNode]; @@ -487,7 +422,6 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl `ConnectionHandler` is a utility module exposed by `relay-runtime` that aids in the manipulation of connections. `ConnectionHandler` exposes the following interface: ```javascript - interface ConnectionHandler { getConnection( record: RecordProxy, @@ -512,7 +446,6 @@ interface ConnectionHandler { ): void, deleteNode(connection: RecordProxy, nodeID: string): void } - ``` ### `getConnection(record: RecordProxy, key: string, filters?: ?Object)` @@ -522,7 +455,6 @@ Given a record and a connection key, and optionally a set of filters, `getConnec First, let's take a look at a plain connection: ```graphql - fragment FriendsFragment on User { friends(first: 10) { edges { @@ -532,26 +464,22 @@ fragment FriendsFragment on User { } } } - ``` Accessing a plain connection field like this is the same as other regular field: ```javascript - // The `friends` connection record can be accessed with: const user = store.get(userID); const friends = user && user.getLinkedRecord(user, 'friends'); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` In a [pagination container](./pagination-container), we usually annotate the actual connection field with `@connection` to tell Relay which part needs to be paginated: ```graphql - fragment FriendsFragment on User { friends(first: 10, orderby: "firstname") @connection( key: "FriendsFragment_friends", @@ -563,7 +491,6 @@ fragment FriendsFragment on User { } } } - ``` For connections like the above, `ConnectionHandler` helps us find the record: @@ -581,7 +508,6 @@ const friends = ConnectionHandler.getConnection( ); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` ### Edge creation and insertion @@ -611,7 +537,6 @@ ConnectionHandler.insertEdgeAfter(friends, edge); // No cursor provided, Insert the edge at the front: ConnectionHandler.insertEdgeBefore(friends, edge); - ``` ### `deleteNode(connection: RecordProxy, nodeID: string): void` @@ -625,5 +550,4 @@ Given a connection, deletes any edges whose id matches the given id. const user = store.get(userID); const friends = ConnectionHandler.getConnection(user, 'friends'); ConnectionHandler.deleteNode(friends, idToDelete); - ``` diff --git a/website/versioned_docs/version-v7.0.0/Modern-Subscriptions.md b/website/versioned_docs/version-v7.0.0/Modern-Subscriptions.md index 802f1d02b06de..bd1c5fe2f350c 100644 --- a/website/versioned_docs/version-v7.0.0/Modern-Subscriptions.md +++ b/website/versioned_docs/version-v7.0.0/Modern-Subscriptions.md @@ -6,7 +6,6 @@ original_id: subscriptions Relay exposes the following APIs to create subscriptions. ```javascript - const {requestSubscription} = require('react-relay'); type Variables = {[name: string]: any}; @@ -27,7 +26,6 @@ requestSubscription( configs?: Array, }, ) => Disposable; - ``` The function returns a `Disposable` on which you could call `dispose()` to cancel the refetch. @@ -53,7 +51,6 @@ appropriate when you are only changing the properties of existing records that can be identified by their `id`: ```javascript - const { requestSubscription, graphql, @@ -87,7 +84,6 @@ requestSubscription( onError: error => console.error(error), } ); - ``` # Updating the client on each response @@ -97,7 +93,6 @@ Relay's in-memory cache when each subscription response is received. To do so, pass an `updater` function: ```javascript - const {ConnectionHandler} = require('relay-runtime'); requestSubscription( @@ -123,5 +118,4 @@ requestSubscription( }, }, ); - ``` diff --git a/website/versioned_docs/version-v7.0.0/Modern-TestingRelayComponents.md b/website/versioned_docs/version-v7.0.0/Modern-TestingRelayComponents.md index 4e5cf9e61a922..2916a65f56e06 100644 --- a/website/versioned_docs/version-v7.0.0/Modern-TestingRelayComponents.md +++ b/website/versioned_docs/version-v7.0.0/Modern-TestingRelayComponents.md @@ -65,7 +65,6 @@ MockPayloadGenerator may drastically simplify the process of creating and mainta Example of a simple Mock Resolver: ```javascript - { ID() { // Return mock value for a scalar filed with type ID @@ -76,13 +75,11 @@ Example of a simple Mock Resolver: return "Lorem Ipsum" } } - ``` It is possible to define more resolvers for Object types ```javascript - { // This will be the default values for User object in the query response User() { @@ -95,7 +92,6 @@ It is possible to define more resolvers for Object types }; }, } - ``` ### Mock Resolver Context @@ -103,7 +99,6 @@ It is possible to define more resolvers for Object types The first argument of the MockResolver is the object that contains Mock Resolver Context. It is possible to return dynamic values from mock resolvers based on the context - for instance, name or alias of the field, a path in the selection, arguments, or parent type. ```javascript - { String(context) { if (context.name === 'zip') { @@ -117,7 +112,6 @@ The first argument of the MockResolver is the object that contains Mock Resolver } } } - ``` ### ID Generation @@ -125,14 +119,12 @@ The first argument of the MockResolver is the object that contains Mock Resolver The second argument of the Mock Resolver its a function that will generate a sequence of integers, useful to generate unique ids in the tests ```javascript - { // will generate strings "my-id-1", "my-id-2", etc. ID(_, generateId) { return `my-id-${generateId()}`; }, } - ``` ### @relay_test_operation @@ -142,7 +134,6 @@ Most of GraphQL type information for a specific field in the selection is not av Operation with the @relay_test_operation directive will have additional metadata that will contain GraphQL type info for fields in the operation's selection. And it will improve the quality of the generated data. You also will be able to define Mock resolvers for Scalar (not only ID and String) and Abstract types: ```javascript - { Float() { return 123.456; @@ -160,7 +151,6 @@ Operation with the @relay_test_operation directive will have additional metadata }; } } - ``` ## Examples @@ -170,7 +160,6 @@ Operation with the @relay_test_operation directive will have additional metadata Using `createMockEnvironment` and `MockPayloadGenerator` allows writing concise tests for components that are using Relay Containers and Renderers. Both those modules can be imported from `relay-test-utils` ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { @@ -223,7 +212,6 @@ test('Error State', () => { renderer.root.find(item => (item.props.testID = 'errorMessage')), ).toBeDefined(); }); - ``` ### Fragment Container Tests @@ -231,7 +219,6 @@ test('Error State', () => { Essentially, in the example above will `resolveMostRecentOperation` will generate data for all child fragment containers (pagination, refetch). But, usually the Root Components container may have many child fragment components and you may want to exercise a specific Fragment Container. The solution for that would be to wrap you fragment container with the QueryRenderer that renders a Query that's spreads fragments from you fragment container. ```javascript - test('Fragment Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -262,7 +249,6 @@ test('Fragment Container', () => { expect(renderer).toMatchSnapshot(); }); - ``` ### Pagination Container Test @@ -270,7 +256,6 @@ test('Fragment Container', () => { Essentially, tests for Pagination container are not different from Fragment Container tests. But we can do more here, we can actually see how the pagination works - we can assert the behavior of our components when performing pagination (load more, refetch). ```javascript - // Pagination Example test('Pagination Container', () => { const environment = createMockEnvironment(); @@ -344,7 +329,6 @@ test('Pagination Container', () => { We can use similar approach here with wrapping container with Query Renderer. And for the sake of completeness, we will add example here: ```javascript - test('Refetch Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -386,7 +370,6 @@ test('Refetch Container', () => { ); // expect(renderer).toMatchSnapshot(); }); - ``` ### Mutations @@ -394,7 +377,6 @@ test('Refetch Container', () => { Mutations itself are operations so we can test them independently (unit-test) for specific mutation, or in combination with the view from which this mutation is called. ```javascript - // Say, you have a mutation function function sendMutation(environment, onCompleted, onError, variables) commitMutation(environment, { @@ -417,7 +399,6 @@ test('it should send mutation', () => { ); expect(onCompleted).toBeCalled(); }); - ``` ### Subscription @@ -425,7 +406,6 @@ test('it should send mutation', () => { We can test subscription in a similar way we test mutations ```javascript - // Example subscribe function function subscribe(environment, onNext, onError, variables) requestSubscription(environment, { @@ -448,7 +428,6 @@ test('it should subscribe', () => { ); expect(onNext).toBeCalled(); }); - ``` ### Example with `queueOperationResolver` @@ -456,7 +435,6 @@ test('it should subscribe', () => { With `queueOpeararionResolver` it possible to define responses for operations that will be executed on the environment ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { diff --git a/website/versioned_docs/version-v7.0.0/Modern-TypeEmission.md b/website/versioned_docs/version-v7.0.0/Modern-TypeEmission.md index 63614b869a322..4ff63e4a7d81b 100644 --- a/website/versioned_docs/version-v7.0.0/Modern-TypeEmission.md +++ b/website/versioned_docs/version-v7.0.0/Modern-TypeEmission.md @@ -16,7 +16,6 @@ In this example the emitted type-information would require the variables object #### Flow ```javascript - /** * export type ExampleQueryVariables = {| * +artistID: string @@ -44,7 +43,6 @@ const variables: ExampleQueryVariables = { #### TypeScript ```javascript - /** * export type ExampleQueryVariables = { * readonly artistID: string @@ -79,7 +77,6 @@ In this example the emitted type-information describes the response data availab #### Flow ```javascript - /** * export type ExampleQueryResponse = {| * +artist: ?{| @@ -110,7 +107,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * export type ExampleQueryResponse = { * readonly artist?: { @@ -146,7 +142,6 @@ Similarly, in this example the emitted type-information describes the prop data #### Flow ```javascript - /** * export type ExampleFragment_artist = {| * +name: string @@ -172,7 +167,6 @@ export const ExampleFragment = createFragmentContainer( #### TypeScript ```javascript - /** * export type ExampleFragment_artist = { * readonly name: string @@ -206,7 +200,6 @@ Consider a component that composes the above fragment container example. In this #### Flow ```javascript - /** * import type { FragmentReference } from "relay-runtime"; * declare export opaque type ExampleFragment_artist$ref: FragmentReference; @@ -250,7 +243,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * declare const _ExampleFragment_artist$ref: unique symbol; * export type ExampleFragment_artist$ref = typeof _ExampleFragment_artist$ref; @@ -315,7 +307,6 @@ $ relay-compiler --artifactDirectory ./src/__generated__ […] ["relay", { "artifactDirectory": "./src/__generated__" }] ] } - ``` It is recommended to alias this directory in your module resolution configuration such that you don’t need to specify relative paths in your source files. This is what is also done in the above examples, where artifacts are imported from a `__generated__` alias, rather than relative paths like `../../../../__generated__`. diff --git a/website/versioned_docs/version-v7.0.0/Modern-UpgradingSetVariables.md b/website/versioned_docs/version-v7.0.0/Modern-UpgradingSetVariables.md index d5b086fafce20..ff73feec04f8b 100644 --- a/website/versioned_docs/version-v7.0.0/Modern-UpgradingSetVariables.md +++ b/website/versioned_docs/version-v7.0.0/Modern-UpgradingSetVariables.md @@ -36,7 +36,6 @@ fragment on User { # ... } } - ``` This should be upgraded to use a [`PaginationContainer`](./pagination-container). @@ -61,7 +60,6 @@ fragment on User { # ... } } - ``` This can be upgraded by using a [`RefetchContainer`](./refetch-container) which allows you to specify the exact query to use to fetch the new data. @@ -86,7 +84,6 @@ fragment on FeedbackTarget { # ... } } - ``` This can be upgraded by conditionally rendering a [`QueryRenderer`](./query-renderer) which will load the data once it is rendered. The code overhead of doing this is dramatically reduced with the new API. diff --git a/website/versioned_docs/version-v7.0.0/Modern-fetchQuery.md b/website/versioned_docs/version-v7.0.0/Modern-fetchQuery.md index 2e9461ad527bd..c1a06ab7d2493 100644 --- a/website/versioned_docs/version-v7.0.0/Modern-fetchQuery.md +++ b/website/versioned_docs/version-v7.0.0/Modern-fetchQuery.md @@ -6,7 +6,6 @@ original_id: fetch-query You can use the `fetchQuery` function to imperatively make GraphQL Requests. This is useful for cases where you want to make requests outside of React but still utilize the Relay store and network layer. ```javascript - import {fetchQuery, graphql} from 'relay-runtime'; const query = graphql` @@ -25,7 +24,6 @@ fetchQuery(environment, query, variables) .then(data => { // access the graphql response }); - ``` ## Arguments diff --git a/website/versioned_docs/version-v7.0.0/PrinciplesAndArchitecture-Compiler.md b/website/versioned_docs/version-v7.0.0/PrinciplesAndArchitecture-Compiler.md index c195491682b1f..fcd0490cb724f 100644 --- a/website/versioned_docs/version-v7.0.0/PrinciplesAndArchitecture-Compiler.md +++ b/website/versioned_docs/version-v7.0.0/PrinciplesAndArchitecture-Compiler.md @@ -74,7 +74,6 @@ foo { # type FooType foo { id } - ``` - `SkipRedundantNodeTransform`: A more advanced version of flattening, this eliminates more complex cases of field duplication such as when a field is fetched both unconditionally and conditionally, or is fetched by two different sub-fragments. For example: @@ -97,7 +96,6 @@ foo { id } } - ``` - `GenerateRequisiteFieldTransform`: This optional, Relay-specific transform inserts `id` fields for globally identifiable objects and `__typename` fields wherever the type cannot be statically determined (e.g. for unions). diff --git a/website/versioned_docs/version-v7.0.0/PrinciplesAndArchitecture-Runtime.md b/website/versioned_docs/version-v7.0.0/PrinciplesAndArchitecture-Runtime.md index 9491d290c146f..e9221631a701d 100644 --- a/website/versioned_docs/version-v7.0.0/PrinciplesAndArchitecture-Runtime.md +++ b/website/versioned_docs/version-v7.0.0/PrinciplesAndArchitecture-Runtime.md @@ -77,7 +77,6 @@ RecordSource { city: 'Seattle', } } - ``` [1] Note that GraphQL itself does not impose this constraint, and Relay Runtime may also be used for schemas that do not conform to it. For example, both systems can be used to query a single denormalized table. However, many of the features that Relay Runtime provides, such as caching and normalization, work best when the data is represented as a normalized graph with stable identities for discrete pieces of information. diff --git a/website/versioned_docs/version-v7.0.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md b/website/versioned_docs/version-v7.0.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md index a8842ae084922..9ff8a7840df90 100644 --- a/website/versioned_docs/version-v7.0.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md +++ b/website/versioned_docs/version-v7.0.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md @@ -12,7 +12,6 @@ In this article we'll explore what it means to build a GraphQL client framework Imagine we have a simple application that fetches a list of stories, and some details about each one. Here's how that might look in resource-oriented REST: ```javascript - // Fetch the list of story IDs but not their details: rest.get('/stories').then(stories => // This resolves to a list of items with linked resources: @@ -25,13 +24,11 @@ rest.get('/stories').then(stories => // `[ { id: "...", text: "..." } ]` console.log(stories); }); - ``` Note that this approach requires _n+1_ requests to the server: 1 to fetch the list, and _n_ to fetch each item. With GraphQL we can fetch the same data in a single network request to the server (without creating a custom endpoint that we'd then have to maintain): ```javascript - graphql.get(`query { stories { id, text } }`).then( stories => { // A list of story items: @@ -39,7 +36,6 @@ graphql.get(`query { stories { id, text } }`).then( console.log(stories); } ); - ``` So far we're just using GraphQL as a more efficient version of typical REST approaches. Note two important benefits in the GraphQL version: @@ -56,7 +52,6 @@ Repeatedly refetching information from the server can get quite slow. For exampl In a resource-oriented REST system, we can maintain a **response cache** based on URIs: ```javascript - var _cache = new Map(); rest.get = uri => { if (!_cache.has(uri)) { @@ -64,13 +59,11 @@ rest.get = uri => { } return _cache.get(uri); }; - ``` Response-caching can also be applied to GraphQL. A basic approach would work similarly to the REST version. The text of the query itself can be used as a cache key: ```javascript - var _cache = new Map(); graphql.get = queryText => { if (!_cache.has(queryText)) { @@ -78,7 +71,6 @@ graphql.get = queryText => { } return _cache.get(queryText); }; - ``` Now, requests for previously cached data can be answered immediately without making a network request. This is a practical approach to improving the perceived performance of an application. However, this method of caching can cause problems with data consistency. @@ -90,7 +82,6 @@ With GraphQL it is very common for the results of multiple queries to overlap. H ``` query { stories { id, text, likeCount } } - ``` and then later refetch one of the stories whose `likeCount` has since been incremented: @@ -98,7 +89,6 @@ and then later refetch one of the stories whose `likeCount` has since been incre ``` query { story(id: "123") { id, text, likeCount } } - ``` We'll now see different `likeCount`s depending on how the story is accessed. A view that uses the first query will see an outdated count, while a view using the second query will see the updated count. @@ -119,7 +109,6 @@ query { } } } - ``` And here's a possible response: @@ -134,13 +123,11 @@ query: { } } } - ``` Although the response is hierarchical, we'll cache it by flattening all the records. Here is an example of how Relay would cache this query response: ```javascript - Map { // `story(id: "1")` 1: Map { @@ -152,7 +139,6 @@ Map { name: 'Jan', }, }; - ``` This is only a simple example: in reality the cache must handle one-to-many associations and pagination (among other things). @@ -182,7 +168,6 @@ The first query was for a list of stories: ``` query { stories { id, text, likeCount } } - ``` With a normalized response cache, a record would be created for each story in the list. The `stories` field would store links to each of these records. @@ -192,7 +177,6 @@ The second query refetched the information for one of those stories: ``` query { story(id: "123") { id, text, likeCount } } - ``` When this response is normalized, Relay can detect that this result overlaps with existing data based on its `id`. Rather than create a new record, Relay will update the existing `123` record. The new `likeCount` is therefore available to _both_ queries, as well as any other query that might reference this story. @@ -215,7 +199,6 @@ query { } } } - ``` After initially fetching this story our cache might be as follows. Note that the story and comment both link to the same record as `author`: @@ -242,7 +225,6 @@ Map { author: Link(2), }, } - ``` The author of this story also commented on it — quite common. Now imagine that some other view fetches new information about the author, and her profile photo has changed to a new URI. Here's the _only_ part of our cached data that changes: @@ -256,7 +238,6 @@ Map { photo: 'http://.../photo2.jpg', }, } - ``` The value of the `photo` field has changed; and therefore the record `2` has also changed. And that's it. Nothing else in the _cache_ is affected. But clearly our _view_ needs to reflect the update: both instances of the author in the UI (as story author and comment author) need to show the new photo. @@ -273,7 +254,6 @@ ImmutableMap { }, 3: ImmutableMap // same as before } - ``` If we replace `2` with a new immutable record, we'll also get a new immutable instance of the cache object. However, records `1` and `3` are untouched. Because the data is normalized, we can't tell that `story`'s contents have changed just by looking at the `story` record alone. @@ -299,7 +279,6 @@ mutation StoryLike($storyID: String) { likeCount } } - ``` Notice that we're querying for data that _may_ have changed as a result of the mutation. An obvious question is: why can't the server just tell us what changed? The answer is: it's complicated. GraphQL abstracts over _any_ data storage layer (or an aggregation of multiple sources), and works with any programming language. Furthermore, the goal of GraphQL is to provide data in a form that is useful to product developers building a view. diff --git a/website/versioned_docs/version-v7.0.0/PrinciplesAndArchitecture-ThinkingInRelay.md b/website/versioned_docs/version-v7.0.0/PrinciplesAndArchitecture-ThinkingInRelay.md index d6f1572d5590b..4fb68372ec4b3 100644 --- a/website/versioned_docs/version-v7.0.0/PrinciplesAndArchitecture-ThinkingInRelay.md +++ b/website/versioned_docs/version-v7.0.0/PrinciplesAndArchitecture-ThinkingInRelay.md @@ -30,13 +30,11 @@ fragment Story_story on Story { photo } } - ``` And this fragment can then be used to define the Story container: ```javascript - const {createFragmentContainer, graphql} = require('react-relay'); // Plain React component. @@ -64,7 +62,6 @@ const StoryContainer = createFragmentContainer(Story, { In React, rendering a view requires two inputs: the _component_ to render, and a _root_ DOM (UI) node to render into. Rendering Relay containers is similar: we need a _container_ to render, and a _root_ in the graph from which to start our query. We also must ensure that the queries for the container are executed and may want to show a loading indicator while data is being fetched. Similar to `ReactDOM.render(component, domNode)`, Relay provides `` for this purpose. The `query` and `variables` define what data to fetch and `render` defines what to render. Here's how we might render ``: ```javascript - ReactDOM.render( { ); } } - ``` The above code is doing something very similar to our [previous example](#rendering-graphql-queries). However, we are now passing a `$userID` variable to the GraphQL query via the `variables` prop. This has a couple of important implications: @@ -228,7 +216,6 @@ Now that we know how to define and fetch queries, let's actually start building First, let's start at the bottom. Suppose that we want to render a component that simply displays a given todo item's text and completed state: ```javascript - // Todo.js import React from 'react'; @@ -258,7 +245,6 @@ export default class Todo extends React.Component { ); } } - ``` From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L112), we know that we can query this data on the `Todo` type. However, we don't want to have to send a separate query for each todo item; that would defeat the purpose of using GraphQL over a traditional REST API. We could manually query for these fields directly in our `QueryRenderer` query, but that would hurt re-usability: what if we want to query the same set of fields as part of a different query? Additionally, we wouldn't know which component needs the data we're querying, which is a problem Relay directly tries to address. @@ -266,18 +252,15 @@ From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/dat Instead, we can define a reusable [Fragment](http://graphql.org/learn/queries/#fragments), which allows us to define a set of fields on a type and reuse them within our queries wherever we need to: ```graphql - fragment TodoItemFragment on Todo { complete text } - ``` Our component can then use this fragment to declare its data dependency on the `Todo` GraphQL type: ```javascript - // Todo.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -340,7 +323,6 @@ Before proceeding, don't forget to run the Relay Compiler with `yarn relay`. Given that [Fragment Containers](./fragment-container) are just React components, we can compose them as such. We can even re-use fragment containers within other fragment containers. As an example, let's see how we would define a `TodoList` component that just renders a list of todo items, and whether all have been completed or not: ```javascript - // TodoList.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -401,7 +383,6 @@ export default createFragmentContainer( `, }, ); - ``` As with the first fragment container we defined, `TodoList` declares it's data dependencies via a fragment. However, this component additionally re-uses the fragment previously defined by the `Todo` component, and passes the appropriate data when rendering the child `Todo` components (a.k.a. fragment containers). @@ -416,7 +397,6 @@ fragment containers do not directly fetch data. Instead, containers declare a sp A `QueryRenderer` rendering these fragment containers could look like the following: ```javascript - // ViewerTodoList.js import React from 'react'; import {graphql, QueryRenderer} from 'react-relay'; @@ -457,7 +437,6 @@ export default class ViewerTodoList extends React.Component { ); } } - ``` Check out our docs for [Fragment Containers](./fragment-container) for more details, and our guides on [Refetch](./refetch-container) and [Pagination](./pagination-container) for more advanced usage of containers. @@ -469,7 +448,6 @@ Now that we know how to query for and render data, let's move on to changing our From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L35), we know that we have some mutations available to us, so let's start by writing a mutation to change the `complete` status of a given todo item (i.e. mark or unmark it as done): ```graphql - mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { changeTodoStatus(input: $input) { todo { @@ -478,7 +456,6 @@ mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { } } } - ``` This mutation allows us to query back some data as a [result of the mutation](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L18), so we're going to query for the updated `complete` status on the todo item. @@ -486,7 +463,6 @@ This mutation allows us to query back some data as a [result of the mutation](ht In order to execute this mutation in Relay, we're going to write a new mutation using Relay's `commitMutation` api: ```javascript - // ChangeTodoStatusMutation.js import {graphql, commitMutation} from 'react-relay'; @@ -520,7 +496,6 @@ function commit( } export default {commit}; - ``` Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mutation to the server and, in our case, upon receiving a response it will automatically update the local data store with the latest data from the server. This also means that upon receiving the response, Relay will ensure that any components (i.e. containers) that depend on the updated data are re-rendered. @@ -528,7 +503,6 @@ Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mut In order to actually use this mutation in our component, we could update our `Todo` component in the following way: ```javascript - // Todo.js // ... @@ -562,7 +536,6 @@ In order to make the experience better, we can configure our mutation to do an o In Relay, there's a couple of options we can pass to `commitMutation` to enable optimistic updates. Let's see what that would look like in our `ChangeTodoStatusMutation`: ```javascript - // ChangeTodoStatusMutation.js // ... @@ -597,7 +570,6 @@ function commit( } export default {commit}; - ``` In the simplest case above, we just need to pass an `optimisticResponse` option, which should refer to an object having the same shape as the mutation response payload. When we pass this option, Relay will know to immediately update our local data with the optimistic response, and then update it with the actual server response or roll it back if an error occurs. diff --git a/website/versioned_docs/version-v7.1.0/Modern-ConvertingMutations.md b/website/versioned_docs/version-v7.1.0/Modern-ConvertingMutations.md index 08ad2e998cb2d..8f4bdc1d8e0d2 100644 --- a/website/versioned_docs/version-v7.1.0/Modern-ConvertingMutations.md +++ b/website/versioned_docs/version-v7.1.0/Modern-ConvertingMutations.md @@ -12,19 +12,16 @@ FatQueries in Relay Classic mutations was a concept that was confusing for a num Example of existing fat query: ```javascript - RelayClassic.QL` fragment on MarkReadNotificationResponsePayload @relay(pattern: true) { notification } `; - ``` Example of converted mutation query: ```javascript - graphql` mutation MarkReadNotificationMutation( $input: MarkReadNotificationData! @@ -37,7 +34,6 @@ graphql` } } `; - ``` ## Migrating Configs @@ -67,7 +63,6 @@ This is no longer needed in Compatibility Mode for neither environments. Simply Take this example of a simple mutation in Relay Classic: ```javascript - class LikeStoryMutation extends RelayClassic.Mutation { getMutation() { return RelayClassic.QL`mutation {likeStory}`; @@ -106,7 +101,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { `, }; } - ``` ### Converting `getMutation()` and `getFatQuery()` @@ -114,7 +108,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { We combine these two into a regular GraphQL mutation, which list out specific fields that needs to be updated. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story(data: $input) { @@ -126,7 +119,6 @@ const mutation = graphql` } } `; - ``` ### Converting `getConfigs()` @@ -138,13 +130,11 @@ As specified above, `FIELDS_CHANGE` configs can be omitted. To convert `getVariables()`, we take the return value from the original function and wrap it in an object that contains a property that matches the variable name for the mutation. In this case, the mutation has a `input` variable that is of type `LikeStoryData`. ```javascript - const variables = { input: { storyID: args.storyID } } - ``` ### Final Result @@ -152,7 +142,6 @@ const variables = { As you can see, our resulting mutation is a lot simpler and more like regular GraphQL than the Relay Classic version we started out with. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story { @@ -178,7 +167,6 @@ function commit(environment: CompatEnvironment, args) { variables, }); } - ``` See [Mutation](./mutations) for additional options on `commitMutation` for more complex mutations. diff --git a/website/versioned_docs/version-v7.1.0/Modern-FragmentContainer.md b/website/versioned_docs/version-v7.1.0/Modern-FragmentContainer.md index 423f446cbb054..6a40bbcfb5d0a 100644 --- a/website/versioned_docs/version-v7.1.0/Modern-FragmentContainer.md +++ b/website/versioned_docs/version-v7.1.0/Modern-FragmentContainer.md @@ -17,12 +17,10 @@ Table of Contents: `createFragmentContainer` has the following signature: ```javascript - createFragmentContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, ): ReactComponentClass; - ``` ### Arguments @@ -43,7 +41,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -58,7 +55,6 @@ To start, let's build the plain React version of a hypothetical `` c Here's a basic implementation of `` that ignores styling in order to highlight the functionality: ```javascript - // TodoItem.js class TodoItem extends React.Component { render() { @@ -78,7 +74,6 @@ class TodoItem extends React.Component { ); } } - ``` ### Data Dependencies With GraphQL @@ -86,7 +81,6 @@ class TodoItem extends React.Component { In Relay, data dependencies are described using [GraphQL](https://github.com/facebook/graphql). For ``, the dependency can be expressed as follows. Note that this exactly matches the shape that the component expected for the `item` prop. ```javascript - graphql` # This fragment only applies to objects of type 'Todo'. fragment TodoItem_item on Todo { @@ -102,7 +96,6 @@ graphql` Given the plain React component and a GraphQL fragment, we can now define a Fragment Container to specify this component's data requirements. Let's look at the code first and then see what's happening: ```javascript - // TodoItem.js import {createFragmentContainer, graphql} from 'react-relay'; @@ -120,7 +113,6 @@ export default createFragmentContainer(TodoItem, { } `, }); - ``` ## Container Composition @@ -134,7 +126,6 @@ Let's explore how this works via a `` component that composes the `< View composition is _exactly_ what you're used to — Relay containers are just standard React components. Here's the `` component: ```javascript - class TodoList extends React.Component { render() { // Expects a `list` with a string `title`, as well as the information @@ -151,7 +142,6 @@ class TodoList extends React.Component { ); } } - ``` ### Composing Fragments @@ -159,7 +149,6 @@ class TodoList extends React.Component { Fragment composition works similarly — a parent container's fragment composes the fragment for each of its children. In this case, `` needs to fetch information about the `Todo`s that are required by ``. ```javascript - class TodoList extends React.Component // as above export default createFragmentContainer(TodoList, { @@ -176,7 +165,6 @@ export default createFragmentContainer(TodoList, { } `, }); - ``` Note that when composing fragments, the type of the composed fragment must match the field on the parent in which it is embedded. For example, it wouldn't make sense to embed a fragment of type `Story` into a parent's field of type `User`. Relay and GraphQL will provide helpful error messages if you get this wrong (and if they aren't helpful, let us know!). @@ -190,7 +178,6 @@ When defining a fragment, you can use the [`@argumentDefinitions`](./graphql-in- For example, let's redefine our `TodoList_list` fragment to take some arguments using `@argumentDefinitions`: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -200,7 +187,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` Any arguments defined inside `@argumentDefinitions` will be local variables available inside the fragment's scope. However, a fragment can also reference global variables that were defined in the root query. @@ -212,11 +198,9 @@ In order to pass arguments to a fragment that has `@argumentDefinitions`, you ne Following our `TodoList_list` example, we would pass arguments to the fragment like so: ```graphql - query TodoListQuery($count: Int, $userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` ## Rendering Containers diff --git a/website/versioned_docs/version-v7.1.0/Modern-GraphQLInRelay.md b/website/versioned_docs/version-v7.1.0/Modern-GraphQLInRelay.md index ef06043a7d364..9fc598b6949fe 100644 --- a/website/versioned_docs/version-v7.1.0/Modern-GraphQLInRelay.md +++ b/website/versioned_docs/version-v7.1.0/Modern-GraphQLInRelay.md @@ -14,7 +14,6 @@ Table of Contents: The `graphql` template tag provided by Relay serves as the mechanism to write queries, fragments, mutations or subscriptions in the [GraphQL](http://graphql.org/learn/) language. For example: ```javascript - import {graphql} from 'react-relay'; graphql` @@ -24,7 +23,6 @@ graphql` } } `; - ``` The result of using the `graphql` template tag is a `GraphQLTaggedNode`; a runtime representation of the GraphQL document which can be used to define [Query Renderers](./query-renderer), [Fragment Containers](./fragment-container), [Refetch Containers](./refetch-container), [Pagination Containers](./pagination-container), etc. @@ -42,11 +40,9 @@ Relay uses directives to add additional information to GraphQL documents, which `@arguments` is a directive used to pass arguments to a fragment that was defined using [`@argumentDefinitions`](#argumentdefinitions). For example: ```graphql - query TodoListQuery($userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -56,7 +52,6 @@ See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fr `@argumentDefinitions` is a directive used to specify arguments taken by a fragment. For example: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -66,7 +61,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -80,7 +74,6 @@ When using the [Pagination Container](./pagination-container), Relay expects con When defining a fragment for use with a Fragment container, you can use the `@relay(plural: true)` directive to indicate that container expects the prop for that fragment to be a list of items instead of a single item. A query or parent that spreads a `@relay(plural: true)` fragment should do so within a plural field (ie a field backed by a [GraphQL list](http://graphql.org/learn/schema/#lists-and-non-null). For example: ```javascript - // Plural fragment definition graphql` fragment TodoItems_items on TodoItem @relay(plural: true) { @@ -95,7 +88,6 @@ fragment TodoApp_app on App { ...TodoItem_items } } - ``` ### `@inline` @@ -107,7 +99,6 @@ Non-React functions can also take advantage of data masking. A fragment can be d In the example below, the function `processItemData` is called from a React component. It requires an item object with a specific set of fields. All React components that use this function should spread the `processItemData_item` fragment to ensure all of the correct item data is loaded for this function. ```javascript - import {graphql, readInlineData} from 'react-relay'; // non-React function called from React @@ -127,11 +118,9 @@ function processItemData(itemRef) { creatorName: item.creator.name }); } - ``` ```javascript - // React Component function MyComponent({item}) { function handleClick() { @@ -151,7 +140,6 @@ export default createFragmentContainer(MyComponent, { } ` }); - ``` ### `@relay(mask: Boolean)` @@ -169,7 +157,6 @@ Keep in mind that it is typically considered an **anti-pattern** to create a sin In the example below, the `user` prop will include the data for `id` and `name` fields wherever `...Component_internUser` is included, instead of Relay's normal behavior to mask those fields: ```javascript - graphql` fragment Component_internUser on InternUser @relay(mask: false) { id @@ -197,7 +184,6 @@ export default createFragmentContainer( } `, ); - ``` ## Relay Compiler @@ -207,7 +193,6 @@ Relay uses the Relay Compiler to convert [`graphql`](#graphql) literals into gen A query like the following: ```javascript - graphql` fragment MyComponent on Type { field @@ -228,12 +213,10 @@ Relay Compiler supports the use of **persisted queries**, in which each version Persisted queries can be enabled by instructing Relay Compiler to emit metadata about each query, mutation, and subscription into a JSON file. The generated file will contain a mapping of query identifiers to query text, which you can then save to your server. To enable persisted queries, use the `--persist-output` flag to the compiler: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` Relay Compiler will then create the id => query text mapping in the path you specify. You can then use this complete @@ -250,7 +233,6 @@ See our relay-compiler section in our [Installation and Setup guide](./installat To use the Relay Compiler, you need either a .graphql or .json GraphQL schema file, describing your GraphQL server's API. Typically these files are local representations of a server source of truth and are not edited directly. For example, we might have a `schema.graphql` like: ```graphql - schema { query: Root } @@ -268,7 +250,6 @@ type WordDefinition { text: String image: String } - ``` ### Source files @@ -284,7 +265,6 @@ For example, given the two files: - `src/Components/DictionaryComponent.js` ```javascript - const DictionaryWordFragment = graphql` fragment DictionaryComponent_word on Word { id @@ -306,7 +286,6 @@ For example, given the two files: - `src/Queries/DictionaryQuery.js` ```javascript - const DictionaryQuery = graphql` query DictionaryQuery { dictionary { @@ -330,9 +309,7 @@ Typically you will not need to import your generated definitions. The [Relay Bab However the Relay Compiler also automatically generates [Flow](https://flow.org) types as [type comments](https://flow.org/en/docs/types/comments/). For example, you can import the generated Flow types like so: ```javascript - import type {DictionaryComponent_word} from './__generated__/DictionaryComponent_word.graphql'; - ``` ### Client schema extensions @@ -342,7 +319,6 @@ The Relay Compiler fully supports client-side schema extensions, which allows yo For example, assuming the server schema `./schema.graphql`: ```graphql - schema { query: Root } @@ -350,28 +326,23 @@ schema { type Root { title: String! } - ``` We can create a `./src/clientSchema.graphql` and define a new type called `Setting`: ```graphql - type Setting { name: String! active: Boolean! } - ``` We can then extend existing server types in the client schema `./src/clientSchema.graphql` with our new `Setting` type, like so: ```graphql - extend type Root { settings: [Setting] } - ``` Any fields specified in the client schema, can be fetched from the [Relay Store](./relay-store), by selecting it in a query or fragment. diff --git a/website/versioned_docs/version-v7.1.0/Modern-LocalStateManagement.md b/website/versioned_docs/version-v7.1.0/Modern-LocalStateManagement.md index 5e0bdde30237a..c6e75a4e6fbf0 100644 --- a/website/versioned_docs/version-v7.1.0/Modern-LocalStateManagement.md +++ b/website/versioned_docs/version-v7.1.0/Modern-LocalStateManagement.md @@ -24,23 +24,19 @@ It can even be used to extend an existing server schema. For example, we can create a new type called `Note`: ```graphql - type Note { ID: ID! title: String body: String } - ``` And then extend the server schema type `User`, with a list of `Note`, called `notes`. ```graphql - extend type User { notes: [Note] } - ``` ## Querying local state @@ -51,7 +47,6 @@ The field can be from the server schema, or it can be schema agnostic, like an i Here, we use a [QueryRenderer](./query-renderer) to get the current `User` via the `viewer` field, along with their id, name and the local list of notes. ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -97,7 +92,6 @@ const Example = (props) => { /> ); } - ``` ## Mutating local state @@ -111,7 +105,6 @@ To build upon the previous example, let's try creating, updating and deleting a ### Create ```javascript - import {commitLocalUpdate} from 'react-relay'; let tempID = 0; @@ -131,7 +124,6 @@ function createUserNote() { user.setLinkedRecords([...userNoteRecords, newNoteRecord], 'notes'); }); } - ``` Note that since this record will be rendered by the `ExampleQuery` in our `QueryRenderer`, the QueryRenderer will automatically retain this data so it isn't garbage collected. @@ -139,20 +131,17 @@ Note that since this record will be rendered by the `ExampleQuery` in our `Query If no component is rendering the local data and you want to manually retain it, you can do so by calling `environment.retain()`: ```javascript - // Tell Relay to retain the record so it isn't garbage collected environment.retain({ dataID, variables: {}, node: { selections: [] } }); - ``` ### Update ```javascript - import {commitLocalUpdate} from 'react-relay'; function updateUserNote(dataID, body, title) { @@ -163,13 +152,11 @@ function updateUserNote(dataID, body, title) { note.setValue(title, 'title') }); } - ``` ### Delete ```javascript - import {commitLocalUpdate} from 'react-relay'; function deleteUserNote(dataID) { @@ -187,7 +174,6 @@ function deleteUserNote(dataID) { user.setLinkedRecords(newUserNoteRecords, 'notes'); }); } - ``` ## Initial local state @@ -196,7 +182,6 @@ All new client-side schema fields default to `undefined` value. Often however, y You can use an updater function via `commitLocalUpdate` to prime local state. ```javascript - import {commitLocalUpdate} from 'react-relay'; commitLocalUpdate(environment, store => { @@ -205,5 +190,4 @@ commitLocalUpdate(environment, store => { // initialize user notes to an empty array. user.setLinkedRecords([], 'notes'); }); - ``` diff --git a/website/versioned_docs/version-v7.1.0/Modern-MigrationSetup.md b/website/versioned_docs/version-v7.1.0/Modern-MigrationSetup.md index 66f1145357e25..a89c0e178e0e5 100644 --- a/website/versioned_docs/version-v7.1.0/Modern-MigrationSetup.md +++ b/website/versioned_docs/version-v7.1.0/Modern-MigrationSetup.md @@ -13,13 +13,11 @@ With some additional configuration, the `"relay"` babel plugin can also translat Relay Classic `Relay.QL` literals. Most importantly, include a reference to your GraphQL Schema as either a json file or graphql schema file. ```javascript - { "plugins": [ ["relay", {"schema": "path/schema.graphql"}] ] } - ``` ## Set up babel-plugin-relay for "[compatibility mode](./relay-compat)" @@ -29,13 +27,11 @@ literals can be translated to be usable by _both_ runtimes if configured to use compatibility mode: ```javascript - { "plugins": [ ["relay", {"compat": true, "schema": "path/schema.graphql"}] ] } - ``` ## Additional Options @@ -47,7 +43,6 @@ thrown at runtime. When compiling code for production deployment, the plugin can be configured to immediately throw upon encountering a validation problem. The plugin can be further customized for different environments with the following options: ```javascript - { "plugins": [ ["relay", { @@ -56,5 +51,4 @@ When compiling code for production deployment, the plugin can be configured to i }] ] } - ``` diff --git a/website/versioned_docs/version-v7.1.0/Modern-Mutations.md b/website/versioned_docs/version-v7.1.0/Modern-Mutations.md index a2e0b285bf2c4..8da3bd999c701 100644 --- a/website/versioned_docs/version-v7.1.0/Modern-Mutations.md +++ b/website/versioned_docs/version-v7.1.0/Modern-Mutations.md @@ -17,7 +17,6 @@ Table of Contents: Use `commitMutation` to create and execute mutations. `commitMutation` has the following signature: ```javascript - commitMutation( environment: Environment, config: { @@ -31,7 +30,6 @@ commitMutation( configs?: Array, }, ); - ``` ### Arguments @@ -58,7 +56,6 @@ commitMutation( Example of a simple mutation: ```javascript - import {commitMutation, graphql} from 'react-relay'; const mutation = graphql` @@ -93,7 +90,6 @@ function markNotificationAsRead(environment, source, storyID) { }, ); } - ``` ## Optimistic Updates @@ -101,7 +97,6 @@ function markNotificationAsRead(environment, source, storyID) { To improve perceived responsiveness, you may wish to perform an "optimistic update", in which the client immediately updates to reflect the anticipated new value even before the response from the server has come back. The simplest way to do this is by providing an `optimisticResponse` and adding it to the `config` that we pass into `commitMutation`: ```javascript - const mutation = graphql` mutation MarkReadNotificationMutation( $input: MarkReadNotificationInput! @@ -130,7 +125,6 @@ commitMutation( variables, }, ); - ``` Another way to enable optimistic updates is via the `optimisticUpdater`, which can be used for more complicated update scenarios. Using `optimisticUpdater` is covered in the section [below](#using-updater-and-optimisticupdater). @@ -152,7 +146,6 @@ Given a deletedIDFieldName, Relay will remove the node(s) from the store. #### Example ```javascript - const mutation = graphql` mutation DestroyShipMutation($input: DestroyShipInput!) { destroyShip(input: $input) { @@ -170,7 +163,6 @@ const configs = [{ type: 'NODE_DELETE', deletedIDFieldName: 'destroyedShipId', }]; - ``` ### RANGE_ADD @@ -190,7 +182,6 @@ Given a parent, information about the connection, and the name of the newly crea #### Example ```javascript - const mutation = graphql` mutation AddShipMutation($input: AddShipInput!) { addShip(input: $input) { @@ -220,7 +211,6 @@ function commit(environment, factionId, name) { }], }); } - ``` ### RANGE_DELETE @@ -242,7 +232,6 @@ from the connection but leave the associated record(s) in the store. #### Example ```javascript - const mutation = graphql` mutation RemoveTagMutation($input: RemoveTagInput!) { removeTag(input: $input) { @@ -268,7 +257,6 @@ function commit(environment, todoId, tagId) { }], }); } - ``` ## Using updater and optimisticUpdater @@ -286,7 +274,6 @@ When you provide these functions, this is roughly what happens during the mutati Here are a quick example of adding a todo item to a Todo list using this [example schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L36): ```javascript - // AddTodoMutation.js import {commitMutation, graphql} from 'react-relay'; import {ConnectionHandler} from 'relay-runtime'; @@ -373,7 +360,6 @@ function commit(environment, text, user) { }, }); } - ``` For details on how to interact with the Relay Store, please refer to our Relay Store [docs](./relay-store). diff --git a/website/versioned_docs/version-v7.1.0/Modern-NetworkLayer.md b/website/versioned_docs/version-v7.1.0/Modern-NetworkLayer.md index 9dddd36d6c235..c9e069b812b01 100644 --- a/website/versioned_docs/version-v7.1.0/Modern-NetworkLayer.md +++ b/website/versioned_docs/version-v7.1.0/Modern-NetworkLayer.md @@ -8,7 +8,6 @@ In order to know how to access your GraphQL server, Relay Modern requires develo Currently the easiest way to create a network layer is via a helper from the `relay-runtime` package: ```javascript - import { Environment, Network, @@ -50,7 +49,6 @@ const environment = new Environment({ }); export default environment; - ``` Note that this is a basic example to help you get started. This example could be extended with additional features such as request/response caching (enabled e.g. when `cacheConfig.force` is false) and uploading form data for mutations (the `uploadables` parameter). @@ -62,7 +60,6 @@ Relay modern makes no assumptions about what to cache and will garbage collect a You have to implement your own cache strategy. A simple solution is to use `QueryResponseCache` (an in-memory cache): ```javascript - import { Environment, Network, @@ -126,7 +123,6 @@ const environment = new Environment({ }); export default environment; - ``` ## Custom open-source implementations diff --git a/website/versioned_docs/version-v7.1.0/Modern-PaginationContainer.md b/website/versioned_docs/version-v7.1.0/Modern-PaginationContainer.md index 6ac3aac8cfb8e..57980d553af9b 100644 --- a/website/versioned_docs/version-v7.1.0/Modern-PaginationContainer.md +++ b/website/versioned_docs/version-v7.1.0/Modern-PaginationContainer.md @@ -24,7 +24,6 @@ However, when [specifying connection fragments](#createpaginationcontainer) for The purpose of the `@connection` directive is to allow Relay to uniquely identify different connections under a parent type. The `@connection` directive takes 2 arguments that help identify the connection: ```graphql - @connection(key: String!, filters: [String]) ``` @@ -37,7 +36,6 @@ The purpose of the `@connection` directive is to allow Relay to uniquely identif Specifying just the `key`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and the value of `$orderBy` (given that no `filters` were provided) @@ -53,13 +51,11 @@ fragment Feed_user on User { } } } - ``` Specifying `key` and `filters`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and /only/ the value of `$searchTerm`, i.e. @@ -77,7 +73,6 @@ fragment Feed_user on User { } } } - ``` ## `createPaginationContainer` @@ -85,7 +80,6 @@ fragment Feed_user on User { `createPaginationContainer` has the following signature: ```javascript - createPaginationContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, @@ -113,7 +107,6 @@ type ConnectionData = { startCursor: ?string, }, }; - ``` ### Arguments @@ -134,7 +127,6 @@ type ConnectionData = { The Component resulting from `createPaginationContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -145,7 +137,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -160,7 +151,6 @@ type Props = { `hasMore` is a function available on the `relay` [prop](#available-props). This function indicates whether there are more pages to fetch from the server or not. ```javascript - hasMore: () => boolean, ``` @@ -170,7 +160,6 @@ hasMore: () => boolean, `isLoading` is a function available on the `relay` [prop](#available-props). This function indicates if a previous call to [`loadMore()`](#loadmore) is still pending. This is convenient for avoiding duplicate load calls. ```javascript - isLoading: () => boolean, ``` @@ -180,7 +169,6 @@ isLoading: () => boolean, `loadMore` is a function available on the `relay` [prop](#available-props). You can call `loadMore()` to fetch more items from the server based on the `connectionConfig` provided to the container. This will return null if there are no more items to fetch, otherwise it will fetch more items and return a Disposable that can be used to cancel the fetch. ```javascript - loadMore( pageSize: number, callback: ?(error: ?Error) => void, @@ -201,7 +189,6 @@ loadMore( `refetchConnection` is a function available on the `relay` [prop](#available-props). You can call `refetchConnection` to restart pagination on a connection from scratch, with optionally a completely new set of variables to pass to the pagination `query`. This is useful for example if you are paginating over a collection based on a userID and the userID changes, you'd want to start paginating over the new collection for the new user. ```javascript - refetchConnection:( totalCount: number, callback: (error: ?Error) => void, @@ -219,7 +206,6 @@ refetchConnection:( ## Pagination Example ```javascript - // Feed.js import {createPaginationContainer, graphql} from 'react-relay'; @@ -314,5 +300,4 @@ module.exports = createPaginationContainer( ` } ); - ``` diff --git a/website/versioned_docs/version-v7.1.0/Modern-PersistedQueries.md b/website/versioned_docs/version-v7.1.0/Modern-PersistedQueries.md index 137cc2e23220c..ec03b69ba09c3 100644 --- a/website/versioned_docs/version-v7.1.0/Modern-PersistedQueries.md +++ b/website/versioned_docs/version-v7.1.0/Modern-PersistedQueries.md @@ -17,12 +17,10 @@ The relay compiler supports persisted queries which is useful because: In your `npm` script in `package.json`, run the relay compiler using the `--persist-output` flag: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` The `--persist-ouput` flag does 3 things: @@ -31,8 +29,7 @@ The `--persist-ouput` flag does 3 things: For example without `--persist-output`, a generated `ConcreteRequest` might look like below: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -49,8 +46,7 @@ The `--persist-ouput` flag does 3 things: With `--persist-output ` this becomes: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -68,12 +64,10 @@ The `--persist-ouput` flag does 3 things: 2. It generates a JSON file at the `` you specify containing a mapping from query ids to the corresponding operation texts. -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./src/queryMaps/queryMap.json" } - ``` The example above writes the complete query map file to `./src/queryMaps/queryMap.json`. You need to ensure all the directories @@ -83,8 +77,7 @@ leading to the `queryMap.json` file exist. You'll need to modify your network layer fetch implementation to pass a documentId parameter in the POST body instead of a query parameter: -```js - +```javascript function fetchQuery(operation, variables,) { return fetch('/graphql', { method: 'POST', @@ -100,7 +93,6 @@ function fetchQuery(operation, variables,) { return response.json(); }); } - ``` ## Executing Persisted Queries on the Server @@ -116,13 +108,11 @@ the query map file in a common location accessible to both the client and the se For applications where the client and server projects are separate, one option is to have an additional npm run script to push the query map at compile time to a location accessible by your server: -```js - +```javascript "scripts": { "push-queries": "node ./pushQueries.js", "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-ouput && npm run push-queries" } - ``` Some possibilities of what you can do in `./pushQueries.js`: @@ -146,8 +136,7 @@ database technologies you use, so we'll just cover the most common and basic exa If you use `express-graphql` and have access to the query map file, you can import the `--persist-output` JSON file directly and perform the matching using the `matchQueryMiddleware` from [relay-compiler-plus](https://github.com/yusinto/relay-compiler-plus). -```js - +```javascript import Express from 'express'; import expressGraphql from 'express-graphql'; import {matchQueryMiddleware} from 'relay-compiler-plus'; @@ -158,7 +147,6 @@ const app = Express(); app.use('/graphql', matchQueryMiddleware(queryMapJson), expressGraphql({schema})); - ``` ## Using `--persist-output` and `--watch` diff --git a/website/versioned_docs/version-v7.1.0/Modern-QueryRenderer.md b/website/versioned_docs/version-v7.1.0/Modern-QueryRenderer.md index cf6c37f3d9a4d..b621ef9986bf1 100644 --- a/website/versioned_docs/version-v7.1.0/Modern-QueryRenderer.md +++ b/website/versioned_docs/version-v7.1.0/Modern-QueryRenderer.md @@ -24,7 +24,6 @@ However, a `QueryRenderer` will not start loading its data until it is mounted, ## Example ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -56,5 +55,4 @@ const Example = (props) => { /> ); } - ``` diff --git a/website/versioned_docs/version-v7.1.0/Modern-RefetchContainer.md b/website/versioned_docs/version-v7.1.0/Modern-RefetchContainer.md index 7ce0d14e45417..51c2c44db8941 100644 --- a/website/versioned_docs/version-v7.1.0/Modern-RefetchContainer.md +++ b/website/versioned_docs/version-v7.1.0/Modern-RefetchContainer.md @@ -16,13 +16,11 @@ Table of Contents: `createRefetchContainer` has the following signature: ```javascript - createRefetchContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, refetchQuery: GraphQLTaggedNode, ): ReactComponentClass; - ``` ### Arguments @@ -37,7 +35,6 @@ createRefetchContainer( The Component resulting from `createRefetchContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -45,7 +42,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -61,7 +57,6 @@ type Props = { `refetch` has the following signature: ```javascript - type RefetchOptions = { force?: boolean, }; @@ -102,7 +97,6 @@ Returns a `Disposable` on which you could call `dispose()` to cancel the refetch In this simple example, let's assume we want to fetch the latest data for a `TodoItem` from the server: ```javascript - // TodoItem.js import {createRefetchContainer, graphql} from 'react-relay'; @@ -148,7 +142,6 @@ export default createRefetchContainer( } ` ); - ``` ### Loading more data @@ -156,7 +149,6 @@ export default createRefetchContainer( In this example we are using a Refetch Container to fetch more stories in a story feed component. ```javascript - import {createRefetchContainer, graphql} from 'react-relay'; class FeedStories extends React.Component { @@ -212,5 +204,4 @@ export default createRefetchContainer( } `, ); - ``` diff --git a/website/versioned_docs/version-v7.1.0/Modern-RelayCompat.md b/website/versioned_docs/version-v7.1.0/Modern-RelayCompat.md index 36632d3a8f1a1..f47dbd845ba3e 100644 --- a/website/versioned_docs/version-v7.1.0/Modern-RelayCompat.md +++ b/website/versioned_docs/version-v7.1.0/Modern-RelayCompat.md @@ -31,7 +31,6 @@ Relay Modern. The components using Relay Compat can be referred to by both other Relay Modern and Relay Classic components. ```javascript - const {createFragmentContainer, graphql} = require('react-relay/compat'); class TodoItem extends React.Component { @@ -47,5 +46,4 @@ module.exports = createFragmentContainer(TodoItem, graphql` isComplete } `); - ``` diff --git a/website/versioned_docs/version-v7.1.0/Modern-RelayEnvironment.md b/website/versioned_docs/version-v7.1.0/Modern-RelayEnvironment.md index 27d90b2fc4fe1..99e728bce740d 100644 --- a/website/versioned_docs/version-v7.1.0/Modern-RelayEnvironment.md +++ b/website/versioned_docs/version-v7.1.0/Modern-RelayEnvironment.md @@ -12,7 +12,6 @@ Most applications will create a single Environment instance and use it throughou To create an environment instance in Relay Modern, use the `RelayModernEnvironment` class: ```javascript - const { Environment, Network, @@ -30,7 +29,6 @@ const environment = new Environment({ network, store, }); - ``` For more details on creating a Network, see the [NetworkLayer guide](./network-layer). @@ -44,7 +42,6 @@ The example above did not configure a `handlerProvider`, which means that a defa If you wish to provide your own `handlerProvider`, you can do so: ```javascript - const { ConnectionHandler, } = require('relay-runtime'); @@ -58,5 +55,4 @@ function handlerProvider(handle) { `handlerProvider: No handler provided for ${handle}` ); } - ``` diff --git a/website/versioned_docs/version-v7.1.0/Modern-RelayStore.md b/website/versioned_docs/version-v7.1.0/Modern-RelayStore.md index 8bc27098b205e..56b91d3036791 100644 --- a/website/versioned_docs/version-v7.1.0/Modern-RelayStore.md +++ b/website/versioned_docs/version-v7.1.0/Modern-RelayStore.md @@ -16,7 +16,6 @@ Table of Contents: The `RecordSourceSelectorProxy` is the type of the `store` that [`updater` functions](./mutations#using-updater-and-optimisticupdater) receive as an argument. The following is the `RecordSourceSelectorProxy` interface: ```javascript - interface RecordSourceSelectorProxy { create(dataID: string, typeName: string): RecordProxy; delete(dataID: string): void; @@ -25,7 +24,6 @@ interface RecordSourceSelectorProxy { getRootField(fieldName: string): ?RecordProxy; getPluralRootField(fieldName: string): ?Array; } - ``` ### `create(dataID: string, typeName: string): RecordProxy` @@ -35,9 +33,7 @@ Creates a new record in the store given a `dataID` and the `typeName` as defined #### Example ```javascript - const record = store.create(dataID, 'Todo'); - ``` ### `delete(dataID: string): void` @@ -47,9 +43,7 @@ Deletes a record from the store given its `dataID`. #### Example ```javascript - store.delete(dataID); - ``` ### `get(dataID: string): ?RecordProxy` @@ -59,9 +53,7 @@ Retrieves a record from the store given its `dataID`. Returns a [`RecordProxy`]( #### Example ```javascript - const record = store.get(dataID); - ``` ### `getRoot(): RecordProxy` @@ -73,20 +65,16 @@ Returns the [`RecordProxy`](#recordproxy) representing the root of the GraphQL d Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - // Represents root query const root = store.getRoot(); - ``` ### `getRootField(fieldName: string): ?RecordProxy` @@ -98,19 +86,15 @@ Retrieves a root field from the store given the `fieldName`, as defined by the G Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - const viewer = store.getRootField('viewer'); - ``` ### `getPluralRootField(fieldName: string): ?Array` @@ -122,19 +106,15 @@ Retrieves a root field that represents a collection from the store given the `fi Given the GraphQL document: ```graphql - nodes(first: 10) { # ... } - ``` Usage: ```javascript - const nodes = store.getPluralRootField('nodes'); - ``` ## RecordProxy @@ -142,7 +122,6 @@ const nodes = store.getPluralRootField('nodes'); The `RecordProxy` serves as an interface to mutate records: ```javascript - interface RecordProxy { copyFieldsFrom(sourceRecord: RecordProxy): void; getDataID(): string; @@ -167,7 +146,6 @@ interface RecordProxy { ): RecordProxy; setValue(value: mixed, name: string, arguments?: ?Object): RecordProxy; } - ``` ### `getDataID(): string` @@ -177,9 +155,7 @@ Returns the dataID of the current record. #### Example ```javascript - const id = record.getDataID(); - ``` ### `getType(): string` @@ -189,7 +165,6 @@ Gets the type of the current record, as defined by the GraphQL schema. #### Example ```javascript - const type = user.getType(); // User ``` @@ -203,20 +178,16 @@ Gets the value of a field in the current record given the field name. Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - const name = viewer.getValue('name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. @@ -226,20 +197,16 @@ Optionally, if the field takes arguments, you can pass a bag of `variables`. Given the GraphQL document: ```graphql - viewer { id name(arg: $arg) } - ``` Usage: ```javascript - const name = viewer.getValue('name', {arg: 'value'}); - ``` ### `getLinkedRecord(name: string, arguments?: ?Object): ?RecordProxy` @@ -251,23 +218,19 @@ Retrieves a record associated with the current record given the field name, as d Given the GraphQL document: ```graphql - rootField { viewer { id name } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -277,22 +240,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { viewer(arg: $arg) { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {arg: 'value'}); - ``` ### `getLinkedRecords(name: string, arguments?: ?Object): ?Array` @@ -304,22 +263,18 @@ Retrieves the set of records associated with the current record given the field Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const nodes = rootField.getLinkedRecords('nodes'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -329,22 +284,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { nodes(first: $count) { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {count: 10}); - ``` ### `getOrCreateLinkedRecord(name: string, typeName: string, arguments?: ?Object)` @@ -356,19 +307,16 @@ Retrieves the a record associated with the current record given the field name, Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = rootField.getOrCreateLinkedRecord('viewer', 'User'); // Will create if it doesn't exist @@ -383,28 +331,22 @@ Mutates the current record by setting a new value on the specified field. Return Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - viewer.setValue('New Name', 'name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. ```javascript - viewer.setValue('New Name', 'name', {arg: 'value'}); - ``` ### `copyFieldsFrom(sourceRecord: RecordProxy): void` @@ -414,7 +356,6 @@ Mutates the current record by copying the fields over from the passed in record #### Example ```javascript - const record = store.get(id1); const otherRecord = store.get(id2); record.copyFieldsFrom(otherRecord); // Mutates `record` @@ -430,19 +371,16 @@ Mutates the current record by setting a new linked record on the given the field Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = store.create(/* ... */)'' rootField.setLinkedRecord(newViewer, 'viewer'); // @@ -460,19 +398,16 @@ Mutates the current record by setting a new set of linked records on the given t Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newNode = store.create(/* ... */); const newNodes = [...rootField.getLinkedRecords('nodes'), newNode]; @@ -487,7 +422,6 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl `ConnectionHandler` is a utility module exposed by `relay-runtime` that aids in the manipulation of connections. `ConnectionHandler` exposes the following interface: ```javascript - interface ConnectionHandler { getConnection( record: RecordProxy, @@ -512,7 +446,6 @@ interface ConnectionHandler { ): void, deleteNode(connection: RecordProxy, nodeID: string): void } - ``` ### `getConnection(record: RecordProxy, key: string, filters?: ?Object)` @@ -522,7 +455,6 @@ Given a record and a connection key, and optionally a set of filters, `getConnec First, let's take a look at a plain connection: ```graphql - fragment FriendsFragment on User { friends(first: 10) { edges { @@ -532,26 +464,22 @@ fragment FriendsFragment on User { } } } - ``` Accessing a plain connection field like this is the same as other regular field: ```javascript - // The `friends` connection record can be accessed with: const user = store.get(userID); const friends = user && user.getLinkedRecord(user, 'friends'); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` In a [pagination container](./pagination-container), we usually annotate the actual connection field with `@connection` to tell Relay which part needs to be paginated: ```graphql - fragment FriendsFragment on User { friends(first: 10, orderby: "firstname") @connection( key: "FriendsFragment_friends", @@ -563,7 +491,6 @@ fragment FriendsFragment on User { } } } - ``` For connections like the above, `ConnectionHandler` helps us find the record: @@ -581,7 +508,6 @@ const friends = ConnectionHandler.getConnection( ); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` ### Edge creation and insertion @@ -611,7 +537,6 @@ ConnectionHandler.insertEdgeAfter(friends, edge); // No cursor provided, Insert the edge at the front: ConnectionHandler.insertEdgeBefore(friends, edge); - ``` ### `deleteNode(connection: RecordProxy, nodeID: string): void` @@ -625,5 +550,4 @@ Given a connection, deletes any edges whose id matches the given id. const user = store.get(userID); const friends = ConnectionHandler.getConnection(user, 'friends'); ConnectionHandler.deleteNode(friends, idToDelete); - ``` diff --git a/website/versioned_docs/version-v7.1.0/Modern-Subscriptions.md b/website/versioned_docs/version-v7.1.0/Modern-Subscriptions.md index 802f1d02b06de..bd1c5fe2f350c 100644 --- a/website/versioned_docs/version-v7.1.0/Modern-Subscriptions.md +++ b/website/versioned_docs/version-v7.1.0/Modern-Subscriptions.md @@ -6,7 +6,6 @@ original_id: subscriptions Relay exposes the following APIs to create subscriptions. ```javascript - const {requestSubscription} = require('react-relay'); type Variables = {[name: string]: any}; @@ -27,7 +26,6 @@ requestSubscription( configs?: Array, }, ) => Disposable; - ``` The function returns a `Disposable` on which you could call `dispose()` to cancel the refetch. @@ -53,7 +51,6 @@ appropriate when you are only changing the properties of existing records that can be identified by their `id`: ```javascript - const { requestSubscription, graphql, @@ -87,7 +84,6 @@ requestSubscription( onError: error => console.error(error), } ); - ``` # Updating the client on each response @@ -97,7 +93,6 @@ Relay's in-memory cache when each subscription response is received. To do so, pass an `updater` function: ```javascript - const {ConnectionHandler} = require('relay-runtime'); requestSubscription( @@ -123,5 +118,4 @@ requestSubscription( }, }, ); - ``` diff --git a/website/versioned_docs/version-v7.1.0/Modern-TestingRelayComponents.md b/website/versioned_docs/version-v7.1.0/Modern-TestingRelayComponents.md index 4e5cf9e61a922..2916a65f56e06 100644 --- a/website/versioned_docs/version-v7.1.0/Modern-TestingRelayComponents.md +++ b/website/versioned_docs/version-v7.1.0/Modern-TestingRelayComponents.md @@ -65,7 +65,6 @@ MockPayloadGenerator may drastically simplify the process of creating and mainta Example of a simple Mock Resolver: ```javascript - { ID() { // Return mock value for a scalar filed with type ID @@ -76,13 +75,11 @@ Example of a simple Mock Resolver: return "Lorem Ipsum" } } - ``` It is possible to define more resolvers for Object types ```javascript - { // This will be the default values for User object in the query response User() { @@ -95,7 +92,6 @@ It is possible to define more resolvers for Object types }; }, } - ``` ### Mock Resolver Context @@ -103,7 +99,6 @@ It is possible to define more resolvers for Object types The first argument of the MockResolver is the object that contains Mock Resolver Context. It is possible to return dynamic values from mock resolvers based on the context - for instance, name or alias of the field, a path in the selection, arguments, or parent type. ```javascript - { String(context) { if (context.name === 'zip') { @@ -117,7 +112,6 @@ The first argument of the MockResolver is the object that contains Mock Resolver } } } - ``` ### ID Generation @@ -125,14 +119,12 @@ The first argument of the MockResolver is the object that contains Mock Resolver The second argument of the Mock Resolver its a function that will generate a sequence of integers, useful to generate unique ids in the tests ```javascript - { // will generate strings "my-id-1", "my-id-2", etc. ID(_, generateId) { return `my-id-${generateId()}`; }, } - ``` ### @relay_test_operation @@ -142,7 +134,6 @@ Most of GraphQL type information for a specific field in the selection is not av Operation with the @relay_test_operation directive will have additional metadata that will contain GraphQL type info for fields in the operation's selection. And it will improve the quality of the generated data. You also will be able to define Mock resolvers for Scalar (not only ID and String) and Abstract types: ```javascript - { Float() { return 123.456; @@ -160,7 +151,6 @@ Operation with the @relay_test_operation directive will have additional metadata }; } } - ``` ## Examples @@ -170,7 +160,6 @@ Operation with the @relay_test_operation directive will have additional metadata Using `createMockEnvironment` and `MockPayloadGenerator` allows writing concise tests for components that are using Relay Containers and Renderers. Both those modules can be imported from `relay-test-utils` ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { @@ -223,7 +212,6 @@ test('Error State', () => { renderer.root.find(item => (item.props.testID = 'errorMessage')), ).toBeDefined(); }); - ``` ### Fragment Container Tests @@ -231,7 +219,6 @@ test('Error State', () => { Essentially, in the example above will `resolveMostRecentOperation` will generate data for all child fragment containers (pagination, refetch). But, usually the Root Components container may have many child fragment components and you may want to exercise a specific Fragment Container. The solution for that would be to wrap you fragment container with the QueryRenderer that renders a Query that's spreads fragments from you fragment container. ```javascript - test('Fragment Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -262,7 +249,6 @@ test('Fragment Container', () => { expect(renderer).toMatchSnapshot(); }); - ``` ### Pagination Container Test @@ -270,7 +256,6 @@ test('Fragment Container', () => { Essentially, tests for Pagination container are not different from Fragment Container tests. But we can do more here, we can actually see how the pagination works - we can assert the behavior of our components when performing pagination (load more, refetch). ```javascript - // Pagination Example test('Pagination Container', () => { const environment = createMockEnvironment(); @@ -344,7 +329,6 @@ test('Pagination Container', () => { We can use similar approach here with wrapping container with Query Renderer. And for the sake of completeness, we will add example here: ```javascript - test('Refetch Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -386,7 +370,6 @@ test('Refetch Container', () => { ); // expect(renderer).toMatchSnapshot(); }); - ``` ### Mutations @@ -394,7 +377,6 @@ test('Refetch Container', () => { Mutations itself are operations so we can test them independently (unit-test) for specific mutation, or in combination with the view from which this mutation is called. ```javascript - // Say, you have a mutation function function sendMutation(environment, onCompleted, onError, variables) commitMutation(environment, { @@ -417,7 +399,6 @@ test('it should send mutation', () => { ); expect(onCompleted).toBeCalled(); }); - ``` ### Subscription @@ -425,7 +406,6 @@ test('it should send mutation', () => { We can test subscription in a similar way we test mutations ```javascript - // Example subscribe function function subscribe(environment, onNext, onError, variables) requestSubscription(environment, { @@ -448,7 +428,6 @@ test('it should subscribe', () => { ); expect(onNext).toBeCalled(); }); - ``` ### Example with `queueOperationResolver` @@ -456,7 +435,6 @@ test('it should subscribe', () => { With `queueOpeararionResolver` it possible to define responses for operations that will be executed on the environment ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { diff --git a/website/versioned_docs/version-v7.1.0/Modern-TypeEmission.md b/website/versioned_docs/version-v7.1.0/Modern-TypeEmission.md index 63614b869a322..4ff63e4a7d81b 100644 --- a/website/versioned_docs/version-v7.1.0/Modern-TypeEmission.md +++ b/website/versioned_docs/version-v7.1.0/Modern-TypeEmission.md @@ -16,7 +16,6 @@ In this example the emitted type-information would require the variables object #### Flow ```javascript - /** * export type ExampleQueryVariables = {| * +artistID: string @@ -44,7 +43,6 @@ const variables: ExampleQueryVariables = { #### TypeScript ```javascript - /** * export type ExampleQueryVariables = { * readonly artistID: string @@ -79,7 +77,6 @@ In this example the emitted type-information describes the response data availab #### Flow ```javascript - /** * export type ExampleQueryResponse = {| * +artist: ?{| @@ -110,7 +107,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * export type ExampleQueryResponse = { * readonly artist?: { @@ -146,7 +142,6 @@ Similarly, in this example the emitted type-information describes the prop data #### Flow ```javascript - /** * export type ExampleFragment_artist = {| * +name: string @@ -172,7 +167,6 @@ export const ExampleFragment = createFragmentContainer( #### TypeScript ```javascript - /** * export type ExampleFragment_artist = { * readonly name: string @@ -206,7 +200,6 @@ Consider a component that composes the above fragment container example. In this #### Flow ```javascript - /** * import type { FragmentReference } from "relay-runtime"; * declare export opaque type ExampleFragment_artist$ref: FragmentReference; @@ -250,7 +243,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * declare const _ExampleFragment_artist$ref: unique symbol; * export type ExampleFragment_artist$ref = typeof _ExampleFragment_artist$ref; @@ -315,7 +307,6 @@ $ relay-compiler --artifactDirectory ./src/__generated__ […] ["relay", { "artifactDirectory": "./src/__generated__" }] ] } - ``` It is recommended to alias this directory in your module resolution configuration such that you don’t need to specify relative paths in your source files. This is what is also done in the above examples, where artifacts are imported from a `__generated__` alias, rather than relative paths like `../../../../__generated__`. diff --git a/website/versioned_docs/version-v7.1.0/Modern-UpgradingSetVariables.md b/website/versioned_docs/version-v7.1.0/Modern-UpgradingSetVariables.md index d5b086fafce20..ff73feec04f8b 100644 --- a/website/versioned_docs/version-v7.1.0/Modern-UpgradingSetVariables.md +++ b/website/versioned_docs/version-v7.1.0/Modern-UpgradingSetVariables.md @@ -36,7 +36,6 @@ fragment on User { # ... } } - ``` This should be upgraded to use a [`PaginationContainer`](./pagination-container). @@ -61,7 +60,6 @@ fragment on User { # ... } } - ``` This can be upgraded by using a [`RefetchContainer`](./refetch-container) which allows you to specify the exact query to use to fetch the new data. @@ -86,7 +84,6 @@ fragment on FeedbackTarget { # ... } } - ``` This can be upgraded by conditionally rendering a [`QueryRenderer`](./query-renderer) which will load the data once it is rendered. The code overhead of doing this is dramatically reduced with the new API. diff --git a/website/versioned_docs/version-v7.1.0/Modern-fetchQuery.md b/website/versioned_docs/version-v7.1.0/Modern-fetchQuery.md index 2e9461ad527bd..c1a06ab7d2493 100644 --- a/website/versioned_docs/version-v7.1.0/Modern-fetchQuery.md +++ b/website/versioned_docs/version-v7.1.0/Modern-fetchQuery.md @@ -6,7 +6,6 @@ original_id: fetch-query You can use the `fetchQuery` function to imperatively make GraphQL Requests. This is useful for cases where you want to make requests outside of React but still utilize the Relay store and network layer. ```javascript - import {fetchQuery, graphql} from 'relay-runtime'; const query = graphql` @@ -25,7 +24,6 @@ fetchQuery(environment, query, variables) .then(data => { // access the graphql response }); - ``` ## Arguments diff --git a/website/versioned_docs/version-v7.1.0/PrinciplesAndArchitecture-Compiler.md b/website/versioned_docs/version-v7.1.0/PrinciplesAndArchitecture-Compiler.md index c195491682b1f..fcd0490cb724f 100644 --- a/website/versioned_docs/version-v7.1.0/PrinciplesAndArchitecture-Compiler.md +++ b/website/versioned_docs/version-v7.1.0/PrinciplesAndArchitecture-Compiler.md @@ -74,7 +74,6 @@ foo { # type FooType foo { id } - ``` - `SkipRedundantNodeTransform`: A more advanced version of flattening, this eliminates more complex cases of field duplication such as when a field is fetched both unconditionally and conditionally, or is fetched by two different sub-fragments. For example: @@ -97,7 +96,6 @@ foo { id } } - ``` - `GenerateRequisiteFieldTransform`: This optional, Relay-specific transform inserts `id` fields for globally identifiable objects and `__typename` fields wherever the type cannot be statically determined (e.g. for unions). diff --git a/website/versioned_docs/version-v7.1.0/PrinciplesAndArchitecture-Runtime.md b/website/versioned_docs/version-v7.1.0/PrinciplesAndArchitecture-Runtime.md index 9491d290c146f..e9221631a701d 100644 --- a/website/versioned_docs/version-v7.1.0/PrinciplesAndArchitecture-Runtime.md +++ b/website/versioned_docs/version-v7.1.0/PrinciplesAndArchitecture-Runtime.md @@ -77,7 +77,6 @@ RecordSource { city: 'Seattle', } } - ``` [1] Note that GraphQL itself does not impose this constraint, and Relay Runtime may also be used for schemas that do not conform to it. For example, both systems can be used to query a single denormalized table. However, many of the features that Relay Runtime provides, such as caching and normalization, work best when the data is represented as a normalized graph with stable identities for discrete pieces of information. diff --git a/website/versioned_docs/version-v7.1.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md b/website/versioned_docs/version-v7.1.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md index a8842ae084922..9ff8a7840df90 100644 --- a/website/versioned_docs/version-v7.1.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md +++ b/website/versioned_docs/version-v7.1.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md @@ -12,7 +12,6 @@ In this article we'll explore what it means to build a GraphQL client framework Imagine we have a simple application that fetches a list of stories, and some details about each one. Here's how that might look in resource-oriented REST: ```javascript - // Fetch the list of story IDs but not their details: rest.get('/stories').then(stories => // This resolves to a list of items with linked resources: @@ -25,13 +24,11 @@ rest.get('/stories').then(stories => // `[ { id: "...", text: "..." } ]` console.log(stories); }); - ``` Note that this approach requires _n+1_ requests to the server: 1 to fetch the list, and _n_ to fetch each item. With GraphQL we can fetch the same data in a single network request to the server (without creating a custom endpoint that we'd then have to maintain): ```javascript - graphql.get(`query { stories { id, text } }`).then( stories => { // A list of story items: @@ -39,7 +36,6 @@ graphql.get(`query { stories { id, text } }`).then( console.log(stories); } ); - ``` So far we're just using GraphQL as a more efficient version of typical REST approaches. Note two important benefits in the GraphQL version: @@ -56,7 +52,6 @@ Repeatedly refetching information from the server can get quite slow. For exampl In a resource-oriented REST system, we can maintain a **response cache** based on URIs: ```javascript - var _cache = new Map(); rest.get = uri => { if (!_cache.has(uri)) { @@ -64,13 +59,11 @@ rest.get = uri => { } return _cache.get(uri); }; - ``` Response-caching can also be applied to GraphQL. A basic approach would work similarly to the REST version. The text of the query itself can be used as a cache key: ```javascript - var _cache = new Map(); graphql.get = queryText => { if (!_cache.has(queryText)) { @@ -78,7 +71,6 @@ graphql.get = queryText => { } return _cache.get(queryText); }; - ``` Now, requests for previously cached data can be answered immediately without making a network request. This is a practical approach to improving the perceived performance of an application. However, this method of caching can cause problems with data consistency. @@ -90,7 +82,6 @@ With GraphQL it is very common for the results of multiple queries to overlap. H ``` query { stories { id, text, likeCount } } - ``` and then later refetch one of the stories whose `likeCount` has since been incremented: @@ -98,7 +89,6 @@ and then later refetch one of the stories whose `likeCount` has since been incre ``` query { story(id: "123") { id, text, likeCount } } - ``` We'll now see different `likeCount`s depending on how the story is accessed. A view that uses the first query will see an outdated count, while a view using the second query will see the updated count. @@ -119,7 +109,6 @@ query { } } } - ``` And here's a possible response: @@ -134,13 +123,11 @@ query: { } } } - ``` Although the response is hierarchical, we'll cache it by flattening all the records. Here is an example of how Relay would cache this query response: ```javascript - Map { // `story(id: "1")` 1: Map { @@ -152,7 +139,6 @@ Map { name: 'Jan', }, }; - ``` This is only a simple example: in reality the cache must handle one-to-many associations and pagination (among other things). @@ -182,7 +168,6 @@ The first query was for a list of stories: ``` query { stories { id, text, likeCount } } - ``` With a normalized response cache, a record would be created for each story in the list. The `stories` field would store links to each of these records. @@ -192,7 +177,6 @@ The second query refetched the information for one of those stories: ``` query { story(id: "123") { id, text, likeCount } } - ``` When this response is normalized, Relay can detect that this result overlaps with existing data based on its `id`. Rather than create a new record, Relay will update the existing `123` record. The new `likeCount` is therefore available to _both_ queries, as well as any other query that might reference this story. @@ -215,7 +199,6 @@ query { } } } - ``` After initially fetching this story our cache might be as follows. Note that the story and comment both link to the same record as `author`: @@ -242,7 +225,6 @@ Map { author: Link(2), }, } - ``` The author of this story also commented on it — quite common. Now imagine that some other view fetches new information about the author, and her profile photo has changed to a new URI. Here's the _only_ part of our cached data that changes: @@ -256,7 +238,6 @@ Map { photo: 'http://.../photo2.jpg', }, } - ``` The value of the `photo` field has changed; and therefore the record `2` has also changed. And that's it. Nothing else in the _cache_ is affected. But clearly our _view_ needs to reflect the update: both instances of the author in the UI (as story author and comment author) need to show the new photo. @@ -273,7 +254,6 @@ ImmutableMap { }, 3: ImmutableMap // same as before } - ``` If we replace `2` with a new immutable record, we'll also get a new immutable instance of the cache object. However, records `1` and `3` are untouched. Because the data is normalized, we can't tell that `story`'s contents have changed just by looking at the `story` record alone. @@ -299,7 +279,6 @@ mutation StoryLike($storyID: String) { likeCount } } - ``` Notice that we're querying for data that _may_ have changed as a result of the mutation. An obvious question is: why can't the server just tell us what changed? The answer is: it's complicated. GraphQL abstracts over _any_ data storage layer (or an aggregation of multiple sources), and works with any programming language. Furthermore, the goal of GraphQL is to provide data in a form that is useful to product developers building a view. diff --git a/website/versioned_docs/version-v7.1.0/PrinciplesAndArchitecture-ThinkingInRelay.md b/website/versioned_docs/version-v7.1.0/PrinciplesAndArchitecture-ThinkingInRelay.md index d6f1572d5590b..4fb68372ec4b3 100644 --- a/website/versioned_docs/version-v7.1.0/PrinciplesAndArchitecture-ThinkingInRelay.md +++ b/website/versioned_docs/version-v7.1.0/PrinciplesAndArchitecture-ThinkingInRelay.md @@ -30,13 +30,11 @@ fragment Story_story on Story { photo } } - ``` And this fragment can then be used to define the Story container: ```javascript - const {createFragmentContainer, graphql} = require('react-relay'); // Plain React component. @@ -64,7 +62,6 @@ const StoryContainer = createFragmentContainer(Story, { In React, rendering a view requires two inputs: the _component_ to render, and a _root_ DOM (UI) node to render into. Rendering Relay containers is similar: we need a _container_ to render, and a _root_ in the graph from which to start our query. We also must ensure that the queries for the container are executed and may want to show a loading indicator while data is being fetched. Similar to `ReactDOM.render(component, domNode)`, Relay provides `` for this purpose. The `query` and `variables` define what data to fetch and `render` defines what to render. Here's how we might render ``: ```javascript - ReactDOM.render( { ); } } - ``` The above code is doing something very similar to our [previous example](#rendering-graphql-queries). However, we are now passing a `$userID` variable to the GraphQL query via the `variables` prop. This has a couple of important implications: @@ -228,7 +216,6 @@ Now that we know how to define and fetch queries, let's actually start building First, let's start at the bottom. Suppose that we want to render a component that simply displays a given todo item's text and completed state: ```javascript - // Todo.js import React from 'react'; @@ -258,7 +245,6 @@ export default class Todo extends React.Component { ); } } - ``` From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L112), we know that we can query this data on the `Todo` type. However, we don't want to have to send a separate query for each todo item; that would defeat the purpose of using GraphQL over a traditional REST API. We could manually query for these fields directly in our `QueryRenderer` query, but that would hurt re-usability: what if we want to query the same set of fields as part of a different query? Additionally, we wouldn't know which component needs the data we're querying, which is a problem Relay directly tries to address. @@ -266,18 +252,15 @@ From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/dat Instead, we can define a reusable [Fragment](http://graphql.org/learn/queries/#fragments), which allows us to define a set of fields on a type and reuse them within our queries wherever we need to: ```graphql - fragment TodoItemFragment on Todo { complete text } - ``` Our component can then use this fragment to declare its data dependency on the `Todo` GraphQL type: ```javascript - // Todo.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -340,7 +323,6 @@ Before proceeding, don't forget to run the Relay Compiler with `yarn relay`. Given that [Fragment Containers](./fragment-container) are just React components, we can compose them as such. We can even re-use fragment containers within other fragment containers. As an example, let's see how we would define a `TodoList` component that just renders a list of todo items, and whether all have been completed or not: ```javascript - // TodoList.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -401,7 +383,6 @@ export default createFragmentContainer( `, }, ); - ``` As with the first fragment container we defined, `TodoList` declares it's data dependencies via a fragment. However, this component additionally re-uses the fragment previously defined by the `Todo` component, and passes the appropriate data when rendering the child `Todo` components (a.k.a. fragment containers). @@ -416,7 +397,6 @@ fragment containers do not directly fetch data. Instead, containers declare a sp A `QueryRenderer` rendering these fragment containers could look like the following: ```javascript - // ViewerTodoList.js import React from 'react'; import {graphql, QueryRenderer} from 'react-relay'; @@ -457,7 +437,6 @@ export default class ViewerTodoList extends React.Component { ); } } - ``` Check out our docs for [Fragment Containers](./fragment-container) for more details, and our guides on [Refetch](./refetch-container) and [Pagination](./pagination-container) for more advanced usage of containers. @@ -469,7 +448,6 @@ Now that we know how to query for and render data, let's move on to changing our From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L35), we know that we have some mutations available to us, so let's start by writing a mutation to change the `complete` status of a given todo item (i.e. mark or unmark it as done): ```graphql - mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { changeTodoStatus(input: $input) { todo { @@ -478,7 +456,6 @@ mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { } } } - ``` This mutation allows us to query back some data as a [result of the mutation](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L18), so we're going to query for the updated `complete` status on the todo item. @@ -486,7 +463,6 @@ This mutation allows us to query back some data as a [result of the mutation](ht In order to execute this mutation in Relay, we're going to write a new mutation using Relay's `commitMutation` api: ```javascript - // ChangeTodoStatusMutation.js import {graphql, commitMutation} from 'react-relay'; @@ -520,7 +496,6 @@ function commit( } export default {commit}; - ``` Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mutation to the server and, in our case, upon receiving a response it will automatically update the local data store with the latest data from the server. This also means that upon receiving the response, Relay will ensure that any components (i.e. containers) that depend on the updated data are re-rendered. @@ -528,7 +503,6 @@ Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mut In order to actually use this mutation in our component, we could update our `Todo` component in the following way: ```javascript - // Todo.js // ... @@ -562,7 +536,6 @@ In order to make the experience better, we can configure our mutation to do an o In Relay, there's a couple of options we can pass to `commitMutation` to enable optimistic updates. Let's see what that would look like in our `ChangeTodoStatusMutation`: ```javascript - // ChangeTodoStatusMutation.js // ... @@ -597,7 +570,6 @@ function commit( } export default {commit}; - ``` In the simplest case above, we just need to pass an `optimisticResponse` option, which should refer to an object having the same shape as the mutation response payload. When we pass this option, Relay will know to immediately update our local data with the optimistic response, and then update it with the actual server response or roll it back if an error occurs. diff --git a/website/versioned_docs/version-v8.0.0/Modern-ConvertingMutations.md b/website/versioned_docs/version-v8.0.0/Modern-ConvertingMutations.md index 08ad2e998cb2d..8f4bdc1d8e0d2 100644 --- a/website/versioned_docs/version-v8.0.0/Modern-ConvertingMutations.md +++ b/website/versioned_docs/version-v8.0.0/Modern-ConvertingMutations.md @@ -12,19 +12,16 @@ FatQueries in Relay Classic mutations was a concept that was confusing for a num Example of existing fat query: ```javascript - RelayClassic.QL` fragment on MarkReadNotificationResponsePayload @relay(pattern: true) { notification } `; - ``` Example of converted mutation query: ```javascript - graphql` mutation MarkReadNotificationMutation( $input: MarkReadNotificationData! @@ -37,7 +34,6 @@ graphql` } } `; - ``` ## Migrating Configs @@ -67,7 +63,6 @@ This is no longer needed in Compatibility Mode for neither environments. Simply Take this example of a simple mutation in Relay Classic: ```javascript - class LikeStoryMutation extends RelayClassic.Mutation { getMutation() { return RelayClassic.QL`mutation {likeStory}`; @@ -106,7 +101,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { `, }; } - ``` ### Converting `getMutation()` and `getFatQuery()` @@ -114,7 +108,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { We combine these two into a regular GraphQL mutation, which list out specific fields that needs to be updated. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story(data: $input) { @@ -126,7 +119,6 @@ const mutation = graphql` } } `; - ``` ### Converting `getConfigs()` @@ -138,13 +130,11 @@ As specified above, `FIELDS_CHANGE` configs can be omitted. To convert `getVariables()`, we take the return value from the original function and wrap it in an object that contains a property that matches the variable name for the mutation. In this case, the mutation has a `input` variable that is of type `LikeStoryData`. ```javascript - const variables = { input: { storyID: args.storyID } } - ``` ### Final Result @@ -152,7 +142,6 @@ const variables = { As you can see, our resulting mutation is a lot simpler and more like regular GraphQL than the Relay Classic version we started out with. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story { @@ -178,7 +167,6 @@ function commit(environment: CompatEnvironment, args) { variables, }); } - ``` See [Mutation](./mutations) for additional options on `commitMutation` for more complex mutations. diff --git a/website/versioned_docs/version-v8.0.0/Modern-FragmentContainer.md b/website/versioned_docs/version-v8.0.0/Modern-FragmentContainer.md index 423f446cbb054..6a40bbcfb5d0a 100644 --- a/website/versioned_docs/version-v8.0.0/Modern-FragmentContainer.md +++ b/website/versioned_docs/version-v8.0.0/Modern-FragmentContainer.md @@ -17,12 +17,10 @@ Table of Contents: `createFragmentContainer` has the following signature: ```javascript - createFragmentContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, ): ReactComponentClass; - ``` ### Arguments @@ -43,7 +41,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -58,7 +55,6 @@ To start, let's build the plain React version of a hypothetical `` c Here's a basic implementation of `` that ignores styling in order to highlight the functionality: ```javascript - // TodoItem.js class TodoItem extends React.Component { render() { @@ -78,7 +74,6 @@ class TodoItem extends React.Component { ); } } - ``` ### Data Dependencies With GraphQL @@ -86,7 +81,6 @@ class TodoItem extends React.Component { In Relay, data dependencies are described using [GraphQL](https://github.com/facebook/graphql). For ``, the dependency can be expressed as follows. Note that this exactly matches the shape that the component expected for the `item` prop. ```javascript - graphql` # This fragment only applies to objects of type 'Todo'. fragment TodoItem_item on Todo { @@ -102,7 +96,6 @@ graphql` Given the plain React component and a GraphQL fragment, we can now define a Fragment Container to specify this component's data requirements. Let's look at the code first and then see what's happening: ```javascript - // TodoItem.js import {createFragmentContainer, graphql} from 'react-relay'; @@ -120,7 +113,6 @@ export default createFragmentContainer(TodoItem, { } `, }); - ``` ## Container Composition @@ -134,7 +126,6 @@ Let's explore how this works via a `` component that composes the `< View composition is _exactly_ what you're used to — Relay containers are just standard React components. Here's the `` component: ```javascript - class TodoList extends React.Component { render() { // Expects a `list` with a string `title`, as well as the information @@ -151,7 +142,6 @@ class TodoList extends React.Component { ); } } - ``` ### Composing Fragments @@ -159,7 +149,6 @@ class TodoList extends React.Component { Fragment composition works similarly — a parent container's fragment composes the fragment for each of its children. In this case, `` needs to fetch information about the `Todo`s that are required by ``. ```javascript - class TodoList extends React.Component // as above export default createFragmentContainer(TodoList, { @@ -176,7 +165,6 @@ export default createFragmentContainer(TodoList, { } `, }); - ``` Note that when composing fragments, the type of the composed fragment must match the field on the parent in which it is embedded. For example, it wouldn't make sense to embed a fragment of type `Story` into a parent's field of type `User`. Relay and GraphQL will provide helpful error messages if you get this wrong (and if they aren't helpful, let us know!). @@ -190,7 +178,6 @@ When defining a fragment, you can use the [`@argumentDefinitions`](./graphql-in- For example, let's redefine our `TodoList_list` fragment to take some arguments using `@argumentDefinitions`: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -200,7 +187,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` Any arguments defined inside `@argumentDefinitions` will be local variables available inside the fragment's scope. However, a fragment can also reference global variables that were defined in the root query. @@ -212,11 +198,9 @@ In order to pass arguments to a fragment that has `@argumentDefinitions`, you ne Following our `TodoList_list` example, we would pass arguments to the fragment like so: ```graphql - query TodoListQuery($count: Int, $userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` ## Rendering Containers diff --git a/website/versioned_docs/version-v8.0.0/Modern-GraphQLInRelay.md b/website/versioned_docs/version-v8.0.0/Modern-GraphQLInRelay.md index ef06043a7d364..9fc598b6949fe 100644 --- a/website/versioned_docs/version-v8.0.0/Modern-GraphQLInRelay.md +++ b/website/versioned_docs/version-v8.0.0/Modern-GraphQLInRelay.md @@ -14,7 +14,6 @@ Table of Contents: The `graphql` template tag provided by Relay serves as the mechanism to write queries, fragments, mutations or subscriptions in the [GraphQL](http://graphql.org/learn/) language. For example: ```javascript - import {graphql} from 'react-relay'; graphql` @@ -24,7 +23,6 @@ graphql` } } `; - ``` The result of using the `graphql` template tag is a `GraphQLTaggedNode`; a runtime representation of the GraphQL document which can be used to define [Query Renderers](./query-renderer), [Fragment Containers](./fragment-container), [Refetch Containers](./refetch-container), [Pagination Containers](./pagination-container), etc. @@ -42,11 +40,9 @@ Relay uses directives to add additional information to GraphQL documents, which `@arguments` is a directive used to pass arguments to a fragment that was defined using [`@argumentDefinitions`](#argumentdefinitions). For example: ```graphql - query TodoListQuery($userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -56,7 +52,6 @@ See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fr `@argumentDefinitions` is a directive used to specify arguments taken by a fragment. For example: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -66,7 +61,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -80,7 +74,6 @@ When using the [Pagination Container](./pagination-container), Relay expects con When defining a fragment for use with a Fragment container, you can use the `@relay(plural: true)` directive to indicate that container expects the prop for that fragment to be a list of items instead of a single item. A query or parent that spreads a `@relay(plural: true)` fragment should do so within a plural field (ie a field backed by a [GraphQL list](http://graphql.org/learn/schema/#lists-and-non-null). For example: ```javascript - // Plural fragment definition graphql` fragment TodoItems_items on TodoItem @relay(plural: true) { @@ -95,7 +88,6 @@ fragment TodoApp_app on App { ...TodoItem_items } } - ``` ### `@inline` @@ -107,7 +99,6 @@ Non-React functions can also take advantage of data masking. A fragment can be d In the example below, the function `processItemData` is called from a React component. It requires an item object with a specific set of fields. All React components that use this function should spread the `processItemData_item` fragment to ensure all of the correct item data is loaded for this function. ```javascript - import {graphql, readInlineData} from 'react-relay'; // non-React function called from React @@ -127,11 +118,9 @@ function processItemData(itemRef) { creatorName: item.creator.name }); } - ``` ```javascript - // React Component function MyComponent({item}) { function handleClick() { @@ -151,7 +140,6 @@ export default createFragmentContainer(MyComponent, { } ` }); - ``` ### `@relay(mask: Boolean)` @@ -169,7 +157,6 @@ Keep in mind that it is typically considered an **anti-pattern** to create a sin In the example below, the `user` prop will include the data for `id` and `name` fields wherever `...Component_internUser` is included, instead of Relay's normal behavior to mask those fields: ```javascript - graphql` fragment Component_internUser on InternUser @relay(mask: false) { id @@ -197,7 +184,6 @@ export default createFragmentContainer( } `, ); - ``` ## Relay Compiler @@ -207,7 +193,6 @@ Relay uses the Relay Compiler to convert [`graphql`](#graphql) literals into gen A query like the following: ```javascript - graphql` fragment MyComponent on Type { field @@ -228,12 +213,10 @@ Relay Compiler supports the use of **persisted queries**, in which each version Persisted queries can be enabled by instructing Relay Compiler to emit metadata about each query, mutation, and subscription into a JSON file. The generated file will contain a mapping of query identifiers to query text, which you can then save to your server. To enable persisted queries, use the `--persist-output` flag to the compiler: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` Relay Compiler will then create the id => query text mapping in the path you specify. You can then use this complete @@ -250,7 +233,6 @@ See our relay-compiler section in our [Installation and Setup guide](./installat To use the Relay Compiler, you need either a .graphql or .json GraphQL schema file, describing your GraphQL server's API. Typically these files are local representations of a server source of truth and are not edited directly. For example, we might have a `schema.graphql` like: ```graphql - schema { query: Root } @@ -268,7 +250,6 @@ type WordDefinition { text: String image: String } - ``` ### Source files @@ -284,7 +265,6 @@ For example, given the two files: - `src/Components/DictionaryComponent.js` ```javascript - const DictionaryWordFragment = graphql` fragment DictionaryComponent_word on Word { id @@ -306,7 +286,6 @@ For example, given the two files: - `src/Queries/DictionaryQuery.js` ```javascript - const DictionaryQuery = graphql` query DictionaryQuery { dictionary { @@ -330,9 +309,7 @@ Typically you will not need to import your generated definitions. The [Relay Bab However the Relay Compiler also automatically generates [Flow](https://flow.org) types as [type comments](https://flow.org/en/docs/types/comments/). For example, you can import the generated Flow types like so: ```javascript - import type {DictionaryComponent_word} from './__generated__/DictionaryComponent_word.graphql'; - ``` ### Client schema extensions @@ -342,7 +319,6 @@ The Relay Compiler fully supports client-side schema extensions, which allows yo For example, assuming the server schema `./schema.graphql`: ```graphql - schema { query: Root } @@ -350,28 +326,23 @@ schema { type Root { title: String! } - ``` We can create a `./src/clientSchema.graphql` and define a new type called `Setting`: ```graphql - type Setting { name: String! active: Boolean! } - ``` We can then extend existing server types in the client schema `./src/clientSchema.graphql` with our new `Setting` type, like so: ```graphql - extend type Root { settings: [Setting] } - ``` Any fields specified in the client schema, can be fetched from the [Relay Store](./relay-store), by selecting it in a query or fragment. diff --git a/website/versioned_docs/version-v8.0.0/Modern-LocalStateManagement.md b/website/versioned_docs/version-v8.0.0/Modern-LocalStateManagement.md index 5e0bdde30237a..c6e75a4e6fbf0 100644 --- a/website/versioned_docs/version-v8.0.0/Modern-LocalStateManagement.md +++ b/website/versioned_docs/version-v8.0.0/Modern-LocalStateManagement.md @@ -24,23 +24,19 @@ It can even be used to extend an existing server schema. For example, we can create a new type called `Note`: ```graphql - type Note { ID: ID! title: String body: String } - ``` And then extend the server schema type `User`, with a list of `Note`, called `notes`. ```graphql - extend type User { notes: [Note] } - ``` ## Querying local state @@ -51,7 +47,6 @@ The field can be from the server schema, or it can be schema agnostic, like an i Here, we use a [QueryRenderer](./query-renderer) to get the current `User` via the `viewer` field, along with their id, name and the local list of notes. ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -97,7 +92,6 @@ const Example = (props) => { /> ); } - ``` ## Mutating local state @@ -111,7 +105,6 @@ To build upon the previous example, let's try creating, updating and deleting a ### Create ```javascript - import {commitLocalUpdate} from 'react-relay'; let tempID = 0; @@ -131,7 +124,6 @@ function createUserNote() { user.setLinkedRecords([...userNoteRecords, newNoteRecord], 'notes'); }); } - ``` Note that since this record will be rendered by the `ExampleQuery` in our `QueryRenderer`, the QueryRenderer will automatically retain this data so it isn't garbage collected. @@ -139,20 +131,17 @@ Note that since this record will be rendered by the `ExampleQuery` in our `Query If no component is rendering the local data and you want to manually retain it, you can do so by calling `environment.retain()`: ```javascript - // Tell Relay to retain the record so it isn't garbage collected environment.retain({ dataID, variables: {}, node: { selections: [] } }); - ``` ### Update ```javascript - import {commitLocalUpdate} from 'react-relay'; function updateUserNote(dataID, body, title) { @@ -163,13 +152,11 @@ function updateUserNote(dataID, body, title) { note.setValue(title, 'title') }); } - ``` ### Delete ```javascript - import {commitLocalUpdate} from 'react-relay'; function deleteUserNote(dataID) { @@ -187,7 +174,6 @@ function deleteUserNote(dataID) { user.setLinkedRecords(newUserNoteRecords, 'notes'); }); } - ``` ## Initial local state @@ -196,7 +182,6 @@ All new client-side schema fields default to `undefined` value. Often however, y You can use an updater function via `commitLocalUpdate` to prime local state. ```javascript - import {commitLocalUpdate} from 'react-relay'; commitLocalUpdate(environment, store => { @@ -205,5 +190,4 @@ commitLocalUpdate(environment, store => { // initialize user notes to an empty array. user.setLinkedRecords([], 'notes'); }); - ``` diff --git a/website/versioned_docs/version-v8.0.0/Modern-MigrationSetup.md b/website/versioned_docs/version-v8.0.0/Modern-MigrationSetup.md index 66f1145357e25..a89c0e178e0e5 100644 --- a/website/versioned_docs/version-v8.0.0/Modern-MigrationSetup.md +++ b/website/versioned_docs/version-v8.0.0/Modern-MigrationSetup.md @@ -13,13 +13,11 @@ With some additional configuration, the `"relay"` babel plugin can also translat Relay Classic `Relay.QL` literals. Most importantly, include a reference to your GraphQL Schema as either a json file or graphql schema file. ```javascript - { "plugins": [ ["relay", {"schema": "path/schema.graphql"}] ] } - ``` ## Set up babel-plugin-relay for "[compatibility mode](./relay-compat)" @@ -29,13 +27,11 @@ literals can be translated to be usable by _both_ runtimes if configured to use compatibility mode: ```javascript - { "plugins": [ ["relay", {"compat": true, "schema": "path/schema.graphql"}] ] } - ``` ## Additional Options @@ -47,7 +43,6 @@ thrown at runtime. When compiling code for production deployment, the plugin can be configured to immediately throw upon encountering a validation problem. The plugin can be further customized for different environments with the following options: ```javascript - { "plugins": [ ["relay", { @@ -56,5 +51,4 @@ When compiling code for production deployment, the plugin can be configured to i }] ] } - ``` diff --git a/website/versioned_docs/version-v8.0.0/Modern-Mutations.md b/website/versioned_docs/version-v8.0.0/Modern-Mutations.md index a25e3f1cc7501..9652daaa656f1 100644 --- a/website/versioned_docs/version-v8.0.0/Modern-Mutations.md +++ b/website/versioned_docs/version-v8.0.0/Modern-Mutations.md @@ -17,7 +17,6 @@ Table of Contents: Use `commitMutation` to create and execute mutations. `commitMutation` has the following signature: ```javascript - commitMutation( environment: Environment, config: { @@ -31,7 +30,6 @@ commitMutation( configs?: Array, }, ); - ``` ### Arguments @@ -58,7 +56,6 @@ commitMutation( Example of a simple mutation: ```javascript - import {commitMutation, graphql} from 'react-relay'; const mutation = graphql` @@ -90,7 +87,6 @@ function markNotificationAsRead(environment, storyID) { }, ); } - ``` ## Optimistic Updates @@ -98,7 +94,6 @@ function markNotificationAsRead(environment, storyID) { To improve perceived responsiveness, you may wish to perform an "optimistic update", in which the client immediately updates to reflect the anticipated new value even before the response from the server has come back. The simplest way to do this is by providing an `optimisticResponse` and adding it to the `config` that we pass into `commitMutation`: ```javascript - const mutation = graphql` mutation MarkReadNotificationMutation( $storyID: ID! @@ -127,7 +122,6 @@ commitMutation( variables, }, ); - ``` Another way to enable optimistic updates is via the `optimisticUpdater`, which can be used for more complicated update scenarios. Using `optimisticUpdater` is covered in the section [below](#using-updater-and-optimisticupdater). @@ -149,7 +143,6 @@ Given a deletedIDFieldName, Relay will remove the node(s) from the store. #### Example ```javascript - const mutation = graphql` mutation DestroyShipMutation($target: ID!) { destroyShip(target: $target) { @@ -167,7 +160,6 @@ const configs = [{ type: 'NODE_DELETE', deletedIDFieldName: 'destroyedShipId', }]; - ``` ### RANGE_ADD @@ -187,7 +179,6 @@ Given a parent, information about the connection, and the name of the newly crea #### Example ```javascript - const mutation = graphql` mutation AddShipMutation($factionID: ID!, $name: String!) { addShip(factionID: $factionID, name: $name) { @@ -218,7 +209,6 @@ function commit(environment, factionID, name) { }], }); } - ``` ### RANGE_DELETE @@ -240,7 +230,6 @@ from the connection but leave the associated record(s) in the store. #### Example ```javascript - const mutation = graphql` mutation RemoveTagMutation($todoID: ID!, $tagID: ID!) { removeTag(todo: $todoID, tag: $tagID) { @@ -267,7 +256,6 @@ function commit(environment, todoID, tagID) { }], }); } - ``` ## Using updater and optimisticUpdater @@ -285,7 +273,6 @@ When you provide these functions, this is roughly what happens during the mutati Here are a quick example of adding a todo item to a Todo list using this [example schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L36): ```javascript - // AddTodoMutation.js import {commitMutation, graphql} from 'react-relay'; import {ConnectionHandler} from 'relay-runtime'; @@ -369,7 +356,6 @@ function commit(environment, text, user) { }, }); } - ``` For details on how to interact with the Relay Store, please refer to our Relay Store [docs](./relay-store). diff --git a/website/versioned_docs/version-v8.0.0/Modern-NetworkLayer.md b/website/versioned_docs/version-v8.0.0/Modern-NetworkLayer.md index 9dddd36d6c235..c9e069b812b01 100644 --- a/website/versioned_docs/version-v8.0.0/Modern-NetworkLayer.md +++ b/website/versioned_docs/version-v8.0.0/Modern-NetworkLayer.md @@ -8,7 +8,6 @@ In order to know how to access your GraphQL server, Relay Modern requires develo Currently the easiest way to create a network layer is via a helper from the `relay-runtime` package: ```javascript - import { Environment, Network, @@ -50,7 +49,6 @@ const environment = new Environment({ }); export default environment; - ``` Note that this is a basic example to help you get started. This example could be extended with additional features such as request/response caching (enabled e.g. when `cacheConfig.force` is false) and uploading form data for mutations (the `uploadables` parameter). @@ -62,7 +60,6 @@ Relay modern makes no assumptions about what to cache and will garbage collect a You have to implement your own cache strategy. A simple solution is to use `QueryResponseCache` (an in-memory cache): ```javascript - import { Environment, Network, @@ -126,7 +123,6 @@ const environment = new Environment({ }); export default environment; - ``` ## Custom open-source implementations diff --git a/website/versioned_docs/version-v8.0.0/Modern-PaginationContainer.md b/website/versioned_docs/version-v8.0.0/Modern-PaginationContainer.md index 6ac3aac8cfb8e..57980d553af9b 100644 --- a/website/versioned_docs/version-v8.0.0/Modern-PaginationContainer.md +++ b/website/versioned_docs/version-v8.0.0/Modern-PaginationContainer.md @@ -24,7 +24,6 @@ However, when [specifying connection fragments](#createpaginationcontainer) for The purpose of the `@connection` directive is to allow Relay to uniquely identify different connections under a parent type. The `@connection` directive takes 2 arguments that help identify the connection: ```graphql - @connection(key: String!, filters: [String]) ``` @@ -37,7 +36,6 @@ The purpose of the `@connection` directive is to allow Relay to uniquely identif Specifying just the `key`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and the value of `$orderBy` (given that no `filters` were provided) @@ -53,13 +51,11 @@ fragment Feed_user on User { } } } - ``` Specifying `key` and `filters`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and /only/ the value of `$searchTerm`, i.e. @@ -77,7 +73,6 @@ fragment Feed_user on User { } } } - ``` ## `createPaginationContainer` @@ -85,7 +80,6 @@ fragment Feed_user on User { `createPaginationContainer` has the following signature: ```javascript - createPaginationContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, @@ -113,7 +107,6 @@ type ConnectionData = { startCursor: ?string, }, }; - ``` ### Arguments @@ -134,7 +127,6 @@ type ConnectionData = { The Component resulting from `createPaginationContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -145,7 +137,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -160,7 +151,6 @@ type Props = { `hasMore` is a function available on the `relay` [prop](#available-props). This function indicates whether there are more pages to fetch from the server or not. ```javascript - hasMore: () => boolean, ``` @@ -170,7 +160,6 @@ hasMore: () => boolean, `isLoading` is a function available on the `relay` [prop](#available-props). This function indicates if a previous call to [`loadMore()`](#loadmore) is still pending. This is convenient for avoiding duplicate load calls. ```javascript - isLoading: () => boolean, ``` @@ -180,7 +169,6 @@ isLoading: () => boolean, `loadMore` is a function available on the `relay` [prop](#available-props). You can call `loadMore()` to fetch more items from the server based on the `connectionConfig` provided to the container. This will return null if there are no more items to fetch, otherwise it will fetch more items and return a Disposable that can be used to cancel the fetch. ```javascript - loadMore( pageSize: number, callback: ?(error: ?Error) => void, @@ -201,7 +189,6 @@ loadMore( `refetchConnection` is a function available on the `relay` [prop](#available-props). You can call `refetchConnection` to restart pagination on a connection from scratch, with optionally a completely new set of variables to pass to the pagination `query`. This is useful for example if you are paginating over a collection based on a userID and the userID changes, you'd want to start paginating over the new collection for the new user. ```javascript - refetchConnection:( totalCount: number, callback: (error: ?Error) => void, @@ -219,7 +206,6 @@ refetchConnection:( ## Pagination Example ```javascript - // Feed.js import {createPaginationContainer, graphql} from 'react-relay'; @@ -314,5 +300,4 @@ module.exports = createPaginationContainer( ` } ); - ``` diff --git a/website/versioned_docs/version-v8.0.0/Modern-PersistedQueries.md b/website/versioned_docs/version-v8.0.0/Modern-PersistedQueries.md index 137cc2e23220c..ec03b69ba09c3 100644 --- a/website/versioned_docs/version-v8.0.0/Modern-PersistedQueries.md +++ b/website/versioned_docs/version-v8.0.0/Modern-PersistedQueries.md @@ -17,12 +17,10 @@ The relay compiler supports persisted queries which is useful because: In your `npm` script in `package.json`, run the relay compiler using the `--persist-output` flag: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` The `--persist-ouput` flag does 3 things: @@ -31,8 +29,7 @@ The `--persist-ouput` flag does 3 things: For example without `--persist-output`, a generated `ConcreteRequest` might look like below: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -49,8 +46,7 @@ The `--persist-ouput` flag does 3 things: With `--persist-output ` this becomes: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -68,12 +64,10 @@ The `--persist-ouput` flag does 3 things: 2. It generates a JSON file at the `` you specify containing a mapping from query ids to the corresponding operation texts. -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./src/queryMaps/queryMap.json" } - ``` The example above writes the complete query map file to `./src/queryMaps/queryMap.json`. You need to ensure all the directories @@ -83,8 +77,7 @@ leading to the `queryMap.json` file exist. You'll need to modify your network layer fetch implementation to pass a documentId parameter in the POST body instead of a query parameter: -```js - +```javascript function fetchQuery(operation, variables,) { return fetch('/graphql', { method: 'POST', @@ -100,7 +93,6 @@ function fetchQuery(operation, variables,) { return response.json(); }); } - ``` ## Executing Persisted Queries on the Server @@ -116,13 +108,11 @@ the query map file in a common location accessible to both the client and the se For applications where the client and server projects are separate, one option is to have an additional npm run script to push the query map at compile time to a location accessible by your server: -```js - +```javascript "scripts": { "push-queries": "node ./pushQueries.js", "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-ouput && npm run push-queries" } - ``` Some possibilities of what you can do in `./pushQueries.js`: @@ -146,8 +136,7 @@ database technologies you use, so we'll just cover the most common and basic exa If you use `express-graphql` and have access to the query map file, you can import the `--persist-output` JSON file directly and perform the matching using the `matchQueryMiddleware` from [relay-compiler-plus](https://github.com/yusinto/relay-compiler-plus). -```js - +```javascript import Express from 'express'; import expressGraphql from 'express-graphql'; import {matchQueryMiddleware} from 'relay-compiler-plus'; @@ -158,7 +147,6 @@ const app = Express(); app.use('/graphql', matchQueryMiddleware(queryMapJson), expressGraphql({schema})); - ``` ## Using `--persist-output` and `--watch` diff --git a/website/versioned_docs/version-v8.0.0/Modern-QueryRenderer.md b/website/versioned_docs/version-v8.0.0/Modern-QueryRenderer.md index cf6c37f3d9a4d..b621ef9986bf1 100644 --- a/website/versioned_docs/version-v8.0.0/Modern-QueryRenderer.md +++ b/website/versioned_docs/version-v8.0.0/Modern-QueryRenderer.md @@ -24,7 +24,6 @@ However, a `QueryRenderer` will not start loading its data until it is mounted, ## Example ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -56,5 +55,4 @@ const Example = (props) => { /> ); } - ``` diff --git a/website/versioned_docs/version-v8.0.0/Modern-RefetchContainer.md b/website/versioned_docs/version-v8.0.0/Modern-RefetchContainer.md index 7ce0d14e45417..51c2c44db8941 100644 --- a/website/versioned_docs/version-v8.0.0/Modern-RefetchContainer.md +++ b/website/versioned_docs/version-v8.0.0/Modern-RefetchContainer.md @@ -16,13 +16,11 @@ Table of Contents: `createRefetchContainer` has the following signature: ```javascript - createRefetchContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, refetchQuery: GraphQLTaggedNode, ): ReactComponentClass; - ``` ### Arguments @@ -37,7 +35,6 @@ createRefetchContainer( The Component resulting from `createRefetchContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -45,7 +42,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -61,7 +57,6 @@ type Props = { `refetch` has the following signature: ```javascript - type RefetchOptions = { force?: boolean, }; @@ -102,7 +97,6 @@ Returns a `Disposable` on which you could call `dispose()` to cancel the refetch In this simple example, let's assume we want to fetch the latest data for a `TodoItem` from the server: ```javascript - // TodoItem.js import {createRefetchContainer, graphql} from 'react-relay'; @@ -148,7 +142,6 @@ export default createRefetchContainer( } ` ); - ``` ### Loading more data @@ -156,7 +149,6 @@ export default createRefetchContainer( In this example we are using a Refetch Container to fetch more stories in a story feed component. ```javascript - import {createRefetchContainer, graphql} from 'react-relay'; class FeedStories extends React.Component { @@ -212,5 +204,4 @@ export default createRefetchContainer( } `, ); - ``` diff --git a/website/versioned_docs/version-v8.0.0/Modern-RelayCompat.md b/website/versioned_docs/version-v8.0.0/Modern-RelayCompat.md index 36632d3a8f1a1..f47dbd845ba3e 100644 --- a/website/versioned_docs/version-v8.0.0/Modern-RelayCompat.md +++ b/website/versioned_docs/version-v8.0.0/Modern-RelayCompat.md @@ -31,7 +31,6 @@ Relay Modern. The components using Relay Compat can be referred to by both other Relay Modern and Relay Classic components. ```javascript - const {createFragmentContainer, graphql} = require('react-relay/compat'); class TodoItem extends React.Component { @@ -47,5 +46,4 @@ module.exports = createFragmentContainer(TodoItem, graphql` isComplete } `); - ``` diff --git a/website/versioned_docs/version-v8.0.0/Modern-RelayEnvironment.md b/website/versioned_docs/version-v8.0.0/Modern-RelayEnvironment.md index 27d90b2fc4fe1..99e728bce740d 100644 --- a/website/versioned_docs/version-v8.0.0/Modern-RelayEnvironment.md +++ b/website/versioned_docs/version-v8.0.0/Modern-RelayEnvironment.md @@ -12,7 +12,6 @@ Most applications will create a single Environment instance and use it throughou To create an environment instance in Relay Modern, use the `RelayModernEnvironment` class: ```javascript - const { Environment, Network, @@ -30,7 +29,6 @@ const environment = new Environment({ network, store, }); - ``` For more details on creating a Network, see the [NetworkLayer guide](./network-layer). @@ -44,7 +42,6 @@ The example above did not configure a `handlerProvider`, which means that a defa If you wish to provide your own `handlerProvider`, you can do so: ```javascript - const { ConnectionHandler, } = require('relay-runtime'); @@ -58,5 +55,4 @@ function handlerProvider(handle) { `handlerProvider: No handler provided for ${handle}` ); } - ``` diff --git a/website/versioned_docs/version-v8.0.0/Modern-RelayStore.md b/website/versioned_docs/version-v8.0.0/Modern-RelayStore.md index 3457960655342..3d552f6035f50 100644 --- a/website/versioned_docs/version-v8.0.0/Modern-RelayStore.md +++ b/website/versioned_docs/version-v8.0.0/Modern-RelayStore.md @@ -16,7 +16,6 @@ Table of Contents: The `RecordSourceSelectorProxy` is the type of the `store` that [`updater` functions](./mutations#using-updater-and-optimisticupdater) receive as an argument. The following is the `RecordSourceSelectorProxy` interface: ```javascript - interface RecordSourceSelectorProxy { create(dataID: string, typeName: string): RecordProxy; delete(dataID: string): void; @@ -26,7 +25,6 @@ interface RecordSourceSelectorProxy { getPluralRootField(fieldName: string): ?Array; invalidateStore(): void; } - ``` ### `create(dataID: string, typeName: string): RecordProxy` @@ -36,9 +34,7 @@ Creates a new record in the store given a `dataID` and the `typeName` as defined #### Example ```javascript - const record = store.create(dataID, 'Todo'); - ``` ### `delete(dataID: string): void` @@ -48,9 +44,7 @@ Deletes a record from the store given its `dataID`. #### Example ```javascript - store.delete(dataID); - ``` ### `get(dataID: string): ?RecordProxy` @@ -60,9 +54,7 @@ Retrieves a record from the store given its `dataID`. Returns a [`RecordProxy`]( #### Example ```javascript - const record = store.get(dataID); - ``` ### `getRoot(): RecordProxy` @@ -74,20 +66,16 @@ Returns the [`RecordProxy`](#recordproxy) representing the root of the GraphQL d Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - // Represents root query const root = store.getRoot(); - ``` ### `getRootField(fieldName: string): ?RecordProxy` @@ -99,19 +87,15 @@ Retrieves a root field from the store given the `fieldName`, as defined by the G Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - const viewer = store.getRootField('viewer'); - ``` ### `getPluralRootField(fieldName: string): ?Array` @@ -123,19 +107,15 @@ Retrieves a root field that represents a collection from the store given the `fi Given the GraphQL document: ```graphql - nodes(first: 10) { # ... } - ``` Usage: ```javascript - const nodes = store.getPluralRootField('nodes'); - ``` ### `invalidateStore(): void` @@ -145,15 +125,12 @@ Globally invalidates the Relay store. This will cause any data that was written #### Example ```javascript - store.invalidateStore(); - ``` After global invalidation, any query that is checked before refetching it will be considered stale: ```javascript - environment.check(query) === 'stale' ``` @@ -163,7 +140,6 @@ environment.check(query) === 'stale' The `RecordProxy` serves as an interface to mutate records: ```javascript - interface RecordProxy { copyFieldsFrom(sourceRecord: RecordProxy): void; getDataID(): string; @@ -189,7 +165,6 @@ interface RecordProxy { setValue(value: mixed, name: string, arguments?: ?Object): RecordProxy; invalidateRecord(): void; } - ``` ### `getDataID(): string` @@ -199,9 +174,7 @@ Returns the dataID of the current record. #### Example ```javascript - const id = record.getDataID(); - ``` ### `getType(): string` @@ -211,7 +184,6 @@ Gets the type of the current record, as defined by the GraphQL schema. #### Example ```javascript - const type = user.getType(); // User ``` @@ -225,20 +197,16 @@ Gets the value of a field in the current record given the field name. Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - const name = viewer.getValue('name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. @@ -248,20 +216,16 @@ Optionally, if the field takes arguments, you can pass a bag of `variables`. Given the GraphQL document: ```graphql - viewer { id name(arg: $arg) } - ``` Usage: ```javascript - const name = viewer.getValue('name', {arg: 'value'}); - ``` ### `getLinkedRecord(name: string, arguments?: ?Object): ?RecordProxy` @@ -273,23 +237,19 @@ Retrieves a record associated with the current record given the field name, as d Given the GraphQL document: ```graphql - rootField { viewer { id name } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -299,22 +259,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { viewer(arg: $arg) { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {arg: 'value'}); - ``` ### `getLinkedRecords(name: string, arguments?: ?Object): ?Array` @@ -326,22 +282,18 @@ Retrieves the set of records associated with the current record given the field Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const nodes = rootField.getLinkedRecords('nodes'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -351,22 +303,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { nodes(first: $count) { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {count: 10}); - ``` ### `getOrCreateLinkedRecord(name: string, typeName: string, arguments?: ?Object)` @@ -378,19 +326,16 @@ Retrieves the a record associated with the current record given the field name, Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = rootField.getOrCreateLinkedRecord('viewer', 'User'); // Will create if it doesn't exist @@ -405,28 +350,22 @@ Mutates the current record by setting a new value on the specified field. Return Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - viewer.setValue('New Name', 'name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. ```javascript - viewer.setValue('New Name', 'name', {arg: 'value'}); - ``` ### `copyFieldsFrom(sourceRecord: RecordProxy): void` @@ -436,7 +375,6 @@ Mutates the current record by copying the fields over from the passed in record #### Example ```javascript - const record = store.get(id1); const otherRecord = store.get(id2); record.copyFieldsFrom(otherRecord); // Mutates `record` @@ -452,19 +390,16 @@ Mutates the current record by setting a new linked record on the given the field Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = store.create(/* ... */)'' rootField.setLinkedRecord(newViewer, 'viewer'); // @@ -482,19 +417,16 @@ Mutates the current record by setting a new set of linked records on the given t Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newNode = store.create(/* ... */); const newNodes = [...rootField.getLinkedRecords('nodes'), newNode]; @@ -511,16 +443,13 @@ Invalidates the record. This will cause any query that references this record to #### Example ```javascript - const record = store.get('4'); record.invalidateRecord(); - ``` After invalidating a record, any query that references the invalidated record and that is checked before refetching it will be considered stale: ```javascript - environment.check(query) === 'stale' ``` @@ -530,7 +459,6 @@ environment.check(query) === 'stale' `ConnectionHandler` is a utility module exposed by `relay-runtime` that aids in the manipulation of connections. `ConnectionHandler` exposes the following interface: ```javascript - interface ConnectionHandler { getConnection( record: RecordProxy, @@ -555,7 +483,6 @@ interface ConnectionHandler { ): void, deleteNode(connection: RecordProxy, nodeID: string): void } - ``` ### `getConnection(record: RecordProxy, key: string, filters?: ?Object)` @@ -565,7 +492,6 @@ Given a record and a connection key, and optionally a set of filters, `getConnec First, let's take a look at a plain connection: ```graphql - fragment FriendsFragment on User { friends(first: 10) { edges { @@ -575,26 +501,22 @@ fragment FriendsFragment on User { } } } - ``` Accessing a plain connection field like this is the same as other regular field: ```javascript - // The `friends` connection record can be accessed with: const user = store.get(userID); const friends = user && user.getLinkedRecord(user, 'friends'); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` In a [pagination container](./pagination-container), we usually annotate the actual connection field with `@connection` to tell Relay which part needs to be paginated: ```graphql - fragment FriendsFragment on User { friends(first: 10, orderby: "firstname") @connection( key: "FriendsFragment_friends", @@ -606,7 +528,6 @@ fragment FriendsFragment on User { } } } - ``` For connections like the above, `ConnectionHandler` helps us find the record: @@ -624,7 +545,6 @@ const friends = ConnectionHandler.getConnection( ); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` ### Edge creation and insertion @@ -654,7 +574,6 @@ ConnectionHandler.insertEdgeAfter(friends, edge); // No cursor provided, Insert the edge at the front: ConnectionHandler.insertEdgeBefore(friends, edge); - ``` ### `deleteNode(connection: RecordProxy, nodeID: string): void` @@ -668,5 +587,4 @@ Given a connection, deletes any edges whose id matches the given id. const user = store.get(userID); const friends = ConnectionHandler.getConnection(user, 'friends'); ConnectionHandler.deleteNode(friends, idToDelete); - ``` diff --git a/website/versioned_docs/version-v8.0.0/Modern-Subscriptions.md b/website/versioned_docs/version-v8.0.0/Modern-Subscriptions.md index 802f1d02b06de..bd1c5fe2f350c 100644 --- a/website/versioned_docs/version-v8.0.0/Modern-Subscriptions.md +++ b/website/versioned_docs/version-v8.0.0/Modern-Subscriptions.md @@ -6,7 +6,6 @@ original_id: subscriptions Relay exposes the following APIs to create subscriptions. ```javascript - const {requestSubscription} = require('react-relay'); type Variables = {[name: string]: any}; @@ -27,7 +26,6 @@ requestSubscription( configs?: Array, }, ) => Disposable; - ``` The function returns a `Disposable` on which you could call `dispose()` to cancel the refetch. @@ -53,7 +51,6 @@ appropriate when you are only changing the properties of existing records that can be identified by their `id`: ```javascript - const { requestSubscription, graphql, @@ -87,7 +84,6 @@ requestSubscription( onError: error => console.error(error), } ); - ``` # Updating the client on each response @@ -97,7 +93,6 @@ Relay's in-memory cache when each subscription response is received. To do so, pass an `updater` function: ```javascript - const {ConnectionHandler} = require('relay-runtime'); requestSubscription( @@ -123,5 +118,4 @@ requestSubscription( }, }, ); - ``` diff --git a/website/versioned_docs/version-v8.0.0/Modern-TestingRelayComponents.md b/website/versioned_docs/version-v8.0.0/Modern-TestingRelayComponents.md index 4e5cf9e61a922..2916a65f56e06 100644 --- a/website/versioned_docs/version-v8.0.0/Modern-TestingRelayComponents.md +++ b/website/versioned_docs/version-v8.0.0/Modern-TestingRelayComponents.md @@ -65,7 +65,6 @@ MockPayloadGenerator may drastically simplify the process of creating and mainta Example of a simple Mock Resolver: ```javascript - { ID() { // Return mock value for a scalar filed with type ID @@ -76,13 +75,11 @@ Example of a simple Mock Resolver: return "Lorem Ipsum" } } - ``` It is possible to define more resolvers for Object types ```javascript - { // This will be the default values for User object in the query response User() { @@ -95,7 +92,6 @@ It is possible to define more resolvers for Object types }; }, } - ``` ### Mock Resolver Context @@ -103,7 +99,6 @@ It is possible to define more resolvers for Object types The first argument of the MockResolver is the object that contains Mock Resolver Context. It is possible to return dynamic values from mock resolvers based on the context - for instance, name or alias of the field, a path in the selection, arguments, or parent type. ```javascript - { String(context) { if (context.name === 'zip') { @@ -117,7 +112,6 @@ The first argument of the MockResolver is the object that contains Mock Resolver } } } - ``` ### ID Generation @@ -125,14 +119,12 @@ The first argument of the MockResolver is the object that contains Mock Resolver The second argument of the Mock Resolver its a function that will generate a sequence of integers, useful to generate unique ids in the tests ```javascript - { // will generate strings "my-id-1", "my-id-2", etc. ID(_, generateId) { return `my-id-${generateId()}`; }, } - ``` ### @relay_test_operation @@ -142,7 +134,6 @@ Most of GraphQL type information for a specific field in the selection is not av Operation with the @relay_test_operation directive will have additional metadata that will contain GraphQL type info for fields in the operation's selection. And it will improve the quality of the generated data. You also will be able to define Mock resolvers for Scalar (not only ID and String) and Abstract types: ```javascript - { Float() { return 123.456; @@ -160,7 +151,6 @@ Operation with the @relay_test_operation directive will have additional metadata }; } } - ``` ## Examples @@ -170,7 +160,6 @@ Operation with the @relay_test_operation directive will have additional metadata Using `createMockEnvironment` and `MockPayloadGenerator` allows writing concise tests for components that are using Relay Containers and Renderers. Both those modules can be imported from `relay-test-utils` ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { @@ -223,7 +212,6 @@ test('Error State', () => { renderer.root.find(item => (item.props.testID = 'errorMessage')), ).toBeDefined(); }); - ``` ### Fragment Container Tests @@ -231,7 +219,6 @@ test('Error State', () => { Essentially, in the example above will `resolveMostRecentOperation` will generate data for all child fragment containers (pagination, refetch). But, usually the Root Components container may have many child fragment components and you may want to exercise a specific Fragment Container. The solution for that would be to wrap you fragment container with the QueryRenderer that renders a Query that's spreads fragments from you fragment container. ```javascript - test('Fragment Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -262,7 +249,6 @@ test('Fragment Container', () => { expect(renderer).toMatchSnapshot(); }); - ``` ### Pagination Container Test @@ -270,7 +256,6 @@ test('Fragment Container', () => { Essentially, tests for Pagination container are not different from Fragment Container tests. But we can do more here, we can actually see how the pagination works - we can assert the behavior of our components when performing pagination (load more, refetch). ```javascript - // Pagination Example test('Pagination Container', () => { const environment = createMockEnvironment(); @@ -344,7 +329,6 @@ test('Pagination Container', () => { We can use similar approach here with wrapping container with Query Renderer. And for the sake of completeness, we will add example here: ```javascript - test('Refetch Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -386,7 +370,6 @@ test('Refetch Container', () => { ); // expect(renderer).toMatchSnapshot(); }); - ``` ### Mutations @@ -394,7 +377,6 @@ test('Refetch Container', () => { Mutations itself are operations so we can test them independently (unit-test) for specific mutation, or in combination with the view from which this mutation is called. ```javascript - // Say, you have a mutation function function sendMutation(environment, onCompleted, onError, variables) commitMutation(environment, { @@ -417,7 +399,6 @@ test('it should send mutation', () => { ); expect(onCompleted).toBeCalled(); }); - ``` ### Subscription @@ -425,7 +406,6 @@ test('it should send mutation', () => { We can test subscription in a similar way we test mutations ```javascript - // Example subscribe function function subscribe(environment, onNext, onError, variables) requestSubscription(environment, { @@ -448,7 +428,6 @@ test('it should subscribe', () => { ); expect(onNext).toBeCalled(); }); - ``` ### Example with `queueOperationResolver` @@ -456,7 +435,6 @@ test('it should subscribe', () => { With `queueOpeararionResolver` it possible to define responses for operations that will be executed on the environment ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { diff --git a/website/versioned_docs/version-v8.0.0/Modern-TypeEmission.md b/website/versioned_docs/version-v8.0.0/Modern-TypeEmission.md index 63614b869a322..4ff63e4a7d81b 100644 --- a/website/versioned_docs/version-v8.0.0/Modern-TypeEmission.md +++ b/website/versioned_docs/version-v8.0.0/Modern-TypeEmission.md @@ -16,7 +16,6 @@ In this example the emitted type-information would require the variables object #### Flow ```javascript - /** * export type ExampleQueryVariables = {| * +artistID: string @@ -44,7 +43,6 @@ const variables: ExampleQueryVariables = { #### TypeScript ```javascript - /** * export type ExampleQueryVariables = { * readonly artistID: string @@ -79,7 +77,6 @@ In this example the emitted type-information describes the response data availab #### Flow ```javascript - /** * export type ExampleQueryResponse = {| * +artist: ?{| @@ -110,7 +107,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * export type ExampleQueryResponse = { * readonly artist?: { @@ -146,7 +142,6 @@ Similarly, in this example the emitted type-information describes the prop data #### Flow ```javascript - /** * export type ExampleFragment_artist = {| * +name: string @@ -172,7 +167,6 @@ export const ExampleFragment = createFragmentContainer( #### TypeScript ```javascript - /** * export type ExampleFragment_artist = { * readonly name: string @@ -206,7 +200,6 @@ Consider a component that composes the above fragment container example. In this #### Flow ```javascript - /** * import type { FragmentReference } from "relay-runtime"; * declare export opaque type ExampleFragment_artist$ref: FragmentReference; @@ -250,7 +243,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * declare const _ExampleFragment_artist$ref: unique symbol; * export type ExampleFragment_artist$ref = typeof _ExampleFragment_artist$ref; @@ -315,7 +307,6 @@ $ relay-compiler --artifactDirectory ./src/__generated__ […] ["relay", { "artifactDirectory": "./src/__generated__" }] ] } - ``` It is recommended to alias this directory in your module resolution configuration such that you don’t need to specify relative paths in your source files. This is what is also done in the above examples, where artifacts are imported from a `__generated__` alias, rather than relative paths like `../../../../__generated__`. diff --git a/website/versioned_docs/version-v8.0.0/Modern-UpgradingSetVariables.md b/website/versioned_docs/version-v8.0.0/Modern-UpgradingSetVariables.md index d5b086fafce20..ff73feec04f8b 100644 --- a/website/versioned_docs/version-v8.0.0/Modern-UpgradingSetVariables.md +++ b/website/versioned_docs/version-v8.0.0/Modern-UpgradingSetVariables.md @@ -36,7 +36,6 @@ fragment on User { # ... } } - ``` This should be upgraded to use a [`PaginationContainer`](./pagination-container). @@ -61,7 +60,6 @@ fragment on User { # ... } } - ``` This can be upgraded by using a [`RefetchContainer`](./refetch-container) which allows you to specify the exact query to use to fetch the new data. @@ -86,7 +84,6 @@ fragment on FeedbackTarget { # ... } } - ``` This can be upgraded by conditionally rendering a [`QueryRenderer`](./query-renderer) which will load the data once it is rendered. The code overhead of doing this is dramatically reduced with the new API. diff --git a/website/versioned_docs/version-v8.0.0/Modern-fetchQuery.md b/website/versioned_docs/version-v8.0.0/Modern-fetchQuery.md index 2e9461ad527bd..c1a06ab7d2493 100644 --- a/website/versioned_docs/version-v8.0.0/Modern-fetchQuery.md +++ b/website/versioned_docs/version-v8.0.0/Modern-fetchQuery.md @@ -6,7 +6,6 @@ original_id: fetch-query You can use the `fetchQuery` function to imperatively make GraphQL Requests. This is useful for cases where you want to make requests outside of React but still utilize the Relay store and network layer. ```javascript - import {fetchQuery, graphql} from 'relay-runtime'; const query = graphql` @@ -25,7 +24,6 @@ fetchQuery(environment, query, variables) .then(data => { // access the graphql response }); - ``` ## Arguments diff --git a/website/versioned_docs/version-v8.0.0/PrinciplesAndArchitecture-Compiler.md b/website/versioned_docs/version-v8.0.0/PrinciplesAndArchitecture-Compiler.md index c195491682b1f..fcd0490cb724f 100644 --- a/website/versioned_docs/version-v8.0.0/PrinciplesAndArchitecture-Compiler.md +++ b/website/versioned_docs/version-v8.0.0/PrinciplesAndArchitecture-Compiler.md @@ -74,7 +74,6 @@ foo { # type FooType foo { id } - ``` - `SkipRedundantNodeTransform`: A more advanced version of flattening, this eliminates more complex cases of field duplication such as when a field is fetched both unconditionally and conditionally, or is fetched by two different sub-fragments. For example: @@ -97,7 +96,6 @@ foo { id } } - ``` - `GenerateRequisiteFieldTransform`: This optional, Relay-specific transform inserts `id` fields for globally identifiable objects and `__typename` fields wherever the type cannot be statically determined (e.g. for unions). diff --git a/website/versioned_docs/version-v8.0.0/PrinciplesAndArchitecture-Runtime.md b/website/versioned_docs/version-v8.0.0/PrinciplesAndArchitecture-Runtime.md index 9491d290c146f..e9221631a701d 100644 --- a/website/versioned_docs/version-v8.0.0/PrinciplesAndArchitecture-Runtime.md +++ b/website/versioned_docs/version-v8.0.0/PrinciplesAndArchitecture-Runtime.md @@ -77,7 +77,6 @@ RecordSource { city: 'Seattle', } } - ``` [1] Note that GraphQL itself does not impose this constraint, and Relay Runtime may also be used for schemas that do not conform to it. For example, both systems can be used to query a single denormalized table. However, many of the features that Relay Runtime provides, such as caching and normalization, work best when the data is represented as a normalized graph with stable identities for discrete pieces of information. diff --git a/website/versioned_docs/version-v8.0.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md b/website/versioned_docs/version-v8.0.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md index a8842ae084922..9ff8a7840df90 100644 --- a/website/versioned_docs/version-v8.0.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md +++ b/website/versioned_docs/version-v8.0.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md @@ -12,7 +12,6 @@ In this article we'll explore what it means to build a GraphQL client framework Imagine we have a simple application that fetches a list of stories, and some details about each one. Here's how that might look in resource-oriented REST: ```javascript - // Fetch the list of story IDs but not their details: rest.get('/stories').then(stories => // This resolves to a list of items with linked resources: @@ -25,13 +24,11 @@ rest.get('/stories').then(stories => // `[ { id: "...", text: "..." } ]` console.log(stories); }); - ``` Note that this approach requires _n+1_ requests to the server: 1 to fetch the list, and _n_ to fetch each item. With GraphQL we can fetch the same data in a single network request to the server (without creating a custom endpoint that we'd then have to maintain): ```javascript - graphql.get(`query { stories { id, text } }`).then( stories => { // A list of story items: @@ -39,7 +36,6 @@ graphql.get(`query { stories { id, text } }`).then( console.log(stories); } ); - ``` So far we're just using GraphQL as a more efficient version of typical REST approaches. Note two important benefits in the GraphQL version: @@ -56,7 +52,6 @@ Repeatedly refetching information from the server can get quite slow. For exampl In a resource-oriented REST system, we can maintain a **response cache** based on URIs: ```javascript - var _cache = new Map(); rest.get = uri => { if (!_cache.has(uri)) { @@ -64,13 +59,11 @@ rest.get = uri => { } return _cache.get(uri); }; - ``` Response-caching can also be applied to GraphQL. A basic approach would work similarly to the REST version. The text of the query itself can be used as a cache key: ```javascript - var _cache = new Map(); graphql.get = queryText => { if (!_cache.has(queryText)) { @@ -78,7 +71,6 @@ graphql.get = queryText => { } return _cache.get(queryText); }; - ``` Now, requests for previously cached data can be answered immediately without making a network request. This is a practical approach to improving the perceived performance of an application. However, this method of caching can cause problems with data consistency. @@ -90,7 +82,6 @@ With GraphQL it is very common for the results of multiple queries to overlap. H ``` query { stories { id, text, likeCount } } - ``` and then later refetch one of the stories whose `likeCount` has since been incremented: @@ -98,7 +89,6 @@ and then later refetch one of the stories whose `likeCount` has since been incre ``` query { story(id: "123") { id, text, likeCount } } - ``` We'll now see different `likeCount`s depending on how the story is accessed. A view that uses the first query will see an outdated count, while a view using the second query will see the updated count. @@ -119,7 +109,6 @@ query { } } } - ``` And here's a possible response: @@ -134,13 +123,11 @@ query: { } } } - ``` Although the response is hierarchical, we'll cache it by flattening all the records. Here is an example of how Relay would cache this query response: ```javascript - Map { // `story(id: "1")` 1: Map { @@ -152,7 +139,6 @@ Map { name: 'Jan', }, }; - ``` This is only a simple example: in reality the cache must handle one-to-many associations and pagination (among other things). @@ -182,7 +168,6 @@ The first query was for a list of stories: ``` query { stories { id, text, likeCount } } - ``` With a normalized response cache, a record would be created for each story in the list. The `stories` field would store links to each of these records. @@ -192,7 +177,6 @@ The second query refetched the information for one of those stories: ``` query { story(id: "123") { id, text, likeCount } } - ``` When this response is normalized, Relay can detect that this result overlaps with existing data based on its `id`. Rather than create a new record, Relay will update the existing `123` record. The new `likeCount` is therefore available to _both_ queries, as well as any other query that might reference this story. @@ -215,7 +199,6 @@ query { } } } - ``` After initially fetching this story our cache might be as follows. Note that the story and comment both link to the same record as `author`: @@ -242,7 +225,6 @@ Map { author: Link(2), }, } - ``` The author of this story also commented on it — quite common. Now imagine that some other view fetches new information about the author, and her profile photo has changed to a new URI. Here's the _only_ part of our cached data that changes: @@ -256,7 +238,6 @@ Map { photo: 'http://.../photo2.jpg', }, } - ``` The value of the `photo` field has changed; and therefore the record `2` has also changed. And that's it. Nothing else in the _cache_ is affected. But clearly our _view_ needs to reflect the update: both instances of the author in the UI (as story author and comment author) need to show the new photo. @@ -273,7 +254,6 @@ ImmutableMap { }, 3: ImmutableMap // same as before } - ``` If we replace `2` with a new immutable record, we'll also get a new immutable instance of the cache object. However, records `1` and `3` are untouched. Because the data is normalized, we can't tell that `story`'s contents have changed just by looking at the `story` record alone. @@ -299,7 +279,6 @@ mutation StoryLike($storyID: String) { likeCount } } - ``` Notice that we're querying for data that _may_ have changed as a result of the mutation. An obvious question is: why can't the server just tell us what changed? The answer is: it's complicated. GraphQL abstracts over _any_ data storage layer (or an aggregation of multiple sources), and works with any programming language. Furthermore, the goal of GraphQL is to provide data in a form that is useful to product developers building a view. diff --git a/website/versioned_docs/version-v8.0.0/PrinciplesAndArchitecture-ThinkingInRelay.md b/website/versioned_docs/version-v8.0.0/PrinciplesAndArchitecture-ThinkingInRelay.md index d6f1572d5590b..4fb68372ec4b3 100644 --- a/website/versioned_docs/version-v8.0.0/PrinciplesAndArchitecture-ThinkingInRelay.md +++ b/website/versioned_docs/version-v8.0.0/PrinciplesAndArchitecture-ThinkingInRelay.md @@ -30,13 +30,11 @@ fragment Story_story on Story { photo } } - ``` And this fragment can then be used to define the Story container: ```javascript - const {createFragmentContainer, graphql} = require('react-relay'); // Plain React component. @@ -64,7 +62,6 @@ const StoryContainer = createFragmentContainer(Story, { In React, rendering a view requires two inputs: the _component_ to render, and a _root_ DOM (UI) node to render into. Rendering Relay containers is similar: we need a _container_ to render, and a _root_ in the graph from which to start our query. We also must ensure that the queries for the container are executed and may want to show a loading indicator while data is being fetched. Similar to `ReactDOM.render(component, domNode)`, Relay provides `` for this purpose. The `query` and `variables` define what data to fetch and `render` defines what to render. Here's how we might render ``: ```javascript - ReactDOM.render( { ); } } - ``` The above code is doing something very similar to our [previous example](#rendering-graphql-queries). However, we are now passing a `$userID` variable to the GraphQL query via the `variables` prop. This has a couple of important implications: @@ -228,7 +216,6 @@ Now that we know how to define and fetch queries, let's actually start building First, let's start at the bottom. Suppose that we want to render a component that simply displays a given todo item's text and completed state: ```javascript - // Todo.js import React from 'react'; @@ -258,7 +245,6 @@ export default class Todo extends React.Component { ); } } - ``` From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L112), we know that we can query this data on the `Todo` type. However, we don't want to have to send a separate query for each todo item; that would defeat the purpose of using GraphQL over a traditional REST API. We could manually query for these fields directly in our `QueryRenderer` query, but that would hurt re-usability: what if we want to query the same set of fields as part of a different query? Additionally, we wouldn't know which component needs the data we're querying, which is a problem Relay directly tries to address. @@ -266,18 +252,15 @@ From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/dat Instead, we can define a reusable [Fragment](http://graphql.org/learn/queries/#fragments), which allows us to define a set of fields on a type and reuse them within our queries wherever we need to: ```graphql - fragment TodoItemFragment on Todo { complete text } - ``` Our component can then use this fragment to declare its data dependency on the `Todo` GraphQL type: ```javascript - // Todo.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -340,7 +323,6 @@ Before proceeding, don't forget to run the Relay Compiler with `yarn relay`. Given that [Fragment Containers](./fragment-container) are just React components, we can compose them as such. We can even re-use fragment containers within other fragment containers. As an example, let's see how we would define a `TodoList` component that just renders a list of todo items, and whether all have been completed or not: ```javascript - // TodoList.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -401,7 +383,6 @@ export default createFragmentContainer( `, }, ); - ``` As with the first fragment container we defined, `TodoList` declares it's data dependencies via a fragment. However, this component additionally re-uses the fragment previously defined by the `Todo` component, and passes the appropriate data when rendering the child `Todo` components (a.k.a. fragment containers). @@ -416,7 +397,6 @@ fragment containers do not directly fetch data. Instead, containers declare a sp A `QueryRenderer` rendering these fragment containers could look like the following: ```javascript - // ViewerTodoList.js import React from 'react'; import {graphql, QueryRenderer} from 'react-relay'; @@ -457,7 +437,6 @@ export default class ViewerTodoList extends React.Component { ); } } - ``` Check out our docs for [Fragment Containers](./fragment-container) for more details, and our guides on [Refetch](./refetch-container) and [Pagination](./pagination-container) for more advanced usage of containers. @@ -469,7 +448,6 @@ Now that we know how to query for and render data, let's move on to changing our From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L35), we know that we have some mutations available to us, so let's start by writing a mutation to change the `complete` status of a given todo item (i.e. mark or unmark it as done): ```graphql - mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { changeTodoStatus(input: $input) { todo { @@ -478,7 +456,6 @@ mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { } } } - ``` This mutation allows us to query back some data as a [result of the mutation](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L18), so we're going to query for the updated `complete` status on the todo item. @@ -486,7 +463,6 @@ This mutation allows us to query back some data as a [result of the mutation](ht In order to execute this mutation in Relay, we're going to write a new mutation using Relay's `commitMutation` api: ```javascript - // ChangeTodoStatusMutation.js import {graphql, commitMutation} from 'react-relay'; @@ -520,7 +496,6 @@ function commit( } export default {commit}; - ``` Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mutation to the server and, in our case, upon receiving a response it will automatically update the local data store with the latest data from the server. This also means that upon receiving the response, Relay will ensure that any components (i.e. containers) that depend on the updated data are re-rendered. @@ -528,7 +503,6 @@ Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mut In order to actually use this mutation in our component, we could update our `Todo` component in the following way: ```javascript - // Todo.js // ... @@ -562,7 +536,6 @@ In order to make the experience better, we can configure our mutation to do an o In Relay, there's a couple of options we can pass to `commitMutation` to enable optimistic updates. Let's see what that would look like in our `ChangeTodoStatusMutation`: ```javascript - // ChangeTodoStatusMutation.js // ... @@ -597,7 +570,6 @@ function commit( } export default {commit}; - ``` In the simplest case above, we just need to pass an `optimisticResponse` option, which should refer to an object having the same shape as the mutation response payload. When we pass this option, Relay will know to immediately update our local data with the optimistic response, and then update it with the actual server response or roll it back if an error occurs. diff --git a/website/versioned_docs/version-v9.0.0/Modern-ConvertingMutations.md b/website/versioned_docs/version-v9.0.0/Modern-ConvertingMutations.md index 08ad2e998cb2d..8f4bdc1d8e0d2 100644 --- a/website/versioned_docs/version-v9.0.0/Modern-ConvertingMutations.md +++ b/website/versioned_docs/version-v9.0.0/Modern-ConvertingMutations.md @@ -12,19 +12,16 @@ FatQueries in Relay Classic mutations was a concept that was confusing for a num Example of existing fat query: ```javascript - RelayClassic.QL` fragment on MarkReadNotificationResponsePayload @relay(pattern: true) { notification } `; - ``` Example of converted mutation query: ```javascript - graphql` mutation MarkReadNotificationMutation( $input: MarkReadNotificationData! @@ -37,7 +34,6 @@ graphql` } } `; - ``` ## Migrating Configs @@ -67,7 +63,6 @@ This is no longer needed in Compatibility Mode for neither environments. Simply Take this example of a simple mutation in Relay Classic: ```javascript - class LikeStoryMutation extends RelayClassic.Mutation { getMutation() { return RelayClassic.QL`mutation {likeStory}`; @@ -106,7 +101,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { `, }; } - ``` ### Converting `getMutation()` and `getFatQuery()` @@ -114,7 +108,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { We combine these two into a regular GraphQL mutation, which list out specific fields that needs to be updated. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story(data: $input) { @@ -126,7 +119,6 @@ const mutation = graphql` } } `; - ``` ### Converting `getConfigs()` @@ -138,13 +130,11 @@ As specified above, `FIELDS_CHANGE` configs can be omitted. To convert `getVariables()`, we take the return value from the original function and wrap it in an object that contains a property that matches the variable name for the mutation. In this case, the mutation has a `input` variable that is of type `LikeStoryData`. ```javascript - const variables = { input: { storyID: args.storyID } } - ``` ### Final Result @@ -152,7 +142,6 @@ const variables = { As you can see, our resulting mutation is a lot simpler and more like regular GraphQL than the Relay Classic version we started out with. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story { @@ -178,7 +167,6 @@ function commit(environment: CompatEnvironment, args) { variables, }); } - ``` See [Mutation](./mutations) for additional options on `commitMutation` for more complex mutations. diff --git a/website/versioned_docs/version-v9.0.0/Modern-FragmentContainer.md b/website/versioned_docs/version-v9.0.0/Modern-FragmentContainer.md index 423f446cbb054..6a40bbcfb5d0a 100644 --- a/website/versioned_docs/version-v9.0.0/Modern-FragmentContainer.md +++ b/website/versioned_docs/version-v9.0.0/Modern-FragmentContainer.md @@ -17,12 +17,10 @@ Table of Contents: `createFragmentContainer` has the following signature: ```javascript - createFragmentContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, ): ReactComponentClass; - ``` ### Arguments @@ -43,7 +41,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -58,7 +55,6 @@ To start, let's build the plain React version of a hypothetical `` c Here's a basic implementation of `` that ignores styling in order to highlight the functionality: ```javascript - // TodoItem.js class TodoItem extends React.Component { render() { @@ -78,7 +74,6 @@ class TodoItem extends React.Component { ); } } - ``` ### Data Dependencies With GraphQL @@ -86,7 +81,6 @@ class TodoItem extends React.Component { In Relay, data dependencies are described using [GraphQL](https://github.com/facebook/graphql). For ``, the dependency can be expressed as follows. Note that this exactly matches the shape that the component expected for the `item` prop. ```javascript - graphql` # This fragment only applies to objects of type 'Todo'. fragment TodoItem_item on Todo { @@ -102,7 +96,6 @@ graphql` Given the plain React component and a GraphQL fragment, we can now define a Fragment Container to specify this component's data requirements. Let's look at the code first and then see what's happening: ```javascript - // TodoItem.js import {createFragmentContainer, graphql} from 'react-relay'; @@ -120,7 +113,6 @@ export default createFragmentContainer(TodoItem, { } `, }); - ``` ## Container Composition @@ -134,7 +126,6 @@ Let's explore how this works via a `` component that composes the `< View composition is _exactly_ what you're used to — Relay containers are just standard React components. Here's the `` component: ```javascript - class TodoList extends React.Component { render() { // Expects a `list` with a string `title`, as well as the information @@ -151,7 +142,6 @@ class TodoList extends React.Component { ); } } - ``` ### Composing Fragments @@ -159,7 +149,6 @@ class TodoList extends React.Component { Fragment composition works similarly — a parent container's fragment composes the fragment for each of its children. In this case, `` needs to fetch information about the `Todo`s that are required by ``. ```javascript - class TodoList extends React.Component // as above export default createFragmentContainer(TodoList, { @@ -176,7 +165,6 @@ export default createFragmentContainer(TodoList, { } `, }); - ``` Note that when composing fragments, the type of the composed fragment must match the field on the parent in which it is embedded. For example, it wouldn't make sense to embed a fragment of type `Story` into a parent's field of type `User`. Relay and GraphQL will provide helpful error messages if you get this wrong (and if they aren't helpful, let us know!). @@ -190,7 +178,6 @@ When defining a fragment, you can use the [`@argumentDefinitions`](./graphql-in- For example, let's redefine our `TodoList_list` fragment to take some arguments using `@argumentDefinitions`: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -200,7 +187,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` Any arguments defined inside `@argumentDefinitions` will be local variables available inside the fragment's scope. However, a fragment can also reference global variables that were defined in the root query. @@ -212,11 +198,9 @@ In order to pass arguments to a fragment that has `@argumentDefinitions`, you ne Following our `TodoList_list` example, we would pass arguments to the fragment like so: ```graphql - query TodoListQuery($count: Int, $userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` ## Rendering Containers diff --git a/website/versioned_docs/version-v9.0.0/Modern-GraphQLInRelay.md b/website/versioned_docs/version-v9.0.0/Modern-GraphQLInRelay.md index c4dc8f3463e53..715b119492cc7 100644 --- a/website/versioned_docs/version-v9.0.0/Modern-GraphQLInRelay.md +++ b/website/versioned_docs/version-v9.0.0/Modern-GraphQLInRelay.md @@ -14,7 +14,6 @@ Table of Contents: The `graphql` template tag provided by Relay serves as the mechanism to write queries, fragments, mutations or subscriptions in the [GraphQL](http://graphql.org/learn/) language. For example: ```javascript - import {graphql} from 'react-relay'; graphql` @@ -24,7 +23,6 @@ graphql` } } `; - ``` The result of using the `graphql` template tag is a `GraphQLTaggedNode`; a runtime representation of the GraphQL document which can be used to define [Query Renderers](./query-renderer), [Fragment Containers](./fragment-container), [Refetch Containers](./refetch-container), [Pagination Containers](./pagination-container), etc. @@ -42,11 +40,9 @@ Relay uses directives to add additional information to GraphQL documents, which `@arguments` is a directive used to pass arguments to a fragment that was defined using [`@argumentDefinitions`](#argumentdefinitions). For example: ```graphql - query TodoListQuery($userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -56,7 +52,6 @@ See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fr `@argumentDefinitions` is a directive used to specify arguments taken by a fragment. For example: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -66,7 +61,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -80,7 +74,6 @@ When using the [Pagination Container](./pagination-container), Relay expects con When defining a fragment for use with a Fragment container, you can use the `@relay(plural: true)` directive to indicate that container expects the prop for that fragment to be a list of items instead of a single item. A query or parent that spreads a `@relay(plural: true)` fragment should do so within a plural field (ie a field backed by a [GraphQL list](http://graphql.org/learn/schema/#lists-and-non-null). For example: ```javascript - // Plural fragment definition graphql` fragment TodoItems_items on TodoItem @relay(plural: true) { @@ -95,7 +88,6 @@ fragment TodoApp_app on App { ...TodoItem_items } } - ``` ### `@inline` @@ -107,7 +99,6 @@ Non-React functions can also take advantage of data masking. A fragment can be d In the example below, the function `processItemData` is called from a React component. It requires an item object with a specific set of fields. All React components that use this function should spread the `processItemData_item` fragment to ensure all of the correct item data is loaded for this function. ```javascript - import {graphql, readInlineData} from 'react-relay'; // non-React function called from React @@ -127,11 +118,9 @@ function processItemData(itemRef) { creatorName: item.creator.name }); } - ``` ```javascript - // React Component function MyComponent({item}) { function handleClick() { @@ -151,7 +140,6 @@ export default createFragmentContainer(MyComponent, { } ` }); - ``` ### `@relay(mask: Boolean)` @@ -169,7 +157,6 @@ Keep in mind that it is typically considered an **anti-pattern** to create a sin In the example below, the `user` prop will include the data for `id` and `name` fields wherever `...Component_internUser` is included, instead of Relay's normal behavior to mask those fields: ```javascript - graphql` fragment Component_internUser on InternUser @relay(mask: false) { id @@ -197,7 +184,6 @@ export default createFragmentContainer( } `, ); - ``` ## Relay Compiler @@ -207,7 +193,6 @@ Relay uses the Relay Compiler to convert [`graphql`](#graphql) literals into gen A query like the following: ```javascript - graphql` fragment MyComponent on Type { field @@ -228,12 +213,10 @@ Relay Compiler supports the use of **persisted queries**, in which each version Persisted queries can be enabled by instructing Relay Compiler to emit metadata about each query, mutation, and subscription into a JSON file. The generated file will contain a mapping of query identifiers to query text, which you can then save to your server. To enable persisted queries, use the `--persist-output` flag to the compiler: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` Relay Compiler will then create the id => query text mapping in the path you specify. You can then use this complete @@ -250,7 +233,6 @@ See our relay-compiler section in our [Installation and Setup guide](./installat To use the Relay Compiler, you need either a .graphql or .json GraphQL schema file, describing your GraphQL server's API. Typically these files are local representations of a server source of truth and are not edited directly. For example, we might have a `schema.graphql` like: ```graphql - schema { query: Root } @@ -268,7 +250,6 @@ type WordDefinition { text: String image: String } - ``` ### Source files @@ -284,7 +265,6 @@ For example, given the two files: - `src/Components/DictionaryComponent.js` ```javascript - const DictionaryWordFragment = graphql` fragment DictionaryComponent_word on Word { id @@ -306,7 +286,6 @@ For example, given the two files: - `src/Queries/DictionaryQuery.js` ```javascript - const DictionaryQuery = graphql` query DictionaryQuery { dictionary { @@ -330,9 +309,7 @@ Typically you will not need to import your generated definitions. The [Relay Bab However the Relay Compiler also automatically generates [Flow](https://flow.org) types as [type comments](https://flow.org/en/docs/types/comments/). For example, you can import the generated Flow types like so: ```javascript - import type {DictionaryComponent_word} from './__generated__/DictionaryComponent_word.graphql'; - ``` ### Client schema extensions @@ -342,7 +319,6 @@ The Relay Compiler fully supports client-side schema extensions, which allows yo For example, assuming the server schema `./schema.graphql`: ```graphql - schema { query: Root } @@ -350,28 +326,23 @@ schema { type Root { title: String! } - ``` We can create a `./src/clientSchema.graphql` and define a new type called `Setting`: ```graphql - type Setting { name: String! active: Boolean! } - ``` We can then extend existing server types in the client schema `./src/clientSchema.graphql` with our new `Setting` type, like so: ```graphql - extend type Root { settings: [Setting] } - ``` Any fields specified in the client schema, can be fetched from the [Relay Store](./relay-store), by selecting it in a query or fragment. diff --git a/website/versioned_docs/version-v9.0.0/Modern-LocalStateManagement.md b/website/versioned_docs/version-v9.0.0/Modern-LocalStateManagement.md index 5e0bdde30237a..c6e75a4e6fbf0 100644 --- a/website/versioned_docs/version-v9.0.0/Modern-LocalStateManagement.md +++ b/website/versioned_docs/version-v9.0.0/Modern-LocalStateManagement.md @@ -24,23 +24,19 @@ It can even be used to extend an existing server schema. For example, we can create a new type called `Note`: ```graphql - type Note { ID: ID! title: String body: String } - ``` And then extend the server schema type `User`, with a list of `Note`, called `notes`. ```graphql - extend type User { notes: [Note] } - ``` ## Querying local state @@ -51,7 +47,6 @@ The field can be from the server schema, or it can be schema agnostic, like an i Here, we use a [QueryRenderer](./query-renderer) to get the current `User` via the `viewer` field, along with their id, name and the local list of notes. ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -97,7 +92,6 @@ const Example = (props) => { /> ); } - ``` ## Mutating local state @@ -111,7 +105,6 @@ To build upon the previous example, let's try creating, updating and deleting a ### Create ```javascript - import {commitLocalUpdate} from 'react-relay'; let tempID = 0; @@ -131,7 +124,6 @@ function createUserNote() { user.setLinkedRecords([...userNoteRecords, newNoteRecord], 'notes'); }); } - ``` Note that since this record will be rendered by the `ExampleQuery` in our `QueryRenderer`, the QueryRenderer will automatically retain this data so it isn't garbage collected. @@ -139,20 +131,17 @@ Note that since this record will be rendered by the `ExampleQuery` in our `Query If no component is rendering the local data and you want to manually retain it, you can do so by calling `environment.retain()`: ```javascript - // Tell Relay to retain the record so it isn't garbage collected environment.retain({ dataID, variables: {}, node: { selections: [] } }); - ``` ### Update ```javascript - import {commitLocalUpdate} from 'react-relay'; function updateUserNote(dataID, body, title) { @@ -163,13 +152,11 @@ function updateUserNote(dataID, body, title) { note.setValue(title, 'title') }); } - ``` ### Delete ```javascript - import {commitLocalUpdate} from 'react-relay'; function deleteUserNote(dataID) { @@ -187,7 +174,6 @@ function deleteUserNote(dataID) { user.setLinkedRecords(newUserNoteRecords, 'notes'); }); } - ``` ## Initial local state @@ -196,7 +182,6 @@ All new client-side schema fields default to `undefined` value. Often however, y You can use an updater function via `commitLocalUpdate` to prime local state. ```javascript - import {commitLocalUpdate} from 'react-relay'; commitLocalUpdate(environment, store => { @@ -205,5 +190,4 @@ commitLocalUpdate(environment, store => { // initialize user notes to an empty array. user.setLinkedRecords([], 'notes'); }); - ``` diff --git a/website/versioned_docs/version-v9.0.0/Modern-MigrationSetup.md b/website/versioned_docs/version-v9.0.0/Modern-MigrationSetup.md index 66f1145357e25..a89c0e178e0e5 100644 --- a/website/versioned_docs/version-v9.0.0/Modern-MigrationSetup.md +++ b/website/versioned_docs/version-v9.0.0/Modern-MigrationSetup.md @@ -13,13 +13,11 @@ With some additional configuration, the `"relay"` babel plugin can also translat Relay Classic `Relay.QL` literals. Most importantly, include a reference to your GraphQL Schema as either a json file or graphql schema file. ```javascript - { "plugins": [ ["relay", {"schema": "path/schema.graphql"}] ] } - ``` ## Set up babel-plugin-relay for "[compatibility mode](./relay-compat)" @@ -29,13 +27,11 @@ literals can be translated to be usable by _both_ runtimes if configured to use compatibility mode: ```javascript - { "plugins": [ ["relay", {"compat": true, "schema": "path/schema.graphql"}] ] } - ``` ## Additional Options @@ -47,7 +43,6 @@ thrown at runtime. When compiling code for production deployment, the plugin can be configured to immediately throw upon encountering a validation problem. The plugin can be further customized for different environments with the following options: ```javascript - { "plugins": [ ["relay", { @@ -56,5 +51,4 @@ When compiling code for production deployment, the plugin can be configured to i }] ] } - ``` diff --git a/website/versioned_docs/version-v9.0.0/Modern-Mutations.md b/website/versioned_docs/version-v9.0.0/Modern-Mutations.md index 78b4df76e1b61..36e9ae0875ff5 100644 --- a/website/versioned_docs/version-v9.0.0/Modern-Mutations.md +++ b/website/versioned_docs/version-v9.0.0/Modern-Mutations.md @@ -17,7 +17,6 @@ Table of Contents: Use `commitMutation` to create and execute mutations. `commitMutation` has the following signature: ```javascript - commitMutation( environment: Environment, config: { @@ -31,7 +30,6 @@ commitMutation( configs?: Array, }, ); - ``` ### Arguments @@ -58,7 +56,6 @@ commitMutation( Example of a simple mutation: ```javascript - import {commitMutation, graphql} from 'react-relay'; const mutation = graphql` @@ -90,7 +87,6 @@ function markNotificationAsRead(environment, storyID) { }, ); } - ``` ## Optimistic Updates @@ -98,7 +94,6 @@ function markNotificationAsRead(environment, storyID) { To improve perceived responsiveness, you may wish to perform an "optimistic update", in which the client immediately updates to reflect the anticipated new value even before the response from the server has come back. The simplest way to do this is by providing an `optimisticResponse` and adding it to the `config` that we pass into `commitMutation`: ```javascript - const mutation = graphql` mutation MarkReadNotificationMutation( $storyID: ID! @@ -127,7 +122,6 @@ commitMutation( variables, }, ); - ``` Another way to enable optimistic updates is via the `optimisticUpdater`, which can be used for more complicated update scenarios. Using `optimisticUpdater` is covered in the section [below](#using-updater-and-optimisticupdater). @@ -149,7 +143,6 @@ Given a deletedIDFieldName, Relay will remove the node(s) from the store. #### Example ```javascript - const mutation = graphql` mutation DestroyShipMutation($target: ID!) { destroyShip(target: $target) { @@ -167,7 +160,6 @@ const configs = [{ type: 'NODE_DELETE', deletedIDFieldName: 'destroyedShipId', }]; - ``` ### RANGE_ADD @@ -187,7 +179,6 @@ Given a parent, information about the connection, and the name of the newly crea #### Example ```javascript - const mutation = graphql` mutation AddShipMutation($factionID: ID!, $name: String!) { addShip(factionID: $factionID, name: $name) { @@ -218,7 +209,6 @@ function commit(environment, factionID, name) { }], }); } - ``` ### RANGE_DELETE @@ -240,7 +230,6 @@ from the connection but leave the associated record(s) in the store. #### Example ```javascript - const mutation = graphql` mutation RemoveTagMutation($todoID: ID!, $tagID: ID!) { removeTag(todo: $todoID, tag: $tagID) { @@ -267,7 +256,6 @@ function commit(environment, todoID, tagID) { }], }); } - ``` ## Using updater and optimisticUpdater @@ -285,7 +273,6 @@ When you provide these functions, this is roughly what happens during the mutati Here are a quick example of adding a todo item to a Todo list using this [example schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L36): ```javascript - // AddTodoMutation.js import {commitMutation, graphql} from 'react-relay'; import {ConnectionHandler} from 'relay-runtime'; @@ -369,7 +356,6 @@ function commit(environment, text, user) { }, }); } - ``` For details on how to interact with the Relay Store, please refer to our Relay Store [docs](./relay-store). diff --git a/website/versioned_docs/version-v9.0.0/Modern-NetworkLayer.md b/website/versioned_docs/version-v9.0.0/Modern-NetworkLayer.md index 9dddd36d6c235..c9e069b812b01 100644 --- a/website/versioned_docs/version-v9.0.0/Modern-NetworkLayer.md +++ b/website/versioned_docs/version-v9.0.0/Modern-NetworkLayer.md @@ -8,7 +8,6 @@ In order to know how to access your GraphQL server, Relay Modern requires develo Currently the easiest way to create a network layer is via a helper from the `relay-runtime` package: ```javascript - import { Environment, Network, @@ -50,7 +49,6 @@ const environment = new Environment({ }); export default environment; - ``` Note that this is a basic example to help you get started. This example could be extended with additional features such as request/response caching (enabled e.g. when `cacheConfig.force` is false) and uploading form data for mutations (the `uploadables` parameter). @@ -62,7 +60,6 @@ Relay modern makes no assumptions about what to cache and will garbage collect a You have to implement your own cache strategy. A simple solution is to use `QueryResponseCache` (an in-memory cache): ```javascript - import { Environment, Network, @@ -126,7 +123,6 @@ const environment = new Environment({ }); export default environment; - ``` ## Custom open-source implementations diff --git a/website/versioned_docs/version-v9.0.0/Modern-PaginationContainer.md b/website/versioned_docs/version-v9.0.0/Modern-PaginationContainer.md index 6ac3aac8cfb8e..57980d553af9b 100644 --- a/website/versioned_docs/version-v9.0.0/Modern-PaginationContainer.md +++ b/website/versioned_docs/version-v9.0.0/Modern-PaginationContainer.md @@ -24,7 +24,6 @@ However, when [specifying connection fragments](#createpaginationcontainer) for The purpose of the `@connection` directive is to allow Relay to uniquely identify different connections under a parent type. The `@connection` directive takes 2 arguments that help identify the connection: ```graphql - @connection(key: String!, filters: [String]) ``` @@ -37,7 +36,6 @@ The purpose of the `@connection` directive is to allow Relay to uniquely identif Specifying just the `key`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and the value of `$orderBy` (given that no `filters` were provided) @@ -53,13 +51,11 @@ fragment Feed_user on User { } } } - ``` Specifying `key` and `filters`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and /only/ the value of `$searchTerm`, i.e. @@ -77,7 +73,6 @@ fragment Feed_user on User { } } } - ``` ## `createPaginationContainer` @@ -85,7 +80,6 @@ fragment Feed_user on User { `createPaginationContainer` has the following signature: ```javascript - createPaginationContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, @@ -113,7 +107,6 @@ type ConnectionData = { startCursor: ?string, }, }; - ``` ### Arguments @@ -134,7 +127,6 @@ type ConnectionData = { The Component resulting from `createPaginationContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -145,7 +137,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -160,7 +151,6 @@ type Props = { `hasMore` is a function available on the `relay` [prop](#available-props). This function indicates whether there are more pages to fetch from the server or not. ```javascript - hasMore: () => boolean, ``` @@ -170,7 +160,6 @@ hasMore: () => boolean, `isLoading` is a function available on the `relay` [prop](#available-props). This function indicates if a previous call to [`loadMore()`](#loadmore) is still pending. This is convenient for avoiding duplicate load calls. ```javascript - isLoading: () => boolean, ``` @@ -180,7 +169,6 @@ isLoading: () => boolean, `loadMore` is a function available on the `relay` [prop](#available-props). You can call `loadMore()` to fetch more items from the server based on the `connectionConfig` provided to the container. This will return null if there are no more items to fetch, otherwise it will fetch more items and return a Disposable that can be used to cancel the fetch. ```javascript - loadMore( pageSize: number, callback: ?(error: ?Error) => void, @@ -201,7 +189,6 @@ loadMore( `refetchConnection` is a function available on the `relay` [prop](#available-props). You can call `refetchConnection` to restart pagination on a connection from scratch, with optionally a completely new set of variables to pass to the pagination `query`. This is useful for example if you are paginating over a collection based on a userID and the userID changes, you'd want to start paginating over the new collection for the new user. ```javascript - refetchConnection:( totalCount: number, callback: (error: ?Error) => void, @@ -219,7 +206,6 @@ refetchConnection:( ## Pagination Example ```javascript - // Feed.js import {createPaginationContainer, graphql} from 'react-relay'; @@ -314,5 +300,4 @@ module.exports = createPaginationContainer( ` } ); - ``` diff --git a/website/versioned_docs/version-v9.0.0/Modern-PersistedQueries.md b/website/versioned_docs/version-v9.0.0/Modern-PersistedQueries.md index 137cc2e23220c..ec03b69ba09c3 100644 --- a/website/versioned_docs/version-v9.0.0/Modern-PersistedQueries.md +++ b/website/versioned_docs/version-v9.0.0/Modern-PersistedQueries.md @@ -17,12 +17,10 @@ The relay compiler supports persisted queries which is useful because: In your `npm` script in `package.json`, run the relay compiler using the `--persist-output` flag: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` The `--persist-ouput` flag does 3 things: @@ -31,8 +29,7 @@ The `--persist-ouput` flag does 3 things: For example without `--persist-output`, a generated `ConcreteRequest` might look like below: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -49,8 +46,7 @@ The `--persist-ouput` flag does 3 things: With `--persist-output ` this becomes: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -68,12 +64,10 @@ The `--persist-ouput` flag does 3 things: 2. It generates a JSON file at the `` you specify containing a mapping from query ids to the corresponding operation texts. -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./src/queryMaps/queryMap.json" } - ``` The example above writes the complete query map file to `./src/queryMaps/queryMap.json`. You need to ensure all the directories @@ -83,8 +77,7 @@ leading to the `queryMap.json` file exist. You'll need to modify your network layer fetch implementation to pass a documentId parameter in the POST body instead of a query parameter: -```js - +```javascript function fetchQuery(operation, variables,) { return fetch('/graphql', { method: 'POST', @@ -100,7 +93,6 @@ function fetchQuery(operation, variables,) { return response.json(); }); } - ``` ## Executing Persisted Queries on the Server @@ -116,13 +108,11 @@ the query map file in a common location accessible to both the client and the se For applications where the client and server projects are separate, one option is to have an additional npm run script to push the query map at compile time to a location accessible by your server: -```js - +```javascript "scripts": { "push-queries": "node ./pushQueries.js", "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-ouput && npm run push-queries" } - ``` Some possibilities of what you can do in `./pushQueries.js`: @@ -146,8 +136,7 @@ database technologies you use, so we'll just cover the most common and basic exa If you use `express-graphql` and have access to the query map file, you can import the `--persist-output` JSON file directly and perform the matching using the `matchQueryMiddleware` from [relay-compiler-plus](https://github.com/yusinto/relay-compiler-plus). -```js - +```javascript import Express from 'express'; import expressGraphql from 'express-graphql'; import {matchQueryMiddleware} from 'relay-compiler-plus'; @@ -158,7 +147,6 @@ const app = Express(); app.use('/graphql', matchQueryMiddleware(queryMapJson), expressGraphql({schema})); - ``` ## Using `--persist-output` and `--watch` diff --git a/website/versioned_docs/version-v9.0.0/Modern-QueryRenderer.md b/website/versioned_docs/version-v9.0.0/Modern-QueryRenderer.md index cf6c37f3d9a4d..b621ef9986bf1 100644 --- a/website/versioned_docs/version-v9.0.0/Modern-QueryRenderer.md +++ b/website/versioned_docs/version-v9.0.0/Modern-QueryRenderer.md @@ -24,7 +24,6 @@ However, a `QueryRenderer` will not start loading its data until it is mounted, ## Example ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -56,5 +55,4 @@ const Example = (props) => { /> ); } - ``` diff --git a/website/versioned_docs/version-v9.0.0/Modern-RefetchContainer.md b/website/versioned_docs/version-v9.0.0/Modern-RefetchContainer.md index 7ce0d14e45417..51c2c44db8941 100644 --- a/website/versioned_docs/version-v9.0.0/Modern-RefetchContainer.md +++ b/website/versioned_docs/version-v9.0.0/Modern-RefetchContainer.md @@ -16,13 +16,11 @@ Table of Contents: `createRefetchContainer` has the following signature: ```javascript - createRefetchContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, refetchQuery: GraphQLTaggedNode, ): ReactComponentClass; - ``` ### Arguments @@ -37,7 +35,6 @@ createRefetchContainer( The Component resulting from `createRefetchContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -45,7 +42,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -61,7 +57,6 @@ type Props = { `refetch` has the following signature: ```javascript - type RefetchOptions = { force?: boolean, }; @@ -102,7 +97,6 @@ Returns a `Disposable` on which you could call `dispose()` to cancel the refetch In this simple example, let's assume we want to fetch the latest data for a `TodoItem` from the server: ```javascript - // TodoItem.js import {createRefetchContainer, graphql} from 'react-relay'; @@ -148,7 +142,6 @@ export default createRefetchContainer( } ` ); - ``` ### Loading more data @@ -156,7 +149,6 @@ export default createRefetchContainer( In this example we are using a Refetch Container to fetch more stories in a story feed component. ```javascript - import {createRefetchContainer, graphql} from 'react-relay'; class FeedStories extends React.Component { @@ -212,5 +204,4 @@ export default createRefetchContainer( } `, ); - ``` diff --git a/website/versioned_docs/version-v9.0.0/Modern-RelayCompat.md b/website/versioned_docs/version-v9.0.0/Modern-RelayCompat.md index 36632d3a8f1a1..f47dbd845ba3e 100644 --- a/website/versioned_docs/version-v9.0.0/Modern-RelayCompat.md +++ b/website/versioned_docs/version-v9.0.0/Modern-RelayCompat.md @@ -31,7 +31,6 @@ Relay Modern. The components using Relay Compat can be referred to by both other Relay Modern and Relay Classic components. ```javascript - const {createFragmentContainer, graphql} = require('react-relay/compat'); class TodoItem extends React.Component { @@ -47,5 +46,4 @@ module.exports = createFragmentContainer(TodoItem, graphql` isComplete } `); - ``` diff --git a/website/versioned_docs/version-v9.0.0/Modern-RelayEnvironment.md b/website/versioned_docs/version-v9.0.0/Modern-RelayEnvironment.md index 27d90b2fc4fe1..99e728bce740d 100644 --- a/website/versioned_docs/version-v9.0.0/Modern-RelayEnvironment.md +++ b/website/versioned_docs/version-v9.0.0/Modern-RelayEnvironment.md @@ -12,7 +12,6 @@ Most applications will create a single Environment instance and use it throughou To create an environment instance in Relay Modern, use the `RelayModernEnvironment` class: ```javascript - const { Environment, Network, @@ -30,7 +29,6 @@ const environment = new Environment({ network, store, }); - ``` For more details on creating a Network, see the [NetworkLayer guide](./network-layer). @@ -44,7 +42,6 @@ The example above did not configure a `handlerProvider`, which means that a defa If you wish to provide your own `handlerProvider`, you can do so: ```javascript - const { ConnectionHandler, } = require('relay-runtime'); @@ -58,5 +55,4 @@ function handlerProvider(handle) { `handlerProvider: No handler provided for ${handle}` ); } - ``` diff --git a/website/versioned_docs/version-v9.0.0/Modern-RelayStore.md b/website/versioned_docs/version-v9.0.0/Modern-RelayStore.md index 3457960655342..3d552f6035f50 100644 --- a/website/versioned_docs/version-v9.0.0/Modern-RelayStore.md +++ b/website/versioned_docs/version-v9.0.0/Modern-RelayStore.md @@ -16,7 +16,6 @@ Table of Contents: The `RecordSourceSelectorProxy` is the type of the `store` that [`updater` functions](./mutations#using-updater-and-optimisticupdater) receive as an argument. The following is the `RecordSourceSelectorProxy` interface: ```javascript - interface RecordSourceSelectorProxy { create(dataID: string, typeName: string): RecordProxy; delete(dataID: string): void; @@ -26,7 +25,6 @@ interface RecordSourceSelectorProxy { getPluralRootField(fieldName: string): ?Array; invalidateStore(): void; } - ``` ### `create(dataID: string, typeName: string): RecordProxy` @@ -36,9 +34,7 @@ Creates a new record in the store given a `dataID` and the `typeName` as defined #### Example ```javascript - const record = store.create(dataID, 'Todo'); - ``` ### `delete(dataID: string): void` @@ -48,9 +44,7 @@ Deletes a record from the store given its `dataID`. #### Example ```javascript - store.delete(dataID); - ``` ### `get(dataID: string): ?RecordProxy` @@ -60,9 +54,7 @@ Retrieves a record from the store given its `dataID`. Returns a [`RecordProxy`]( #### Example ```javascript - const record = store.get(dataID); - ``` ### `getRoot(): RecordProxy` @@ -74,20 +66,16 @@ Returns the [`RecordProxy`](#recordproxy) representing the root of the GraphQL d Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - // Represents root query const root = store.getRoot(); - ``` ### `getRootField(fieldName: string): ?RecordProxy` @@ -99,19 +87,15 @@ Retrieves a root field from the store given the `fieldName`, as defined by the G Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - const viewer = store.getRootField('viewer'); - ``` ### `getPluralRootField(fieldName: string): ?Array` @@ -123,19 +107,15 @@ Retrieves a root field that represents a collection from the store given the `fi Given the GraphQL document: ```graphql - nodes(first: 10) { # ... } - ``` Usage: ```javascript - const nodes = store.getPluralRootField('nodes'); - ``` ### `invalidateStore(): void` @@ -145,15 +125,12 @@ Globally invalidates the Relay store. This will cause any data that was written #### Example ```javascript - store.invalidateStore(); - ``` After global invalidation, any query that is checked before refetching it will be considered stale: ```javascript - environment.check(query) === 'stale' ``` @@ -163,7 +140,6 @@ environment.check(query) === 'stale' The `RecordProxy` serves as an interface to mutate records: ```javascript - interface RecordProxy { copyFieldsFrom(sourceRecord: RecordProxy): void; getDataID(): string; @@ -189,7 +165,6 @@ interface RecordProxy { setValue(value: mixed, name: string, arguments?: ?Object): RecordProxy; invalidateRecord(): void; } - ``` ### `getDataID(): string` @@ -199,9 +174,7 @@ Returns the dataID of the current record. #### Example ```javascript - const id = record.getDataID(); - ``` ### `getType(): string` @@ -211,7 +184,6 @@ Gets the type of the current record, as defined by the GraphQL schema. #### Example ```javascript - const type = user.getType(); // User ``` @@ -225,20 +197,16 @@ Gets the value of a field in the current record given the field name. Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - const name = viewer.getValue('name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. @@ -248,20 +216,16 @@ Optionally, if the field takes arguments, you can pass a bag of `variables`. Given the GraphQL document: ```graphql - viewer { id name(arg: $arg) } - ``` Usage: ```javascript - const name = viewer.getValue('name', {arg: 'value'}); - ``` ### `getLinkedRecord(name: string, arguments?: ?Object): ?RecordProxy` @@ -273,23 +237,19 @@ Retrieves a record associated with the current record given the field name, as d Given the GraphQL document: ```graphql - rootField { viewer { id name } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -299,22 +259,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { viewer(arg: $arg) { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {arg: 'value'}); - ``` ### `getLinkedRecords(name: string, arguments?: ?Object): ?Array` @@ -326,22 +282,18 @@ Retrieves the set of records associated with the current record given the field Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const nodes = rootField.getLinkedRecords('nodes'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -351,22 +303,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { nodes(first: $count) { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {count: 10}); - ``` ### `getOrCreateLinkedRecord(name: string, typeName: string, arguments?: ?Object)` @@ -378,19 +326,16 @@ Retrieves the a record associated with the current record given the field name, Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = rootField.getOrCreateLinkedRecord('viewer', 'User'); // Will create if it doesn't exist @@ -405,28 +350,22 @@ Mutates the current record by setting a new value on the specified field. Return Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - viewer.setValue('New Name', 'name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. ```javascript - viewer.setValue('New Name', 'name', {arg: 'value'}); - ``` ### `copyFieldsFrom(sourceRecord: RecordProxy): void` @@ -436,7 +375,6 @@ Mutates the current record by copying the fields over from the passed in record #### Example ```javascript - const record = store.get(id1); const otherRecord = store.get(id2); record.copyFieldsFrom(otherRecord); // Mutates `record` @@ -452,19 +390,16 @@ Mutates the current record by setting a new linked record on the given the field Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = store.create(/* ... */)'' rootField.setLinkedRecord(newViewer, 'viewer'); // @@ -482,19 +417,16 @@ Mutates the current record by setting a new set of linked records on the given t Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newNode = store.create(/* ... */); const newNodes = [...rootField.getLinkedRecords('nodes'), newNode]; @@ -511,16 +443,13 @@ Invalidates the record. This will cause any query that references this record to #### Example ```javascript - const record = store.get('4'); record.invalidateRecord(); - ``` After invalidating a record, any query that references the invalidated record and that is checked before refetching it will be considered stale: ```javascript - environment.check(query) === 'stale' ``` @@ -530,7 +459,6 @@ environment.check(query) === 'stale' `ConnectionHandler` is a utility module exposed by `relay-runtime` that aids in the manipulation of connections. `ConnectionHandler` exposes the following interface: ```javascript - interface ConnectionHandler { getConnection( record: RecordProxy, @@ -555,7 +483,6 @@ interface ConnectionHandler { ): void, deleteNode(connection: RecordProxy, nodeID: string): void } - ``` ### `getConnection(record: RecordProxy, key: string, filters?: ?Object)` @@ -565,7 +492,6 @@ Given a record and a connection key, and optionally a set of filters, `getConnec First, let's take a look at a plain connection: ```graphql - fragment FriendsFragment on User { friends(first: 10) { edges { @@ -575,26 +501,22 @@ fragment FriendsFragment on User { } } } - ``` Accessing a plain connection field like this is the same as other regular field: ```javascript - // The `friends` connection record can be accessed with: const user = store.get(userID); const friends = user && user.getLinkedRecord(user, 'friends'); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` In a [pagination container](./pagination-container), we usually annotate the actual connection field with `@connection` to tell Relay which part needs to be paginated: ```graphql - fragment FriendsFragment on User { friends(first: 10, orderby: "firstname") @connection( key: "FriendsFragment_friends", @@ -606,7 +528,6 @@ fragment FriendsFragment on User { } } } - ``` For connections like the above, `ConnectionHandler` helps us find the record: @@ -624,7 +545,6 @@ const friends = ConnectionHandler.getConnection( ); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` ### Edge creation and insertion @@ -654,7 +574,6 @@ ConnectionHandler.insertEdgeAfter(friends, edge); // No cursor provided, Insert the edge at the front: ConnectionHandler.insertEdgeBefore(friends, edge); - ``` ### `deleteNode(connection: RecordProxy, nodeID: string): void` @@ -668,5 +587,4 @@ Given a connection, deletes any edges whose id matches the given id. const user = store.get(userID); const friends = ConnectionHandler.getConnection(user, 'friends'); ConnectionHandler.deleteNode(friends, idToDelete); - ``` diff --git a/website/versioned_docs/version-v9.0.0/Modern-Subscriptions.md b/website/versioned_docs/version-v9.0.0/Modern-Subscriptions.md index 802f1d02b06de..bd1c5fe2f350c 100644 --- a/website/versioned_docs/version-v9.0.0/Modern-Subscriptions.md +++ b/website/versioned_docs/version-v9.0.0/Modern-Subscriptions.md @@ -6,7 +6,6 @@ original_id: subscriptions Relay exposes the following APIs to create subscriptions. ```javascript - const {requestSubscription} = require('react-relay'); type Variables = {[name: string]: any}; @@ -27,7 +26,6 @@ requestSubscription( configs?: Array, }, ) => Disposable; - ``` The function returns a `Disposable` on which you could call `dispose()` to cancel the refetch. @@ -53,7 +51,6 @@ appropriate when you are only changing the properties of existing records that can be identified by their `id`: ```javascript - const { requestSubscription, graphql, @@ -87,7 +84,6 @@ requestSubscription( onError: error => console.error(error), } ); - ``` # Updating the client on each response @@ -97,7 +93,6 @@ Relay's in-memory cache when each subscription response is received. To do so, pass an `updater` function: ```javascript - const {ConnectionHandler} = require('relay-runtime'); requestSubscription( @@ -123,5 +118,4 @@ requestSubscription( }, }, ); - ``` diff --git a/website/versioned_docs/version-v9.0.0/Modern-TestingRelayComponents.md b/website/versioned_docs/version-v9.0.0/Modern-TestingRelayComponents.md index 5e7aca178349f..6b1a60981a3b1 100644 --- a/website/versioned_docs/version-v9.0.0/Modern-TestingRelayComponents.md +++ b/website/versioned_docs/version-v9.0.0/Modern-TestingRelayComponents.md @@ -65,7 +65,6 @@ MockPayloadGenerator may drastically simplify the process of creating and mainta Example of a simple Mock Resolver: ```javascript - { ID() { // Return mock value for a scalar filed with type ID @@ -76,13 +75,11 @@ Example of a simple Mock Resolver: return "Lorem Ipsum" } } - ``` It is possible to define more resolvers for Object types ```javascript - { // This will be the default values for User object in the query response User() { @@ -95,7 +92,6 @@ It is possible to define more resolvers for Object types }; }, } - ``` ### Mock Resolver Context @@ -103,7 +99,6 @@ It is possible to define more resolvers for Object types The first argument of the MockResolver is the object that contains Mock Resolver Context. It is possible to return dynamic values from mock resolvers based on the context - for instance, name or alias of the field, a path in the selection, arguments, or parent type. ```javascript - { String(context) { if (context.name === 'zip') { @@ -117,7 +112,6 @@ The first argument of the MockResolver is the object that contains Mock Resolver } } } - ``` ### ID Generation @@ -125,14 +119,12 @@ The first argument of the MockResolver is the object that contains Mock Resolver The second argument of the Mock Resolver its a function that will generate a sequence of integers, useful to generate unique ids in the tests ```javascript - { // will generate strings "my-id-1", "my-id-2", etc. ID(_, generateId) { return `my-id-${generateId()}`; }, } - ``` ### @relay_test_operation @@ -142,7 +134,6 @@ Most of GraphQL type information for a specific field in the selection is not av Operation with the @relay_test_operation directive will have additional metadata that will contain GraphQL type info for fields in the operation's selection. And it will improve the quality of the generated data. You also will be able to define Mock resolvers for Scalar (not only ID and String) and Abstract types: ```javascript - { Float() { return 123.456; @@ -160,7 +151,6 @@ Operation with the @relay_test_operation directive will have additional metadata }; } } - ``` ## Examples @@ -170,7 +160,6 @@ Operation with the @relay_test_operation directive will have additional metadata Using `createMockEnvironment` and `MockPayloadGenerator` allows writing concise tests for components that are using Relay Containers and Renderers. Both those modules can be imported from `relay-test-utils` ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { @@ -223,7 +212,6 @@ test('Error State', () => { renderer.root.find(item => (item.props.testID = 'errorMessage')), ).toBeDefined(); }); - ``` ### Fragment Container Tests @@ -231,7 +219,6 @@ test('Error State', () => { Essentially, in the example above will `resolveMostRecentOperation` will generate data for all child fragment containers (pagination, refetch). But, usually the Root Components container may have many child fragment components and you may want to exercise a specific Fragment Container. The solution for that would be to wrap you fragment container with the QueryRenderer that renders a Query that's spreads fragments from you fragment container. ```javascript - test('Fragment Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -262,7 +249,6 @@ test('Fragment Container', () => { expect(renderer).toMatchSnapshot(); }); - ``` ### Pagination Container Test @@ -270,7 +256,6 @@ test('Fragment Container', () => { Essentially, tests for Pagination container are not different from Fragment Container tests. But we can do more here, we can actually see how the pagination works - we can assert the behavior of our components when performing pagination (load more, refetch). ```javascript - // Pagination Example test('Pagination Container', () => { const environment = createMockEnvironment(); @@ -344,7 +329,6 @@ test('Pagination Container', () => { We can use similar approach here with wrapping container with Query Renderer. And for the sake of completeness, we will add example here: ```javascript - test('Refetch Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -386,7 +370,6 @@ test('Refetch Container', () => { ); // expect(renderer).toMatchSnapshot(); }); - ``` ### Mutations @@ -394,7 +377,6 @@ test('Refetch Container', () => { Mutations itself are operations so we can test them independently (unit-test) for specific mutation, or in combination with the view from which this mutation is called. ```javascript - // Say, you have a mutation function function sendMutation(environment, onCompleted, onError, variables) commitMutation(environment, { @@ -417,7 +399,6 @@ test('it should send mutation', () => { ); expect(onCompleted).toBeCalled(); }); - ``` ### Subscription @@ -425,7 +406,6 @@ test('it should send mutation', () => { We can test subscription in a similar way we test mutations ```javascript - // Example subscribe function function subscribe(environment, onNext, onError, variables) requestSubscription(environment, { @@ -448,7 +428,6 @@ test('it should subscribe', () => { ); expect(onNext).toBeCalled(); }); - ``` ### Example with `queueOperationResolver` @@ -456,7 +435,6 @@ test('it should subscribe', () => { With `queueOpeararionResolver` it possible to define responses for operations that will be executed on the environment ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { diff --git a/website/versioned_docs/version-v9.0.0/Modern-TypeEmission.md b/website/versioned_docs/version-v9.0.0/Modern-TypeEmission.md index 63614b869a322..4ff63e4a7d81b 100644 --- a/website/versioned_docs/version-v9.0.0/Modern-TypeEmission.md +++ b/website/versioned_docs/version-v9.0.0/Modern-TypeEmission.md @@ -16,7 +16,6 @@ In this example the emitted type-information would require the variables object #### Flow ```javascript - /** * export type ExampleQueryVariables = {| * +artistID: string @@ -44,7 +43,6 @@ const variables: ExampleQueryVariables = { #### TypeScript ```javascript - /** * export type ExampleQueryVariables = { * readonly artistID: string @@ -79,7 +77,6 @@ In this example the emitted type-information describes the response data availab #### Flow ```javascript - /** * export type ExampleQueryResponse = {| * +artist: ?{| @@ -110,7 +107,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * export type ExampleQueryResponse = { * readonly artist?: { @@ -146,7 +142,6 @@ Similarly, in this example the emitted type-information describes the prop data #### Flow ```javascript - /** * export type ExampleFragment_artist = {| * +name: string @@ -172,7 +167,6 @@ export const ExampleFragment = createFragmentContainer( #### TypeScript ```javascript - /** * export type ExampleFragment_artist = { * readonly name: string @@ -206,7 +200,6 @@ Consider a component that composes the above fragment container example. In this #### Flow ```javascript - /** * import type { FragmentReference } from "relay-runtime"; * declare export opaque type ExampleFragment_artist$ref: FragmentReference; @@ -250,7 +243,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * declare const _ExampleFragment_artist$ref: unique symbol; * export type ExampleFragment_artist$ref = typeof _ExampleFragment_artist$ref; @@ -315,7 +307,6 @@ $ relay-compiler --artifactDirectory ./src/__generated__ […] ["relay", { "artifactDirectory": "./src/__generated__" }] ] } - ``` It is recommended to alias this directory in your module resolution configuration such that you don’t need to specify relative paths in your source files. This is what is also done in the above examples, where artifacts are imported from a `__generated__` alias, rather than relative paths like `../../../../__generated__`. diff --git a/website/versioned_docs/version-v9.0.0/Modern-UpgradingSetVariables.md b/website/versioned_docs/version-v9.0.0/Modern-UpgradingSetVariables.md index d5b086fafce20..ff73feec04f8b 100644 --- a/website/versioned_docs/version-v9.0.0/Modern-UpgradingSetVariables.md +++ b/website/versioned_docs/version-v9.0.0/Modern-UpgradingSetVariables.md @@ -36,7 +36,6 @@ fragment on User { # ... } } - ``` This should be upgraded to use a [`PaginationContainer`](./pagination-container). @@ -61,7 +60,6 @@ fragment on User { # ... } } - ``` This can be upgraded by using a [`RefetchContainer`](./refetch-container) which allows you to specify the exact query to use to fetch the new data. @@ -86,7 +84,6 @@ fragment on FeedbackTarget { # ... } } - ``` This can be upgraded by conditionally rendering a [`QueryRenderer`](./query-renderer) which will load the data once it is rendered. The code overhead of doing this is dramatically reduced with the new API. diff --git a/website/versioned_docs/version-v9.0.0/Modern-fetchQuery.md b/website/versioned_docs/version-v9.0.0/Modern-fetchQuery.md index 2e9461ad527bd..c1a06ab7d2493 100644 --- a/website/versioned_docs/version-v9.0.0/Modern-fetchQuery.md +++ b/website/versioned_docs/version-v9.0.0/Modern-fetchQuery.md @@ -6,7 +6,6 @@ original_id: fetch-query You can use the `fetchQuery` function to imperatively make GraphQL Requests. This is useful for cases where you want to make requests outside of React but still utilize the Relay store and network layer. ```javascript - import {fetchQuery, graphql} from 'relay-runtime'; const query = graphql` @@ -25,7 +24,6 @@ fetchQuery(environment, query, variables) .then(data => { // access the graphql response }); - ``` ## Arguments diff --git a/website/versioned_docs/version-v9.0.0/PrinciplesAndArchitecture-Compiler.md b/website/versioned_docs/version-v9.0.0/PrinciplesAndArchitecture-Compiler.md index c195491682b1f..fcd0490cb724f 100644 --- a/website/versioned_docs/version-v9.0.0/PrinciplesAndArchitecture-Compiler.md +++ b/website/versioned_docs/version-v9.0.0/PrinciplesAndArchitecture-Compiler.md @@ -74,7 +74,6 @@ foo { # type FooType foo { id } - ``` - `SkipRedundantNodeTransform`: A more advanced version of flattening, this eliminates more complex cases of field duplication such as when a field is fetched both unconditionally and conditionally, or is fetched by two different sub-fragments. For example: @@ -97,7 +96,6 @@ foo { id } } - ``` - `GenerateRequisiteFieldTransform`: This optional, Relay-specific transform inserts `id` fields for globally identifiable objects and `__typename` fields wherever the type cannot be statically determined (e.g. for unions). diff --git a/website/versioned_docs/version-v9.0.0/PrinciplesAndArchitecture-Runtime.md b/website/versioned_docs/version-v9.0.0/PrinciplesAndArchitecture-Runtime.md index 9491d290c146f..e9221631a701d 100644 --- a/website/versioned_docs/version-v9.0.0/PrinciplesAndArchitecture-Runtime.md +++ b/website/versioned_docs/version-v9.0.0/PrinciplesAndArchitecture-Runtime.md @@ -77,7 +77,6 @@ RecordSource { city: 'Seattle', } } - ``` [1] Note that GraphQL itself does not impose this constraint, and Relay Runtime may also be used for schemas that do not conform to it. For example, both systems can be used to query a single denormalized table. However, many of the features that Relay Runtime provides, such as caching and normalization, work best when the data is represented as a normalized graph with stable identities for discrete pieces of information. diff --git a/website/versioned_docs/version-v9.0.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md b/website/versioned_docs/version-v9.0.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md index a8842ae084922..9ff8a7840df90 100644 --- a/website/versioned_docs/version-v9.0.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md +++ b/website/versioned_docs/version-v9.0.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md @@ -12,7 +12,6 @@ In this article we'll explore what it means to build a GraphQL client framework Imagine we have a simple application that fetches a list of stories, and some details about each one. Here's how that might look in resource-oriented REST: ```javascript - // Fetch the list of story IDs but not their details: rest.get('/stories').then(stories => // This resolves to a list of items with linked resources: @@ -25,13 +24,11 @@ rest.get('/stories').then(stories => // `[ { id: "...", text: "..." } ]` console.log(stories); }); - ``` Note that this approach requires _n+1_ requests to the server: 1 to fetch the list, and _n_ to fetch each item. With GraphQL we can fetch the same data in a single network request to the server (without creating a custom endpoint that we'd then have to maintain): ```javascript - graphql.get(`query { stories { id, text } }`).then( stories => { // A list of story items: @@ -39,7 +36,6 @@ graphql.get(`query { stories { id, text } }`).then( console.log(stories); } ); - ``` So far we're just using GraphQL as a more efficient version of typical REST approaches. Note two important benefits in the GraphQL version: @@ -56,7 +52,6 @@ Repeatedly refetching information from the server can get quite slow. For exampl In a resource-oriented REST system, we can maintain a **response cache** based on URIs: ```javascript - var _cache = new Map(); rest.get = uri => { if (!_cache.has(uri)) { @@ -64,13 +59,11 @@ rest.get = uri => { } return _cache.get(uri); }; - ``` Response-caching can also be applied to GraphQL. A basic approach would work similarly to the REST version. The text of the query itself can be used as a cache key: ```javascript - var _cache = new Map(); graphql.get = queryText => { if (!_cache.has(queryText)) { @@ -78,7 +71,6 @@ graphql.get = queryText => { } return _cache.get(queryText); }; - ``` Now, requests for previously cached data can be answered immediately without making a network request. This is a practical approach to improving the perceived performance of an application. However, this method of caching can cause problems with data consistency. @@ -90,7 +82,6 @@ With GraphQL it is very common for the results of multiple queries to overlap. H ``` query { stories { id, text, likeCount } } - ``` and then later refetch one of the stories whose `likeCount` has since been incremented: @@ -98,7 +89,6 @@ and then later refetch one of the stories whose `likeCount` has since been incre ``` query { story(id: "123") { id, text, likeCount } } - ``` We'll now see different `likeCount`s depending on how the story is accessed. A view that uses the first query will see an outdated count, while a view using the second query will see the updated count. @@ -119,7 +109,6 @@ query { } } } - ``` And here's a possible response: @@ -134,13 +123,11 @@ query: { } } } - ``` Although the response is hierarchical, we'll cache it by flattening all the records. Here is an example of how Relay would cache this query response: ```javascript - Map { // `story(id: "1")` 1: Map { @@ -152,7 +139,6 @@ Map { name: 'Jan', }, }; - ``` This is only a simple example: in reality the cache must handle one-to-many associations and pagination (among other things). @@ -182,7 +168,6 @@ The first query was for a list of stories: ``` query { stories { id, text, likeCount } } - ``` With a normalized response cache, a record would be created for each story in the list. The `stories` field would store links to each of these records. @@ -192,7 +177,6 @@ The second query refetched the information for one of those stories: ``` query { story(id: "123") { id, text, likeCount } } - ``` When this response is normalized, Relay can detect that this result overlaps with existing data based on its `id`. Rather than create a new record, Relay will update the existing `123` record. The new `likeCount` is therefore available to _both_ queries, as well as any other query that might reference this story. @@ -215,7 +199,6 @@ query { } } } - ``` After initially fetching this story our cache might be as follows. Note that the story and comment both link to the same record as `author`: @@ -242,7 +225,6 @@ Map { author: Link(2), }, } - ``` The author of this story also commented on it — quite common. Now imagine that some other view fetches new information about the author, and her profile photo has changed to a new URI. Here's the _only_ part of our cached data that changes: @@ -256,7 +238,6 @@ Map { photo: 'http://.../photo2.jpg', }, } - ``` The value of the `photo` field has changed; and therefore the record `2` has also changed. And that's it. Nothing else in the _cache_ is affected. But clearly our _view_ needs to reflect the update: both instances of the author in the UI (as story author and comment author) need to show the new photo. @@ -273,7 +254,6 @@ ImmutableMap { }, 3: ImmutableMap // same as before } - ``` If we replace `2` with a new immutable record, we'll also get a new immutable instance of the cache object. However, records `1` and `3` are untouched. Because the data is normalized, we can't tell that `story`'s contents have changed just by looking at the `story` record alone. @@ -299,7 +279,6 @@ mutation StoryLike($storyID: String) { likeCount } } - ``` Notice that we're querying for data that _may_ have changed as a result of the mutation. An obvious question is: why can't the server just tell us what changed? The answer is: it's complicated. GraphQL abstracts over _any_ data storage layer (or an aggregation of multiple sources), and works with any programming language. Furthermore, the goal of GraphQL is to provide data in a form that is useful to product developers building a view. diff --git a/website/versioned_docs/version-v9.0.0/PrinciplesAndArchitecture-ThinkingInRelay.md b/website/versioned_docs/version-v9.0.0/PrinciplesAndArchitecture-ThinkingInRelay.md index e61f3fd21c933..62b1914ef3ff9 100644 --- a/website/versioned_docs/version-v9.0.0/PrinciplesAndArchitecture-ThinkingInRelay.md +++ b/website/versioned_docs/version-v9.0.0/PrinciplesAndArchitecture-ThinkingInRelay.md @@ -30,13 +30,11 @@ fragment Story_story on Story { photo } } - ``` And this fragment can then be used to define the Story container: ```javascript - const {createFragmentContainer, graphql} = require('react-relay'); // Plain React component. @@ -64,7 +62,6 @@ const StoryContainer = createFragmentContainer(Story, { In React, rendering a view requires two inputs: the _component_ to render, and a _root_ DOM (UI) node to render into. Rendering Relay containers is similar: we need a _container_ to render, and a _root_ in the graph from which to start our query. We also must ensure that the queries for the container are executed and may want to show a loading indicator while data is being fetched. Similar to `ReactDOM.render(component, domNode)`, Relay provides `` for this purpose. The `query` and `variables` define what data to fetch and `render` defines what to render. Here's how we might render ``: ```javascript - ReactDOM.render( { ); } } - ``` The above code is doing something very similar to our [previous example](#rendering-graphql-queries). However, we are now passing a `$userID` variable to the GraphQL query via the `variables` prop. This has a couple of important implications: @@ -228,7 +216,6 @@ Now that we know how to define and fetch queries, let's actually start building First, let's start at the bottom. Suppose that we want to render a component that simply displays a given todo item's text and completed state: ```javascript - // Todo.js import React from 'react'; @@ -258,7 +245,6 @@ export default class Todo extends React.Component { ); } } - ``` From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L112), we know that we can query this data on the `Todo` type. However, we don't want to have to send a separate query for each todo item; that would defeat the purpose of using GraphQL over a traditional REST API. We could manually query for these fields directly in our `QueryRenderer` query, but that would hurt re-usability: what if we want to query the same set of fields as part of a different query? Additionally, we wouldn't know which component needs the data we're querying, which is a problem Relay directly tries to address. @@ -266,18 +252,15 @@ From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/dat Instead, we can define a reusable [Fragment](http://graphql.org/learn/queries/#fragments), which allows us to define a set of fields on a type and reuse them within our queries wherever we need to: ```graphql - fragment TodoItemFragment on Todo { complete text } - ``` Our component can then use this fragment to declare its data dependency on the `Todo` GraphQL type: ```javascript - // Todo.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -340,7 +323,6 @@ Before proceeding, don't forget to run the Relay Compiler with `yarn relay`. Given that [Fragment Containers](./fragment-container) are just React components, we can compose them as such. We can even re-use fragment containers within other fragment containers. As an example, let's see how we would define a `TodoList` component that just renders a list of todo items, and whether all have been completed or not: ```javascript - // TodoList.js // OPTIONAL: Flow type generated after running `yarn relay`, defining an Object type with shape of the fragment: @@ -401,7 +383,6 @@ export default createFragmentContainer( `, }, ); - ``` As with the first fragment container we defined, `TodoList` declares it's data dependencies via a fragment. However, this component additionally re-uses the fragment previously defined by the `Todo` component, and passes the appropriate data when rendering the child `Todo` components (a.k.a. fragment containers). @@ -416,7 +397,6 @@ fragment containers do not directly fetch data. Instead, containers declare a sp A `QueryRenderer` rendering these fragment containers could look like the following: ```javascript - // ViewerTodoList.js import React from 'react'; import {graphql, QueryRenderer} from 'react-relay'; @@ -457,7 +437,6 @@ export default class ViewerTodoList extends React.Component { ); } } - ``` Check out our docs for [Fragment Containers](./fragment-container) for more details, and our guides on [Refetch](./refetch-container) and [Pagination](./pagination-container) for more advanced usage of containers. @@ -469,7 +448,6 @@ Now that we know how to query for and render data, let's move on to changing our From our [schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L35), we know that we have some mutations available to us, so let's start by writing a mutation to change the `complete` status of a given todo item (i.e. mark or unmark it as done): ```graphql - mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { changeTodoStatus(input: $input) { todo { @@ -478,7 +456,6 @@ mutation ChangeTodoStatusMutation($input: ChangeTodoStatusInput!) { } } } - ``` This mutation allows us to query back some data as a [result of the mutation](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L18), so we're going to query for the updated `complete` status on the todo item. @@ -486,7 +463,6 @@ This mutation allows us to query back some data as a [result of the mutation](ht In order to execute this mutation in Relay, we're going to write a new mutation using Relay's `commitMutation` api: ```javascript - // ChangeTodoStatusMutation.js import {graphql, commitMutation} from 'react-relay'; @@ -520,7 +496,6 @@ function commit( } export default {commit}; - ``` Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mutation to the server and, in our case, upon receiving a response it will automatically update the local data store with the latest data from the server. This also means that upon receiving the response, Relay will ensure that any components (i.e. containers) that depend on the updated data are re-rendered. @@ -528,7 +503,6 @@ Whenever we call `ChangeTodoStatusMutation.commit(...)`, Relay will send the mut In order to actually use this mutation in our component, we could update our `Todo` component in the following way: ```javascript - // Todo.js // ... @@ -562,7 +536,6 @@ In order to make the experience better, we can configure our mutation to do an o In Relay, there's a couple of options we can pass to `commitMutation` to enable optimistic updates. Let's see what that would look like in our `ChangeTodoStatusMutation`: ```javascript - // ChangeTodoStatusMutation.js // ... @@ -597,7 +570,6 @@ function commit( } export default {commit}; - ``` In the simplest case above, we just need to pass an `optimisticResponse` option, which should refer to an object having the same shape as the mutation response payload. When we pass this option, Relay will know to immediately update our local data with the optimistic response, and then update it with the actual server response or roll it back if an error occurs. diff --git a/website/versioned_docs/version-v9.1.0/Modern-ConvertingMutations.md b/website/versioned_docs/version-v9.1.0/Modern-ConvertingMutations.md index 08ad2e998cb2d..8f4bdc1d8e0d2 100644 --- a/website/versioned_docs/version-v9.1.0/Modern-ConvertingMutations.md +++ b/website/versioned_docs/version-v9.1.0/Modern-ConvertingMutations.md @@ -12,19 +12,16 @@ FatQueries in Relay Classic mutations was a concept that was confusing for a num Example of existing fat query: ```javascript - RelayClassic.QL` fragment on MarkReadNotificationResponsePayload @relay(pattern: true) { notification } `; - ``` Example of converted mutation query: ```javascript - graphql` mutation MarkReadNotificationMutation( $input: MarkReadNotificationData! @@ -37,7 +34,6 @@ graphql` } } `; - ``` ## Migrating Configs @@ -67,7 +63,6 @@ This is no longer needed in Compatibility Mode for neither environments. Simply Take this example of a simple mutation in Relay Classic: ```javascript - class LikeStoryMutation extends RelayClassic.Mutation { getMutation() { return RelayClassic.QL`mutation {likeStory}`; @@ -106,7 +101,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { `, }; } - ``` ### Converting `getMutation()` and `getFatQuery()` @@ -114,7 +108,6 @@ class LikeStoryMutation extends RelayClassic.Mutation { We combine these two into a regular GraphQL mutation, which list out specific fields that needs to be updated. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story(data: $input) { @@ -126,7 +119,6 @@ const mutation = graphql` } } `; - ``` ### Converting `getConfigs()` @@ -138,13 +130,11 @@ As specified above, `FIELDS_CHANGE` configs can be omitted. To convert `getVariables()`, we take the return value from the original function and wrap it in an object that contains a property that matches the variable name for the mutation. In this case, the mutation has a `input` variable that is of type `LikeStoryData`. ```javascript - const variables = { input: { storyID: args.storyID } } - ``` ### Final Result @@ -152,7 +142,6 @@ const variables = { As you can see, our resulting mutation is a lot simpler and more like regular GraphQL than the Relay Classic version we started out with. ```javascript - const mutation = graphql` mutation LikeStoryMutation($input: LikeStoryData!) { story { @@ -178,7 +167,6 @@ function commit(environment: CompatEnvironment, args) { variables, }); } - ``` See [Mutation](./mutations) for additional options on `commitMutation` for more complex mutations. diff --git a/website/versioned_docs/version-v9.1.0/Modern-FragmentContainer.md b/website/versioned_docs/version-v9.1.0/Modern-FragmentContainer.md index 423f446cbb054..6a40bbcfb5d0a 100644 --- a/website/versioned_docs/version-v9.1.0/Modern-FragmentContainer.md +++ b/website/versioned_docs/version-v9.1.0/Modern-FragmentContainer.md @@ -17,12 +17,10 @@ Table of Contents: `createFragmentContainer` has the following signature: ```javascript - createFragmentContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, ): ReactComponentClass; - ``` ### Arguments @@ -43,7 +41,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -58,7 +55,6 @@ To start, let's build the plain React version of a hypothetical `` c Here's a basic implementation of `` that ignores styling in order to highlight the functionality: ```javascript - // TodoItem.js class TodoItem extends React.Component { render() { @@ -78,7 +74,6 @@ class TodoItem extends React.Component { ); } } - ``` ### Data Dependencies With GraphQL @@ -86,7 +81,6 @@ class TodoItem extends React.Component { In Relay, data dependencies are described using [GraphQL](https://github.com/facebook/graphql). For ``, the dependency can be expressed as follows. Note that this exactly matches the shape that the component expected for the `item` prop. ```javascript - graphql` # This fragment only applies to objects of type 'Todo'. fragment TodoItem_item on Todo { @@ -102,7 +96,6 @@ graphql` Given the plain React component and a GraphQL fragment, we can now define a Fragment Container to specify this component's data requirements. Let's look at the code first and then see what's happening: ```javascript - // TodoItem.js import {createFragmentContainer, graphql} from 'react-relay'; @@ -120,7 +113,6 @@ export default createFragmentContainer(TodoItem, { } `, }); - ``` ## Container Composition @@ -134,7 +126,6 @@ Let's explore how this works via a `` component that composes the `< View composition is _exactly_ what you're used to — Relay containers are just standard React components. Here's the `` component: ```javascript - class TodoList extends React.Component { render() { // Expects a `list` with a string `title`, as well as the information @@ -151,7 +142,6 @@ class TodoList extends React.Component { ); } } - ``` ### Composing Fragments @@ -159,7 +149,6 @@ class TodoList extends React.Component { Fragment composition works similarly — a parent container's fragment composes the fragment for each of its children. In this case, `` needs to fetch information about the `Todo`s that are required by ``. ```javascript - class TodoList extends React.Component // as above export default createFragmentContainer(TodoList, { @@ -176,7 +165,6 @@ export default createFragmentContainer(TodoList, { } `, }); - ``` Note that when composing fragments, the type of the composed fragment must match the field on the parent in which it is embedded. For example, it wouldn't make sense to embed a fragment of type `Story` into a parent's field of type `User`. Relay and GraphQL will provide helpful error messages if you get this wrong (and if they aren't helpful, let us know!). @@ -190,7 +178,6 @@ When defining a fragment, you can use the [`@argumentDefinitions`](./graphql-in- For example, let's redefine our `TodoList_list` fragment to take some arguments using `@argumentDefinitions`: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -200,7 +187,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` Any arguments defined inside `@argumentDefinitions` will be local variables available inside the fragment's scope. However, a fragment can also reference global variables that were defined in the root query. @@ -212,11 +198,9 @@ In order to pass arguments to a fragment that has `@argumentDefinitions`, you ne Following our `TodoList_list` example, we would pass arguments to the fragment like so: ```graphql - query TodoListQuery($count: Int, $userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` ## Rendering Containers diff --git a/website/versioned_docs/version-v9.1.0/Modern-GraphQLInRelay.md b/website/versioned_docs/version-v9.1.0/Modern-GraphQLInRelay.md index c4dc8f3463e53..715b119492cc7 100644 --- a/website/versioned_docs/version-v9.1.0/Modern-GraphQLInRelay.md +++ b/website/versioned_docs/version-v9.1.0/Modern-GraphQLInRelay.md @@ -14,7 +14,6 @@ Table of Contents: The `graphql` template tag provided by Relay serves as the mechanism to write queries, fragments, mutations or subscriptions in the [GraphQL](http://graphql.org/learn/) language. For example: ```javascript - import {graphql} from 'react-relay'; graphql` @@ -24,7 +23,6 @@ graphql` } } `; - ``` The result of using the `graphql` template tag is a `GraphQLTaggedNode`; a runtime representation of the GraphQL document which can be used to define [Query Renderers](./query-renderer), [Fragment Containers](./fragment-container), [Refetch Containers](./refetch-container), [Pagination Containers](./pagination-container), etc. @@ -42,11 +40,9 @@ Relay uses directives to add additional information to GraphQL documents, which `@arguments` is a directive used to pass arguments to a fragment that was defined using [`@argumentDefinitions`](#argumentdefinitions). For example: ```graphql - query TodoListQuery($userID: ID) { ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here } - ``` See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -56,7 +52,6 @@ See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fr `@argumentDefinitions` is a directive used to specify arguments taken by a fragment. For example: ```graphql - fragment TodoList_list on TodoList @argumentDefinitions( count: {type: "Int", defaultValue: 10}, # Optional argument userID: {type: "ID"}, # Required argument @@ -66,7 +61,6 @@ fragment TodoList_list on TodoList @argumentDefinitions( ...TodoItem_item } } - ``` See the [Fragment Container docs](./fragment-container#passing-arguments-to-a-fragment) for more details. @@ -80,7 +74,6 @@ When using the [Pagination Container](./pagination-container), Relay expects con When defining a fragment for use with a Fragment container, you can use the `@relay(plural: true)` directive to indicate that container expects the prop for that fragment to be a list of items instead of a single item. A query or parent that spreads a `@relay(plural: true)` fragment should do so within a plural field (ie a field backed by a [GraphQL list](http://graphql.org/learn/schema/#lists-and-non-null). For example: ```javascript - // Plural fragment definition graphql` fragment TodoItems_items on TodoItem @relay(plural: true) { @@ -95,7 +88,6 @@ fragment TodoApp_app on App { ...TodoItem_items } } - ``` ### `@inline` @@ -107,7 +99,6 @@ Non-React functions can also take advantage of data masking. A fragment can be d In the example below, the function `processItemData` is called from a React component. It requires an item object with a specific set of fields. All React components that use this function should spread the `processItemData_item` fragment to ensure all of the correct item data is loaded for this function. ```javascript - import {graphql, readInlineData} from 'react-relay'; // non-React function called from React @@ -127,11 +118,9 @@ function processItemData(itemRef) { creatorName: item.creator.name }); } - ``` ```javascript - // React Component function MyComponent({item}) { function handleClick() { @@ -151,7 +140,6 @@ export default createFragmentContainer(MyComponent, { } ` }); - ``` ### `@relay(mask: Boolean)` @@ -169,7 +157,6 @@ Keep in mind that it is typically considered an **anti-pattern** to create a sin In the example below, the `user` prop will include the data for `id` and `name` fields wherever `...Component_internUser` is included, instead of Relay's normal behavior to mask those fields: ```javascript - graphql` fragment Component_internUser on InternUser @relay(mask: false) { id @@ -197,7 +184,6 @@ export default createFragmentContainer( } `, ); - ``` ## Relay Compiler @@ -207,7 +193,6 @@ Relay uses the Relay Compiler to convert [`graphql`](#graphql) literals into gen A query like the following: ```javascript - graphql` fragment MyComponent on Type { field @@ -228,12 +213,10 @@ Relay Compiler supports the use of **persisted queries**, in which each version Persisted queries can be enabled by instructing Relay Compiler to emit metadata about each query, mutation, and subscription into a JSON file. The generated file will contain a mapping of query identifiers to query text, which you can then save to your server. To enable persisted queries, use the `--persist-output` flag to the compiler: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` Relay Compiler will then create the id => query text mapping in the path you specify. You can then use this complete @@ -250,7 +233,6 @@ See our relay-compiler section in our [Installation and Setup guide](./installat To use the Relay Compiler, you need either a .graphql or .json GraphQL schema file, describing your GraphQL server's API. Typically these files are local representations of a server source of truth and are not edited directly. For example, we might have a `schema.graphql` like: ```graphql - schema { query: Root } @@ -268,7 +250,6 @@ type WordDefinition { text: String image: String } - ``` ### Source files @@ -284,7 +265,6 @@ For example, given the two files: - `src/Components/DictionaryComponent.js` ```javascript - const DictionaryWordFragment = graphql` fragment DictionaryComponent_word on Word { id @@ -306,7 +286,6 @@ For example, given the two files: - `src/Queries/DictionaryQuery.js` ```javascript - const DictionaryQuery = graphql` query DictionaryQuery { dictionary { @@ -330,9 +309,7 @@ Typically you will not need to import your generated definitions. The [Relay Bab However the Relay Compiler also automatically generates [Flow](https://flow.org) types as [type comments](https://flow.org/en/docs/types/comments/). For example, you can import the generated Flow types like so: ```javascript - import type {DictionaryComponent_word} from './__generated__/DictionaryComponent_word.graphql'; - ``` ### Client schema extensions @@ -342,7 +319,6 @@ The Relay Compiler fully supports client-side schema extensions, which allows yo For example, assuming the server schema `./schema.graphql`: ```graphql - schema { query: Root } @@ -350,28 +326,23 @@ schema { type Root { title: String! } - ``` We can create a `./src/clientSchema.graphql` and define a new type called `Setting`: ```graphql - type Setting { name: String! active: Boolean! } - ``` We can then extend existing server types in the client schema `./src/clientSchema.graphql` with our new `Setting` type, like so: ```graphql - extend type Root { settings: [Setting] } - ``` Any fields specified in the client schema, can be fetched from the [Relay Store](./relay-store), by selecting it in a query or fragment. diff --git a/website/versioned_docs/version-v9.1.0/Modern-LocalStateManagement.md b/website/versioned_docs/version-v9.1.0/Modern-LocalStateManagement.md index 19a1cbf61add1..008eb81d02b52 100644 --- a/website/versioned_docs/version-v9.1.0/Modern-LocalStateManagement.md +++ b/website/versioned_docs/version-v9.1.0/Modern-LocalStateManagement.md @@ -24,23 +24,19 @@ It can even be used to extend an existing server schema. For example, we can create a new type called `Note`: ```graphql - type Note { ID: ID! title: String body: String } - ``` And then extend the server schema type `User`, with a list of `Note`, called `notes`. ```graphql - extend type User { notes: [Note] } - ``` ## Querying local state @@ -51,7 +47,6 @@ The field can be from the server schema, or it can be schema agnostic, like an i Here, we use a [QueryRenderer](./query-renderer) to get the current `User` via the `viewer` field, along with their id, name and the local list of notes. ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -97,7 +92,6 @@ const Example = (props) => { /> ); } - ``` ## Mutating local state @@ -111,7 +105,6 @@ To build upon the previous example, let's try creating, updating and deleting a ### Create ```javascript - import {commitLocalUpdate} from 'react-relay'; let tempID = 0; @@ -131,7 +124,6 @@ function createUserNote() { user.setLinkedRecords([...userNoteRecords, newNoteRecord], 'notes'); }); } - ``` Note that since this record will be rendered by the `ExampleQuery` in our `QueryRenderer`, the QueryRenderer will automatically retain this data so it isn't garbage collected. @@ -139,7 +131,6 @@ Note that since this record will be rendered by the `ExampleQuery` in our `Query If no component is rendering the local data and you want to manually retain it, you can do so by calling `environment.retain()`: ```javascript - import {createOperationDescriptor, getRequest} from 'relay-runtime'; // Create a query that references that record @@ -166,13 +157,11 @@ const disposable = environment.retain(operation); // Whenever you don't need that data anymore and it's okay for Relay to garbage collect it, // you can dispose of the retain disposable.dispose(); - ``` ### Update ```javascript - import {commitLocalUpdate} from 'react-relay'; function updateUserNote(dataID, body, title) { @@ -183,13 +172,11 @@ function updateUserNote(dataID, body, title) { note.setValue(title, 'title') }); } - ``` ### Delete ```javascript - import {commitLocalUpdate} from 'react-relay'; function deleteUserNote(dataID) { @@ -207,7 +194,6 @@ function deleteUserNote(dataID) { user.setLinkedRecords(newUserNoteRecords, 'notes'); }); } - ``` ## Initial local state @@ -216,7 +202,6 @@ All new client-side schema fields default to `undefined` value. Often however, y You can use an updater function via `commitLocalUpdate` to prime local state. ```javascript - import {commitLocalUpdate} from 'react-relay'; commitLocalUpdate(environment, store => { @@ -225,5 +210,4 @@ commitLocalUpdate(environment, store => { // initialize user notes to an empty array. user.setLinkedRecords([], 'notes'); }); - ``` diff --git a/website/versioned_docs/version-v9.1.0/Modern-MigrationSetup.md b/website/versioned_docs/version-v9.1.0/Modern-MigrationSetup.md index 66f1145357e25..a89c0e178e0e5 100644 --- a/website/versioned_docs/version-v9.1.0/Modern-MigrationSetup.md +++ b/website/versioned_docs/version-v9.1.0/Modern-MigrationSetup.md @@ -13,13 +13,11 @@ With some additional configuration, the `"relay"` babel plugin can also translat Relay Classic `Relay.QL` literals. Most importantly, include a reference to your GraphQL Schema as either a json file or graphql schema file. ```javascript - { "plugins": [ ["relay", {"schema": "path/schema.graphql"}] ] } - ``` ## Set up babel-plugin-relay for "[compatibility mode](./relay-compat)" @@ -29,13 +27,11 @@ literals can be translated to be usable by _both_ runtimes if configured to use compatibility mode: ```javascript - { "plugins": [ ["relay", {"compat": true, "schema": "path/schema.graphql"}] ] } - ``` ## Additional Options @@ -47,7 +43,6 @@ thrown at runtime. When compiling code for production deployment, the plugin can be configured to immediately throw upon encountering a validation problem. The plugin can be further customized for different environments with the following options: ```javascript - { "plugins": [ ["relay", { @@ -56,5 +51,4 @@ When compiling code for production deployment, the plugin can be configured to i }] ] } - ``` diff --git a/website/versioned_docs/version-v9.1.0/Modern-Mutations.md b/website/versioned_docs/version-v9.1.0/Modern-Mutations.md index 78b4df76e1b61..36e9ae0875ff5 100644 --- a/website/versioned_docs/version-v9.1.0/Modern-Mutations.md +++ b/website/versioned_docs/version-v9.1.0/Modern-Mutations.md @@ -17,7 +17,6 @@ Table of Contents: Use `commitMutation` to create and execute mutations. `commitMutation` has the following signature: ```javascript - commitMutation( environment: Environment, config: { @@ -31,7 +30,6 @@ commitMutation( configs?: Array, }, ); - ``` ### Arguments @@ -58,7 +56,6 @@ commitMutation( Example of a simple mutation: ```javascript - import {commitMutation, graphql} from 'react-relay'; const mutation = graphql` @@ -90,7 +87,6 @@ function markNotificationAsRead(environment, storyID) { }, ); } - ``` ## Optimistic Updates @@ -98,7 +94,6 @@ function markNotificationAsRead(environment, storyID) { To improve perceived responsiveness, you may wish to perform an "optimistic update", in which the client immediately updates to reflect the anticipated new value even before the response from the server has come back. The simplest way to do this is by providing an `optimisticResponse` and adding it to the `config` that we pass into `commitMutation`: ```javascript - const mutation = graphql` mutation MarkReadNotificationMutation( $storyID: ID! @@ -127,7 +122,6 @@ commitMutation( variables, }, ); - ``` Another way to enable optimistic updates is via the `optimisticUpdater`, which can be used for more complicated update scenarios. Using `optimisticUpdater` is covered in the section [below](#using-updater-and-optimisticupdater). @@ -149,7 +143,6 @@ Given a deletedIDFieldName, Relay will remove the node(s) from the store. #### Example ```javascript - const mutation = graphql` mutation DestroyShipMutation($target: ID!) { destroyShip(target: $target) { @@ -167,7 +160,6 @@ const configs = [{ type: 'NODE_DELETE', deletedIDFieldName: 'destroyedShipId', }]; - ``` ### RANGE_ADD @@ -187,7 +179,6 @@ Given a parent, information about the connection, and the name of the newly crea #### Example ```javascript - const mutation = graphql` mutation AddShipMutation($factionID: ID!, $name: String!) { addShip(factionID: $factionID, name: $name) { @@ -218,7 +209,6 @@ function commit(environment, factionID, name) { }], }); } - ``` ### RANGE_DELETE @@ -240,7 +230,6 @@ from the connection but leave the associated record(s) in the store. #### Example ```javascript - const mutation = graphql` mutation RemoveTagMutation($todoID: ID!, $tagID: ID!) { removeTag(todo: $todoID, tag: $tagID) { @@ -267,7 +256,6 @@ function commit(environment, todoID, tagID) { }], }); } - ``` ## Using updater and optimisticUpdater @@ -285,7 +273,6 @@ When you provide these functions, this is roughly what happens during the mutati Here are a quick example of adding a todo item to a Todo list using this [example schema](https://github.com/relayjs/relay-examples/blob/master/todo/data/schema.graphql#L36): ```javascript - // AddTodoMutation.js import {commitMutation, graphql} from 'react-relay'; import {ConnectionHandler} from 'relay-runtime'; @@ -369,7 +356,6 @@ function commit(environment, text, user) { }, }); } - ``` For details on how to interact with the Relay Store, please refer to our Relay Store [docs](./relay-store). diff --git a/website/versioned_docs/version-v9.1.0/Modern-NetworkLayer.md b/website/versioned_docs/version-v9.1.0/Modern-NetworkLayer.md index 9dddd36d6c235..c9e069b812b01 100644 --- a/website/versioned_docs/version-v9.1.0/Modern-NetworkLayer.md +++ b/website/versioned_docs/version-v9.1.0/Modern-NetworkLayer.md @@ -8,7 +8,6 @@ In order to know how to access your GraphQL server, Relay Modern requires develo Currently the easiest way to create a network layer is via a helper from the `relay-runtime` package: ```javascript - import { Environment, Network, @@ -50,7 +49,6 @@ const environment = new Environment({ }); export default environment; - ``` Note that this is a basic example to help you get started. This example could be extended with additional features such as request/response caching (enabled e.g. when `cacheConfig.force` is false) and uploading form data for mutations (the `uploadables` parameter). @@ -62,7 +60,6 @@ Relay modern makes no assumptions about what to cache and will garbage collect a You have to implement your own cache strategy. A simple solution is to use `QueryResponseCache` (an in-memory cache): ```javascript - import { Environment, Network, @@ -126,7 +123,6 @@ const environment = new Environment({ }); export default environment; - ``` ## Custom open-source implementations diff --git a/website/versioned_docs/version-v9.1.0/Modern-PaginationContainer.md b/website/versioned_docs/version-v9.1.0/Modern-PaginationContainer.md index 6ac3aac8cfb8e..57980d553af9b 100644 --- a/website/versioned_docs/version-v9.1.0/Modern-PaginationContainer.md +++ b/website/versioned_docs/version-v9.1.0/Modern-PaginationContainer.md @@ -24,7 +24,6 @@ However, when [specifying connection fragments](#createpaginationcontainer) for The purpose of the `@connection` directive is to allow Relay to uniquely identify different connections under a parent type. The `@connection` directive takes 2 arguments that help identify the connection: ```graphql - @connection(key: String!, filters: [String]) ``` @@ -37,7 +36,6 @@ The purpose of the `@connection` directive is to allow Relay to uniquely identif Specifying just the `key`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and the value of `$orderBy` (given that no `filters` were provided) @@ -53,13 +51,11 @@ fragment Feed_user on User { } } } - ``` Specifying `key` and `filters`: ```javascript - fragment Feed_user on User { # This connection, under a specific User, will be uniquely identified by # the key "Feed_feed" and /only/ the value of `$searchTerm`, i.e. @@ -77,7 +73,6 @@ fragment Feed_user on User { } } } - ``` ## `createPaginationContainer` @@ -85,7 +80,6 @@ fragment Feed_user on User { `createPaginationContainer` has the following signature: ```javascript - createPaginationContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, @@ -113,7 +107,6 @@ type ConnectionData = { startCursor: ?string, }, }; - ``` ### Arguments @@ -134,7 +127,6 @@ type ConnectionData = { The Component resulting from `createPaginationContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -145,7 +137,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -160,7 +151,6 @@ type Props = { `hasMore` is a function available on the `relay` [prop](#available-props). This function indicates whether there are more pages to fetch from the server or not. ```javascript - hasMore: () => boolean, ``` @@ -170,7 +160,6 @@ hasMore: () => boolean, `isLoading` is a function available on the `relay` [prop](#available-props). This function indicates if a previous call to [`loadMore()`](#loadmore) is still pending. This is convenient for avoiding duplicate load calls. ```javascript - isLoading: () => boolean, ``` @@ -180,7 +169,6 @@ isLoading: () => boolean, `loadMore` is a function available on the `relay` [prop](#available-props). You can call `loadMore()` to fetch more items from the server based on the `connectionConfig` provided to the container. This will return null if there are no more items to fetch, otherwise it will fetch more items and return a Disposable that can be used to cancel the fetch. ```javascript - loadMore( pageSize: number, callback: ?(error: ?Error) => void, @@ -201,7 +189,6 @@ loadMore( `refetchConnection` is a function available on the `relay` [prop](#available-props). You can call `refetchConnection` to restart pagination on a connection from scratch, with optionally a completely new set of variables to pass to the pagination `query`. This is useful for example if you are paginating over a collection based on a userID and the userID changes, you'd want to start paginating over the new collection for the new user. ```javascript - refetchConnection:( totalCount: number, callback: (error: ?Error) => void, @@ -219,7 +206,6 @@ refetchConnection:( ## Pagination Example ```javascript - // Feed.js import {createPaginationContainer, graphql} from 'react-relay'; @@ -314,5 +300,4 @@ module.exports = createPaginationContainer( ` } ); - ``` diff --git a/website/versioned_docs/version-v9.1.0/Modern-PersistedQueries.md b/website/versioned_docs/version-v9.1.0/Modern-PersistedQueries.md index 137cc2e23220c..ec03b69ba09c3 100644 --- a/website/versioned_docs/version-v9.1.0/Modern-PersistedQueries.md +++ b/website/versioned_docs/version-v9.1.0/Modern-PersistedQueries.md @@ -17,12 +17,10 @@ The relay compiler supports persisted queries which is useful because: In your `npm` script in `package.json`, run the relay compiler using the `--persist-output` flag: -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./path/to/persisted-queries.json" } - ``` The `--persist-ouput` flag does 3 things: @@ -31,8 +29,7 @@ The `--persist-ouput` flag does 3 things: For example without `--persist-output`, a generated `ConcreteRequest` might look like below: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -49,8 +46,7 @@ The `--persist-ouput` flag does 3 things: With `--persist-output ` this becomes: - ```js - + ```javascript const node/*: ConcreteRequest*/ = (function(){ //... excluded for brevity return { @@ -68,12 +64,10 @@ The `--persist-ouput` flag does 3 things: 2. It generates a JSON file at the `` you specify containing a mapping from query ids to the corresponding operation texts. -```js - +```javascript "scripts": { "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-output ./src/queryMaps/queryMap.json" } - ``` The example above writes the complete query map file to `./src/queryMaps/queryMap.json`. You need to ensure all the directories @@ -83,8 +77,7 @@ leading to the `queryMap.json` file exist. You'll need to modify your network layer fetch implementation to pass a documentId parameter in the POST body instead of a query parameter: -```js - +```javascript function fetchQuery(operation, variables,) { return fetch('/graphql', { method: 'POST', @@ -100,7 +93,6 @@ function fetchQuery(operation, variables,) { return response.json(); }); } - ``` ## Executing Persisted Queries on the Server @@ -116,13 +108,11 @@ the query map file in a common location accessible to both the client and the se For applications where the client and server projects are separate, one option is to have an additional npm run script to push the query map at compile time to a location accessible by your server: -```js - +```javascript "scripts": { "push-queries": "node ./pushQueries.js", "relay": "relay-compiler --src ./src --schema ./schema.graphql --persist-ouput && npm run push-queries" } - ``` Some possibilities of what you can do in `./pushQueries.js`: @@ -146,8 +136,7 @@ database technologies you use, so we'll just cover the most common and basic exa If you use `express-graphql` and have access to the query map file, you can import the `--persist-output` JSON file directly and perform the matching using the `matchQueryMiddleware` from [relay-compiler-plus](https://github.com/yusinto/relay-compiler-plus). -```js - +```javascript import Express from 'express'; import expressGraphql from 'express-graphql'; import {matchQueryMiddleware} from 'relay-compiler-plus'; @@ -158,7 +147,6 @@ const app = Express(); app.use('/graphql', matchQueryMiddleware(queryMapJson), expressGraphql({schema})); - ``` ## Using `--persist-output` and `--watch` diff --git a/website/versioned_docs/version-v9.1.0/Modern-QueryRenderer.md b/website/versioned_docs/version-v9.1.0/Modern-QueryRenderer.md index cf6c37f3d9a4d..b621ef9986bf1 100644 --- a/website/versioned_docs/version-v9.1.0/Modern-QueryRenderer.md +++ b/website/versioned_docs/version-v9.1.0/Modern-QueryRenderer.md @@ -24,7 +24,6 @@ However, a `QueryRenderer` will not start loading its data until it is mounted, ## Example ```javascript - // Example.js import React from 'react'; import { QueryRenderer, graphql } from 'react-relay'; @@ -56,5 +55,4 @@ const Example = (props) => { /> ); } - ``` diff --git a/website/versioned_docs/version-v9.1.0/Modern-RefetchContainer.md b/website/versioned_docs/version-v9.1.0/Modern-RefetchContainer.md index 7ce0d14e45417..51c2c44db8941 100644 --- a/website/versioned_docs/version-v9.1.0/Modern-RefetchContainer.md +++ b/website/versioned_docs/version-v9.1.0/Modern-RefetchContainer.md @@ -16,13 +16,11 @@ Table of Contents: `createRefetchContainer` has the following signature: ```javascript - createRefetchContainer( component: ReactComponentClass, fragmentSpec: {[string]: GraphQLTaggedNode}, refetchQuery: GraphQLTaggedNode, ): ReactComponentClass; - ``` ### Arguments @@ -37,7 +35,6 @@ createRefetchContainer( The Component resulting from `createRefetchContainer` will receive the following `props`: ```javascript - type Props = { relay: { environment: Environment, @@ -45,7 +42,6 @@ type Props = { }, // Additional props as specified by the fragmentSpec } - ``` - `relay`: @@ -61,7 +57,6 @@ type Props = { `refetch` has the following signature: ```javascript - type RefetchOptions = { force?: boolean, }; @@ -102,7 +97,6 @@ Returns a `Disposable` on which you could call `dispose()` to cancel the refetch In this simple example, let's assume we want to fetch the latest data for a `TodoItem` from the server: ```javascript - // TodoItem.js import {createRefetchContainer, graphql} from 'react-relay'; @@ -148,7 +142,6 @@ export default createRefetchContainer( } ` ); - ``` ### Loading more data @@ -156,7 +149,6 @@ export default createRefetchContainer( In this example we are using a Refetch Container to fetch more stories in a story feed component. ```javascript - import {createRefetchContainer, graphql} from 'react-relay'; class FeedStories extends React.Component { @@ -212,5 +204,4 @@ export default createRefetchContainer( } `, ); - ``` diff --git a/website/versioned_docs/version-v9.1.0/Modern-RelayCompat.md b/website/versioned_docs/version-v9.1.0/Modern-RelayCompat.md index 36632d3a8f1a1..f47dbd845ba3e 100644 --- a/website/versioned_docs/version-v9.1.0/Modern-RelayCompat.md +++ b/website/versioned_docs/version-v9.1.0/Modern-RelayCompat.md @@ -31,7 +31,6 @@ Relay Modern. The components using Relay Compat can be referred to by both other Relay Modern and Relay Classic components. ```javascript - const {createFragmentContainer, graphql} = require('react-relay/compat'); class TodoItem extends React.Component { @@ -47,5 +46,4 @@ module.exports = createFragmentContainer(TodoItem, graphql` isComplete } `); - ``` diff --git a/website/versioned_docs/version-v9.1.0/Modern-RelayEnvironment.md b/website/versioned_docs/version-v9.1.0/Modern-RelayEnvironment.md index 27d90b2fc4fe1..99e728bce740d 100644 --- a/website/versioned_docs/version-v9.1.0/Modern-RelayEnvironment.md +++ b/website/versioned_docs/version-v9.1.0/Modern-RelayEnvironment.md @@ -12,7 +12,6 @@ Most applications will create a single Environment instance and use it throughou To create an environment instance in Relay Modern, use the `RelayModernEnvironment` class: ```javascript - const { Environment, Network, @@ -30,7 +29,6 @@ const environment = new Environment({ network, store, }); - ``` For more details on creating a Network, see the [NetworkLayer guide](./network-layer). @@ -44,7 +42,6 @@ The example above did not configure a `handlerProvider`, which means that a defa If you wish to provide your own `handlerProvider`, you can do so: ```javascript - const { ConnectionHandler, } = require('relay-runtime'); @@ -58,5 +55,4 @@ function handlerProvider(handle) { `handlerProvider: No handler provided for ${handle}` ); } - ``` diff --git a/website/versioned_docs/version-v9.1.0/Modern-RelayStore.md b/website/versioned_docs/version-v9.1.0/Modern-RelayStore.md index 3457960655342..3d552f6035f50 100644 --- a/website/versioned_docs/version-v9.1.0/Modern-RelayStore.md +++ b/website/versioned_docs/version-v9.1.0/Modern-RelayStore.md @@ -16,7 +16,6 @@ Table of Contents: The `RecordSourceSelectorProxy` is the type of the `store` that [`updater` functions](./mutations#using-updater-and-optimisticupdater) receive as an argument. The following is the `RecordSourceSelectorProxy` interface: ```javascript - interface RecordSourceSelectorProxy { create(dataID: string, typeName: string): RecordProxy; delete(dataID: string): void; @@ -26,7 +25,6 @@ interface RecordSourceSelectorProxy { getPluralRootField(fieldName: string): ?Array; invalidateStore(): void; } - ``` ### `create(dataID: string, typeName: string): RecordProxy` @@ -36,9 +34,7 @@ Creates a new record in the store given a `dataID` and the `typeName` as defined #### Example ```javascript - const record = store.create(dataID, 'Todo'); - ``` ### `delete(dataID: string): void` @@ -48,9 +44,7 @@ Deletes a record from the store given its `dataID`. #### Example ```javascript - store.delete(dataID); - ``` ### `get(dataID: string): ?RecordProxy` @@ -60,9 +54,7 @@ Retrieves a record from the store given its `dataID`. Returns a [`RecordProxy`]( #### Example ```javascript - const record = store.get(dataID); - ``` ### `getRoot(): RecordProxy` @@ -74,20 +66,16 @@ Returns the [`RecordProxy`](#recordproxy) representing the root of the GraphQL d Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - // Represents root query const root = store.getRoot(); - ``` ### `getRootField(fieldName: string): ?RecordProxy` @@ -99,19 +87,15 @@ Retrieves a root field from the store given the `fieldName`, as defined by the G Given the GraphQL document: ```graphql - viewer { id } - ``` Usage: ```javascript - const viewer = store.getRootField('viewer'); - ``` ### `getPluralRootField(fieldName: string): ?Array` @@ -123,19 +107,15 @@ Retrieves a root field that represents a collection from the store given the `fi Given the GraphQL document: ```graphql - nodes(first: 10) { # ... } - ``` Usage: ```javascript - const nodes = store.getPluralRootField('nodes'); - ``` ### `invalidateStore(): void` @@ -145,15 +125,12 @@ Globally invalidates the Relay store. This will cause any data that was written #### Example ```javascript - store.invalidateStore(); - ``` After global invalidation, any query that is checked before refetching it will be considered stale: ```javascript - environment.check(query) === 'stale' ``` @@ -163,7 +140,6 @@ environment.check(query) === 'stale' The `RecordProxy` serves as an interface to mutate records: ```javascript - interface RecordProxy { copyFieldsFrom(sourceRecord: RecordProxy): void; getDataID(): string; @@ -189,7 +165,6 @@ interface RecordProxy { setValue(value: mixed, name: string, arguments?: ?Object): RecordProxy; invalidateRecord(): void; } - ``` ### `getDataID(): string` @@ -199,9 +174,7 @@ Returns the dataID of the current record. #### Example ```javascript - const id = record.getDataID(); - ``` ### `getType(): string` @@ -211,7 +184,6 @@ Gets the type of the current record, as defined by the GraphQL schema. #### Example ```javascript - const type = user.getType(); // User ``` @@ -225,20 +197,16 @@ Gets the value of a field in the current record given the field name. Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - const name = viewer.getValue('name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. @@ -248,20 +216,16 @@ Optionally, if the field takes arguments, you can pass a bag of `variables`. Given the GraphQL document: ```graphql - viewer { id name(arg: $arg) } - ``` Usage: ```javascript - const name = viewer.getValue('name', {arg: 'value'}); - ``` ### `getLinkedRecord(name: string, arguments?: ?Object): ?RecordProxy` @@ -273,23 +237,19 @@ Retrieves a record associated with the current record given the field name, as d Given the GraphQL document: ```graphql - rootField { viewer { id name } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -299,22 +259,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { viewer(arg: $arg) { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {arg: 'value'}); - ``` ### `getLinkedRecords(name: string, arguments?: ?Object): ?Array` @@ -326,22 +282,18 @@ Retrieves the set of records associated with the current record given the field Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const nodes = rootField.getLinkedRecords('nodes'); - ``` Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well. @@ -351,22 +303,18 @@ Optionally, if the linked record takes arguments, you can pass a bag of `variabl Given the GraphQL document: ```graphql - rootField { nodes(first: $count) { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const viewer = rootField.getLinkedRecord('viewer', {count: 10}); - ``` ### `getOrCreateLinkedRecord(name: string, typeName: string, arguments?: ?Object)` @@ -378,19 +326,16 @@ Retrieves the a record associated with the current record given the field name, Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = rootField.getOrCreateLinkedRecord('viewer', 'User'); // Will create if it doesn't exist @@ -405,28 +350,22 @@ Mutates the current record by setting a new value on the specified field. Return Given the GraphQL document: ```graphql - viewer { id name } - ``` Usage: ```javascript - viewer.setValue('New Name', 'name'); - ``` Optionally, if the field takes arguments, you can pass a bag of `variables`. ```javascript - viewer.setValue('New Name', 'name', {arg: 'value'}); - ``` ### `copyFieldsFrom(sourceRecord: RecordProxy): void` @@ -436,7 +375,6 @@ Mutates the current record by copying the fields over from the passed in record #### Example ```javascript - const record = store.get(id1); const otherRecord = store.get(id2); record.copyFieldsFrom(otherRecord); // Mutates `record` @@ -452,19 +390,16 @@ Mutates the current record by setting a new linked record on the given the field Given the GraphQL document: ```graphql - rootField { viewer { id } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newViewer = store.create(/* ... */)'' rootField.setLinkedRecord(newViewer, 'viewer'); // @@ -482,19 +417,16 @@ Mutates the current record by setting a new set of linked records on the given t Given the GraphQL document: ```graphql - rootField { nodes { # ... } } - ``` Usage: ```javascript - const rootField = store.getRootField('rootField'); const newNode = store.create(/* ... */); const newNodes = [...rootField.getLinkedRecords('nodes'), newNode]; @@ -511,16 +443,13 @@ Invalidates the record. This will cause any query that references this record to #### Example ```javascript - const record = store.get('4'); record.invalidateRecord(); - ``` After invalidating a record, any query that references the invalidated record and that is checked before refetching it will be considered stale: ```javascript - environment.check(query) === 'stale' ``` @@ -530,7 +459,6 @@ environment.check(query) === 'stale' `ConnectionHandler` is a utility module exposed by `relay-runtime` that aids in the manipulation of connections. `ConnectionHandler` exposes the following interface: ```javascript - interface ConnectionHandler { getConnection( record: RecordProxy, @@ -555,7 +483,6 @@ interface ConnectionHandler { ): void, deleteNode(connection: RecordProxy, nodeID: string): void } - ``` ### `getConnection(record: RecordProxy, key: string, filters?: ?Object)` @@ -565,7 +492,6 @@ Given a record and a connection key, and optionally a set of filters, `getConnec First, let's take a look at a plain connection: ```graphql - fragment FriendsFragment on User { friends(first: 10) { edges { @@ -575,26 +501,22 @@ fragment FriendsFragment on User { } } } - ``` Accessing a plain connection field like this is the same as other regular field: ```javascript - // The `friends` connection record can be accessed with: const user = store.get(userID); const friends = user && user.getLinkedRecord(user, 'friends'); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` In a [pagination container](./pagination-container), we usually annotate the actual connection field with `@connection` to tell Relay which part needs to be paginated: ```graphql - fragment FriendsFragment on User { friends(first: 10, orderby: "firstname") @connection( key: "FriendsFragment_friends", @@ -606,7 +528,6 @@ fragment FriendsFragment on User { } } } - ``` For connections like the above, `ConnectionHandler` helps us find the record: @@ -624,7 +545,6 @@ const friends = ConnectionHandler.getConnection( ); // Access fields on the connection: const edges = friends.getLinkedRecords('edges'); - ``` ### Edge creation and insertion @@ -654,7 +574,6 @@ ConnectionHandler.insertEdgeAfter(friends, edge); // No cursor provided, Insert the edge at the front: ConnectionHandler.insertEdgeBefore(friends, edge); - ``` ### `deleteNode(connection: RecordProxy, nodeID: string): void` @@ -668,5 +587,4 @@ Given a connection, deletes any edges whose id matches the given id. const user = store.get(userID); const friends = ConnectionHandler.getConnection(user, 'friends'); ConnectionHandler.deleteNode(friends, idToDelete); - ``` diff --git a/website/versioned_docs/version-v9.1.0/Modern-Subscriptions.md b/website/versioned_docs/version-v9.1.0/Modern-Subscriptions.md index 802f1d02b06de..bd1c5fe2f350c 100644 --- a/website/versioned_docs/version-v9.1.0/Modern-Subscriptions.md +++ b/website/versioned_docs/version-v9.1.0/Modern-Subscriptions.md @@ -6,7 +6,6 @@ original_id: subscriptions Relay exposes the following APIs to create subscriptions. ```javascript - const {requestSubscription} = require('react-relay'); type Variables = {[name: string]: any}; @@ -27,7 +26,6 @@ requestSubscription( configs?: Array, }, ) => Disposable; - ``` The function returns a `Disposable` on which you could call `dispose()` to cancel the refetch. @@ -53,7 +51,6 @@ appropriate when you are only changing the properties of existing records that can be identified by their `id`: ```javascript - const { requestSubscription, graphql, @@ -87,7 +84,6 @@ requestSubscription( onError: error => console.error(error), } ); - ``` # Updating the client on each response @@ -97,7 +93,6 @@ Relay's in-memory cache when each subscription response is received. To do so, pass an `updater` function: ```javascript - const {ConnectionHandler} = require('relay-runtime'); requestSubscription( @@ -123,5 +118,4 @@ requestSubscription( }, }, ); - ``` diff --git a/website/versioned_docs/version-v9.1.0/Modern-TestingRelayComponents.md b/website/versioned_docs/version-v9.1.0/Modern-TestingRelayComponents.md index 5e7aca178349f..6b1a60981a3b1 100644 --- a/website/versioned_docs/version-v9.1.0/Modern-TestingRelayComponents.md +++ b/website/versioned_docs/version-v9.1.0/Modern-TestingRelayComponents.md @@ -65,7 +65,6 @@ MockPayloadGenerator may drastically simplify the process of creating and mainta Example of a simple Mock Resolver: ```javascript - { ID() { // Return mock value for a scalar filed with type ID @@ -76,13 +75,11 @@ Example of a simple Mock Resolver: return "Lorem Ipsum" } } - ``` It is possible to define more resolvers for Object types ```javascript - { // This will be the default values for User object in the query response User() { @@ -95,7 +92,6 @@ It is possible to define more resolvers for Object types }; }, } - ``` ### Mock Resolver Context @@ -103,7 +99,6 @@ It is possible to define more resolvers for Object types The first argument of the MockResolver is the object that contains Mock Resolver Context. It is possible to return dynamic values from mock resolvers based on the context - for instance, name or alias of the field, a path in the selection, arguments, or parent type. ```javascript - { String(context) { if (context.name === 'zip') { @@ -117,7 +112,6 @@ The first argument of the MockResolver is the object that contains Mock Resolver } } } - ``` ### ID Generation @@ -125,14 +119,12 @@ The first argument of the MockResolver is the object that contains Mock Resolver The second argument of the Mock Resolver its a function that will generate a sequence of integers, useful to generate unique ids in the tests ```javascript - { // will generate strings "my-id-1", "my-id-2", etc. ID(_, generateId) { return `my-id-${generateId()}`; }, } - ``` ### @relay_test_operation @@ -142,7 +134,6 @@ Most of GraphQL type information for a specific field in the selection is not av Operation with the @relay_test_operation directive will have additional metadata that will contain GraphQL type info for fields in the operation's selection. And it will improve the quality of the generated data. You also will be able to define Mock resolvers for Scalar (not only ID and String) and Abstract types: ```javascript - { Float() { return 123.456; @@ -160,7 +151,6 @@ Operation with the @relay_test_operation directive will have additional metadata }; } } - ``` ## Examples @@ -170,7 +160,6 @@ Operation with the @relay_test_operation directive will have additional metadata Using `createMockEnvironment` and `MockPayloadGenerator` allows writing concise tests for components that are using Relay Containers and Renderers. Both those modules can be imported from `relay-test-utils` ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { @@ -223,7 +212,6 @@ test('Error State', () => { renderer.root.find(item => (item.props.testID = 'errorMessage')), ).toBeDefined(); }); - ``` ### Fragment Container Tests @@ -231,7 +219,6 @@ test('Error State', () => { Essentially, in the example above will `resolveMostRecentOperation` will generate data for all child fragment containers (pagination, refetch). But, usually the Root Components container may have many child fragment components and you may want to exercise a specific Fragment Container. The solution for that would be to wrap you fragment container with the QueryRenderer that renders a Query that's spreads fragments from you fragment container. ```javascript - test('Fragment Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -262,7 +249,6 @@ test('Fragment Container', () => { expect(renderer).toMatchSnapshot(); }); - ``` ### Pagination Container Test @@ -270,7 +256,6 @@ test('Fragment Container', () => { Essentially, tests for Pagination container are not different from Fragment Container tests. But we can do more here, we can actually see how the pagination works - we can assert the behavior of our components when performing pagination (load more, refetch). ```javascript - // Pagination Example test('Pagination Container', () => { const environment = createMockEnvironment(); @@ -344,7 +329,6 @@ test('Pagination Container', () => { We can use similar approach here with wrapping container with Query Renderer. And for the sake of completeness, we will add example here: ```javascript - test('Refetch Container', () => { const environment = createMockEnvironment(); const TestRenderer = () => ( @@ -386,7 +370,6 @@ test('Refetch Container', () => { ); // expect(renderer).toMatchSnapshot(); }); - ``` ### Mutations @@ -394,7 +377,6 @@ test('Refetch Container', () => { Mutations itself are operations so we can test them independently (unit-test) for specific mutation, or in combination with the view from which this mutation is called. ```javascript - // Say, you have a mutation function function sendMutation(environment, onCompleted, onError, variables) commitMutation(environment, { @@ -417,7 +399,6 @@ test('it should send mutation', () => { ); expect(onCompleted).toBeCalled(); }); - ``` ### Subscription @@ -425,7 +406,6 @@ test('it should send mutation', () => { We can test subscription in a similar way we test mutations ```javascript - // Example subscribe function function subscribe(environment, onNext, onError, variables) requestSubscription(environment, { @@ -448,7 +428,6 @@ test('it should subscribe', () => { ); expect(onNext).toBeCalled(); }); - ``` ### Example with `queueOperationResolver` @@ -456,7 +435,6 @@ test('it should subscribe', () => { With `queueOpeararionResolver` it possible to define responses for operations that will be executed on the environment ```javascript - // Say you have a component with the QueryRenderer const MyAwesomeViewRoot = require('MyAwesomeViewRoot'); const { diff --git a/website/versioned_docs/version-v9.1.0/Modern-TypeEmission.md b/website/versioned_docs/version-v9.1.0/Modern-TypeEmission.md index 63614b869a322..4ff63e4a7d81b 100644 --- a/website/versioned_docs/version-v9.1.0/Modern-TypeEmission.md +++ b/website/versioned_docs/version-v9.1.0/Modern-TypeEmission.md @@ -16,7 +16,6 @@ In this example the emitted type-information would require the variables object #### Flow ```javascript - /** * export type ExampleQueryVariables = {| * +artistID: string @@ -44,7 +43,6 @@ const variables: ExampleQueryVariables = { #### TypeScript ```javascript - /** * export type ExampleQueryVariables = { * readonly artistID: string @@ -79,7 +77,6 @@ In this example the emitted type-information describes the response data availab #### Flow ```javascript - /** * export type ExampleQueryResponse = {| * +artist: ?{| @@ -110,7 +107,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * export type ExampleQueryResponse = { * readonly artist?: { @@ -146,7 +142,6 @@ Similarly, in this example the emitted type-information describes the prop data #### Flow ```javascript - /** * export type ExampleFragment_artist = {| * +name: string @@ -172,7 +167,6 @@ export const ExampleFragment = createFragmentContainer( #### TypeScript ```javascript - /** * export type ExampleFragment_artist = { * readonly name: string @@ -206,7 +200,6 @@ Consider a component that composes the above fragment container example. In this #### Flow ```javascript - /** * import type { FragmentReference } from "relay-runtime"; * declare export opaque type ExampleFragment_artist$ref: FragmentReference; @@ -250,7 +243,6 @@ import type { ExampleQueryResponse } from "__generated__/ExampleQuery.graphql" #### TypeScript ```javascript - /** * declare const _ExampleFragment_artist$ref: unique symbol; * export type ExampleFragment_artist$ref = typeof _ExampleFragment_artist$ref; @@ -315,7 +307,6 @@ $ relay-compiler --artifactDirectory ./src/__generated__ […] ["relay", { "artifactDirectory": "./src/__generated__" }] ] } - ``` It is recommended to alias this directory in your module resolution configuration such that you don’t need to specify relative paths in your source files. This is what is also done in the above examples, where artifacts are imported from a `__generated__` alias, rather than relative paths like `../../../../__generated__`. diff --git a/website/versioned_docs/version-v9.1.0/Modern-UpgradingSetVariables.md b/website/versioned_docs/version-v9.1.0/Modern-UpgradingSetVariables.md index d5b086fafce20..ff73feec04f8b 100644 --- a/website/versioned_docs/version-v9.1.0/Modern-UpgradingSetVariables.md +++ b/website/versioned_docs/version-v9.1.0/Modern-UpgradingSetVariables.md @@ -36,7 +36,6 @@ fragment on User { # ... } } - ``` This should be upgraded to use a [`PaginationContainer`](./pagination-container). @@ -61,7 +60,6 @@ fragment on User { # ... } } - ``` This can be upgraded by using a [`RefetchContainer`](./refetch-container) which allows you to specify the exact query to use to fetch the new data. @@ -86,7 +84,6 @@ fragment on FeedbackTarget { # ... } } - ``` This can be upgraded by conditionally rendering a [`QueryRenderer`](./query-renderer) which will load the data once it is rendered. The code overhead of doing this is dramatically reduced with the new API. diff --git a/website/versioned_docs/version-v9.1.0/Modern-fetchQuery.md b/website/versioned_docs/version-v9.1.0/Modern-fetchQuery.md index 2e9461ad527bd..c1a06ab7d2493 100644 --- a/website/versioned_docs/version-v9.1.0/Modern-fetchQuery.md +++ b/website/versioned_docs/version-v9.1.0/Modern-fetchQuery.md @@ -6,7 +6,6 @@ original_id: fetch-query You can use the `fetchQuery` function to imperatively make GraphQL Requests. This is useful for cases where you want to make requests outside of React but still utilize the Relay store and network layer. ```javascript - import {fetchQuery, graphql} from 'relay-runtime'; const query = graphql` @@ -25,7 +24,6 @@ fetchQuery(environment, query, variables) .then(data => { // access the graphql response }); - ``` ## Arguments diff --git a/website/versioned_docs/version-v9.1.0/PrinciplesAndArchitecture-Compiler.md b/website/versioned_docs/version-v9.1.0/PrinciplesAndArchitecture-Compiler.md index c195491682b1f..fcd0490cb724f 100644 --- a/website/versioned_docs/version-v9.1.0/PrinciplesAndArchitecture-Compiler.md +++ b/website/versioned_docs/version-v9.1.0/PrinciplesAndArchitecture-Compiler.md @@ -74,7 +74,6 @@ foo { # type FooType foo { id } - ``` - `SkipRedundantNodeTransform`: A more advanced version of flattening, this eliminates more complex cases of field duplication such as when a field is fetched both unconditionally and conditionally, or is fetched by two different sub-fragments. For example: @@ -97,7 +96,6 @@ foo { id } } - ``` - `GenerateRequisiteFieldTransform`: This optional, Relay-specific transform inserts `id` fields for globally identifiable objects and `__typename` fields wherever the type cannot be statically determined (e.g. for unions). diff --git a/website/versioned_docs/version-v9.1.0/PrinciplesAndArchitecture-Runtime.md b/website/versioned_docs/version-v9.1.0/PrinciplesAndArchitecture-Runtime.md index 9491d290c146f..e9221631a701d 100644 --- a/website/versioned_docs/version-v9.1.0/PrinciplesAndArchitecture-Runtime.md +++ b/website/versioned_docs/version-v9.1.0/PrinciplesAndArchitecture-Runtime.md @@ -77,7 +77,6 @@ RecordSource { city: 'Seattle', } } - ``` [1] Note that GraphQL itself does not impose this constraint, and Relay Runtime may also be used for schemas that do not conform to it. For example, both systems can be used to query a single denormalized table. However, many of the features that Relay Runtime provides, such as caching and normalization, work best when the data is represented as a normalized graph with stable identities for discrete pieces of information. diff --git a/website/versioned_docs/version-v9.1.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md b/website/versioned_docs/version-v9.1.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md index a8842ae084922..9ff8a7840df90 100644 --- a/website/versioned_docs/version-v9.1.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md +++ b/website/versioned_docs/version-v9.1.0/PrinciplesAndArchitecture-ThinkingInGraphQL.md @@ -12,7 +12,6 @@ In this article we'll explore what it means to build a GraphQL client framework Imagine we have a simple application that fetches a list of stories, and some details about each one. Here's how that might look in resource-oriented REST: ```javascript - // Fetch the list of story IDs but not their details: rest.get('/stories').then(stories => // This resolves to a list of items with linked resources: @@ -25,13 +24,11 @@ rest.get('/stories').then(stories => // `[ { id: "...", text: "..." } ]` console.log(stories); }); - ``` Note that this approach requires _n+1_ requests to the server: 1 to fetch the list, and _n_ to fetch each item. With GraphQL we can fetch the same data in a single network request to the server (without creating a custom endpoint that we'd then have to maintain): ```javascript - graphql.get(`query { stories { id, text } }`).then( stories => { // A list of story items: @@ -39,7 +36,6 @@ graphql.get(`query { stories { id, text } }`).then( console.log(stories); } ); - ``` So far we're just using GraphQL as a more efficient version of typical REST approaches. Note two important benefits in the GraphQL version: @@ -56,7 +52,6 @@ Repeatedly refetching information from the server can get quite slow. For exampl In a resource-oriented REST system, we can maintain a **response cache** based on URIs: ```javascript - var _cache = new Map(); rest.get = uri => { if (!_cache.has(uri)) { @@ -64,13 +59,11 @@ rest.get = uri => { } return _cache.get(uri); }; - ``` Response-caching can also be applied to GraphQL. A basic approach would work similarly to the REST version. The text of the query itself can be used as a cache key: ```javascript - var _cache = new Map(); graphql.get = queryText => { if (!_cache.has(queryText)) { @@ -78,7 +71,6 @@ graphql.get = queryText => { } return _cache.get(queryText); }; - ``` Now, requests for previously cached data can be answered immediately without making a network request. This is a practical approach to improving the perceived performance of an application. However, this method of caching can cause problems with data consistency. @@ -90,7 +82,6 @@ With GraphQL it is very common for the results of multiple queries to overlap. H ``` query { stories { id, text, likeCount } } - ``` and then later refetch one of the stories whose `likeCount` has since been incremented: @@ -98,7 +89,6 @@ and then later refetch one of the stories whose `likeCount` has since been incre ``` query { story(id: "123") { id, text, likeCount } } - ``` We'll now see different `likeCount`s depending on how the story is accessed. A view that uses the first query will see an outdated count, while a view using the second query will see the updated count. @@ -119,7 +109,6 @@ query { } } } - ``` And here's a possible response: @@ -134,13 +123,11 @@ query: { } } } - ``` Although the response is hierarchical, we'll cache it by flattening all the records. Here is an example of how Relay would cache this query response: ```javascript - Map { // `story(id: "1")` 1: Map { @@ -152,7 +139,6 @@ Map { name: 'Jan', }, }; - ``` This is only a simple example: in reality the cache must handle one-to-many associations and pagination (among other things). @@ -182,7 +168,6 @@ The first query was for a list of stories: ``` query { stories { id, text, likeCount } } - ``` With a normalized response cache, a record would be created for each story in the list. The `stories` field would store links to each of these records. @@ -192,7 +177,6 @@ The second query refetched the information for one of those stories: ``` query { story(id: "123") { id, text, likeCount } } - ``` When this response is normalized, Relay can detect that this result overlaps with existing data based on its `id`. Rather than create a new record, Relay will update the existing `123` record. The new `likeCount` is therefore available to _both_ queries, as well as any other query that might reference this story. @@ -215,7 +199,6 @@ query { } } } - ``` After initially fetching this story our cache might be as follows. Note that the story and comment both link to the same record as `author`: @@ -242,7 +225,6 @@ Map { author: Link(2), }, } - ``` The author of this story also commented on it — quite common. Now imagine that some other view fetches new information about the author, and her profile photo has changed to a new URI. Here's the _only_ part of our cached data that changes: @@ -256,7 +238,6 @@ Map { photo: 'http://.../photo2.jpg', }, } - ``` The value of the `photo` field has changed; and therefore the record `2` has also changed. And that's it. Nothing else in the _cache_ is affected. But clearly our _view_ needs to reflect the update: both instances of the author in the UI (as story author and comment author) need to show the new photo. @@ -273,7 +254,6 @@ ImmutableMap { }, 3: ImmutableMap // same as before } - ``` If we replace `2` with a new immutable record, we'll also get a new immutable instance of the cache object. However, records `1` and `3` are untouched. Because the data is normalized, we can't tell that `story`'s contents have changed just by looking at the `story` record alone. @@ -299,7 +279,6 @@ mutation StoryLike($storyID: String) { likeCount } } - ``` Notice that we're querying for data that _may_ have changed as a result of the mutation. An obvious question is: why can't the server just tell us what changed? The answer is: it's complicated. GraphQL abstracts over _any_ data storage layer (or an aggregation of multiple sources), and works with any programming language. Furthermore, the goal of GraphQL is to provide data in a form that is useful to product developers building a view. diff --git a/website/versioned_docs/version-v9.1.0/PrinciplesAndArchitecture-ThinkingInRelay.md b/website/versioned_docs/version-v9.1.0/PrinciplesAndArchitecture-ThinkingInRelay.md index e61f3fd21c933..62b1914ef3ff9 100644 --- a/website/versioned_docs/version-v9.1.0/PrinciplesAndArchitecture-ThinkingInRelay.md +++ b/website/versioned_docs/version-v9.1.0/PrinciplesAndArchitecture-ThinkingInRelay.md @@ -30,13 +30,11 @@ fragment Story_story on Story { photo } } - ``` And this fragment can then be used to define the Story container: ```javascript - const {createFragmentContainer, graphql} = require('react-relay'); // Plain React component. @@ -64,7 +62,6 @@ const StoryContainer = createFragmentContainer(Story, { In React, rendering a view requires two inputs: the _component_ to render, and a _root_ DOM (UI) node to render into. Rendering Relay containers is similar: we need a _container_ to render, and a _root_ in the graph from which to start our query. We also must ensure that the queries for the container are executed and may want to show a loading indicator while data is being fetched. Similar to `ReactDOM.render(component, domNode)`, Relay provides `` for this purpose. The `query` and `variables` define what data to fetch and `render` defines what to render. Here's how we might render ``: ```javascript - ReactDOM.render(