relay-runtime 20.1.0 → 21.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (262) hide show
  1. package/experimental.js +1 -1
  2. package/experimental.js.flow +8 -8
  3. package/handlers/connection/ConnectionHandler.js.flow +5 -5
  4. package/handlers/connection/ConnectionInterface.js.flow +1 -1
  5. package/index.js +1 -1
  6. package/index.js.flow +125 -62
  7. package/lib/experimental.js +3 -3
  8. package/lib/index.js +105 -57
  9. package/lib/multi-actor-environment/ActorIdentifier.js +2 -2
  10. package/lib/multi-actor-environment/MultiActorEnvironment.js +3 -1
  11. package/lib/mutations/commitMutation.js +8 -8
  12. package/lib/mutations/validateMutation.js +4 -4
  13. package/lib/query/GraphQLTag.js +3 -3
  14. package/lib/query/fetchQuery.js +15 -3
  15. package/lib/store/DataChecker.js +38 -4
  16. package/lib/store/NormalizationEngine.js +373 -0
  17. package/lib/store/OperationExecutor.js +172 -113
  18. package/lib/store/RelayConcreteVariables.js +1 -1
  19. package/lib/store/RelayErrorTrie.js +2 -2
  20. package/lib/store/RelayExperimentalGraphResponseTransform.js +8 -8
  21. package/lib/store/RelayModernEnvironment.js +26 -19
  22. package/lib/store/RelayModernRecord.js +18 -8
  23. package/lib/store/RelayModernSelector.js +9 -9
  24. package/lib/store/RelayModernStore.js +152 -43
  25. package/lib/store/RelayPublishQueue.js +1 -1
  26. package/lib/store/RelayReader.js +76 -38
  27. package/lib/store/RelayRecordSource.js +6 -0
  28. package/lib/store/RelayReferenceMarker.js +2 -1
  29. package/lib/store/RelayResponseNormalizer.js +88 -55
  30. package/lib/store/RelayStoreSubscriptions.js +34 -10
  31. package/lib/store/RelayStoreUtils.js +8 -1
  32. package/lib/store/ResolverFragments.js +2 -2
  33. package/lib/store/live-resolvers/LiveResolverCache.js +25 -9
  34. package/lib/store/observeFragmentExperimental.js +17 -1
  35. package/lib/store/observeQueryExperimental.js +2 -2
  36. package/lib/subscription/requestSubscription.js +3 -3
  37. package/lib/util/RelayError.js +3 -0
  38. package/lib/util/RelayFeatureFlags.js +6 -2
  39. package/lib/util/RelayReplaySubject.js +4 -4
  40. package/lib/util/handlePotentialSnapshotErrors.js +2 -2
  41. package/lib/util/stableCopy.js +2 -2
  42. package/llm-docs/api-reference/entrypoint-apis/entrypoint-container.mdx +38 -0
  43. package/llm-docs/api-reference/entrypoint-apis/load-entrypoint.mdx +77 -0
  44. package/llm-docs/api-reference/entrypoint-apis/use-entrypoint-loader.mdx +99 -0
  45. package/llm-docs/api-reference/graphql/graphql-directives.mdx +378 -0
  46. package/llm-docs/api-reference/hooks/_use-lazy-load-query-extra.mdx +16 -0
  47. package/llm-docs/api-reference/hooks/load-query.mdx +84 -0
  48. package/llm-docs/api-reference/hooks/relay-environment-provider.mdx +78 -0
  49. package/llm-docs/api-reference/hooks/use-client-query.mdx +65 -0
  50. package/llm-docs/api-reference/hooks/use-fragment.mdx +69 -0
  51. package/llm-docs/api-reference/hooks/use-lazy-load-query.mdx +62 -0
  52. package/llm-docs/api-reference/hooks/use-mutation.mdx +94 -0
  53. package/llm-docs/api-reference/hooks/use-pagination-fragment.mdx +166 -0
  54. package/llm-docs/api-reference/hooks/use-prefetchable-forward-pagination-fragment.mdx +134 -0
  55. package/llm-docs/api-reference/hooks/use-preloaded-query.mdx +84 -0
  56. package/llm-docs/api-reference/hooks/use-query-loader.mdx +95 -0
  57. package/llm-docs/api-reference/hooks/use-refetchable-fragment.mdx +122 -0
  58. package/llm-docs/api-reference/hooks/use-relay-environment.mdx +37 -0
  59. package/llm-docs/api-reference/hooks/use-subscription.mdx +66 -0
  60. package/llm-docs/api-reference/relay-resolvers/docblock-format.mdx +321 -0
  61. package/llm-docs/api-reference/relay-resolvers/runtime-functions.mdx +94 -0
  62. package/llm-docs/api-reference/relay-runtime/commit-mutation.mdx +65 -0
  63. package/llm-docs/api-reference/relay-runtime/fetch-query.mdx +113 -0
  64. package/llm-docs/api-reference/relay-runtime/field-logger.mdx +170 -0
  65. package/llm-docs/api-reference/relay-runtime/observe-fragment.mdx +92 -0
  66. package/llm-docs/api-reference/relay-runtime/relay-environment.mdx +53 -0
  67. package/llm-docs/api-reference/relay-runtime/request-subscription.mdx +54 -0
  68. package/llm-docs/api-reference/relay-runtime/runtime-configuration.mdx +52 -0
  69. package/llm-docs/api-reference/relay-runtime/store.mdx +734 -0
  70. package/llm-docs/api-reference/relay-runtime/wait-for-fragment-data.mdx +89 -0
  71. package/llm-docs/api-reference/types/CacheConfig.mdx +8 -0
  72. package/llm-docs/api-reference/types/Disposable.mdx +4 -0
  73. package/llm-docs/api-reference/types/GraphQLSubscriptionConfig.mdx +17 -0
  74. package/llm-docs/api-reference/types/MutationConfig.mdx +31 -0
  75. package/llm-docs/api-reference/types/SelectorStoreUpdater.mdx +6 -0
  76. package/llm-docs/api-reference/types/UploadableMap.mdx +3 -0
  77. package/llm-docs/community/learning-resources.mdx +64 -0
  78. package/llm-docs/debugging/declarative-mutation-directives.mdx +34 -0
  79. package/llm-docs/debugging/disallowed-id-types-error.mdx +43 -0
  80. package/llm-docs/debugging/inconsistent-typename-error.mdx +47 -0
  81. package/llm-docs/debugging/relay-devtools.mdx +73 -0
  82. package/llm-docs/debugging/why-null.mdx +116 -0
  83. package/llm-docs/editor-support.mdx +55 -0
  84. package/llm-docs/error-reference/unknown-field.mdx +36 -0
  85. package/llm-docs/getting-started/babel-plugin.mdx +31 -0
  86. package/llm-docs/getting-started/compiler-config.mdx +25 -0
  87. package/llm-docs/getting-started/compiler.mdx +82 -0
  88. package/llm-docs/getting-started/lint-rules.mdx +87 -0
  89. package/llm-docs/getting-started/production.mdx +30 -0
  90. package/llm-docs/getting-started/quick-start.mdx +213 -0
  91. package/llm-docs/glossary/glossary.mdx +1040 -0
  92. package/llm-docs/guided-tour/list-data/advanced-pagination.mdx +157 -0
  93. package/llm-docs/guided-tour/list-data/connections.mdx +81 -0
  94. package/llm-docs/guided-tour/list-data/pagination.mdx +193 -0
  95. package/llm-docs/guided-tour/list-data/rendering-connections.mdx +112 -0
  96. package/llm-docs/guided-tour/list-data/streaming-pagination.mdx +87 -0
  97. package/llm-docs/guided-tour/managing-data-outside-react/retaining-queries.mdx +51 -0
  98. package/llm-docs/guided-tour/refetching/refetching-queries-with-different-data.mdx +337 -0
  99. package/llm-docs/guided-tour/refetching/refreshing-queries.mdx +350 -0
  100. package/llm-docs/guided-tour/rendering/environment.mdx +59 -0
  101. package/llm-docs/guided-tour/rendering/error-states.mdx +295 -0
  102. package/llm-docs/guided-tour/rendering/fragments.mdx +354 -0
  103. package/llm-docs/guided-tour/rendering/loading-states.mdx +245 -0
  104. package/llm-docs/guided-tour/rendering/queries.mdx +261 -0
  105. package/llm-docs/guided-tour/rendering/variables.mdx +233 -0
  106. package/llm-docs/guided-tour/reusing-cached-data/fetch-policies.mdx +56 -0
  107. package/llm-docs/guided-tour/reusing-cached-data/filling-in-missing-data.mdx +102 -0
  108. package/llm-docs/guided-tour/reusing-cached-data/introduction.mdx +22 -0
  109. package/llm-docs/guided-tour/reusing-cached-data/presence-of-data.mdx +93 -0
  110. package/llm-docs/guided-tour/reusing-cached-data/rendering-partially-cached-data.mdx +175 -0
  111. package/llm-docs/guided-tour/reusing-cached-data/staleness-of-data.mdx +116 -0
  112. package/llm-docs/guided-tour/updating-data/client-only-data.mdx +115 -0
  113. package/llm-docs/guided-tour/updating-data/graphql-mutations.mdx +334 -0
  114. package/llm-docs/guided-tour/updating-data/graphql-subscriptions.mdx +279 -0
  115. package/llm-docs/guided-tour/updating-data/imperatively-modifying-linked-fields.mdx +511 -0
  116. package/llm-docs/guided-tour/updating-data/imperatively-modifying-store-data-legacy.mdx +142 -0
  117. package/llm-docs/guided-tour/updating-data/imperatively-modifying-store-data.mdx +275 -0
  118. package/llm-docs/guided-tour/updating-data/introduction.mdx +25 -0
  119. package/llm-docs/guided-tour/updating-data/local-data-updates.mdx +71 -0
  120. package/llm-docs/guided-tour/updating-data/typesafe-updaters-faq.mdx +83 -0
  121. package/llm-docs/guided-tour/updating-data/updating-connections.mdx +592 -0
  122. package/llm-docs/guides/alias-directive.mdx +160 -0
  123. package/llm-docs/guides/catch-directive.mdx +167 -0
  124. package/llm-docs/guides/client-schema-extensions.mdx +208 -0
  125. package/llm-docs/guides/codemods.mdx +66 -0
  126. package/llm-docs/guides/data-driven-dependencies/client-3d.mdx +255 -0
  127. package/llm-docs/guides/data-driven-dependencies/configuration.mdx +127 -0
  128. package/llm-docs/guides/data-driven-dependencies/introduction.mdx +39 -0
  129. package/llm-docs/guides/data-driven-dependencies/server-3d.mdx +664 -0
  130. package/llm-docs/guides/document-comparison.mdx +106 -0
  131. package/llm-docs/guides/graphql-server-specification.mdx +453 -0
  132. package/llm-docs/guides/network-layer.mdx +69 -0
  133. package/llm-docs/guides/persisted-queries.mdx +328 -0
  134. package/llm-docs/guides/relay-resolvers/context.mdx +99 -0
  135. package/llm-docs/guides/relay-resolvers/defining-fields.mdx +151 -0
  136. package/llm-docs/guides/relay-resolvers/defining-types.mdx +164 -0
  137. package/llm-docs/guides/relay-resolvers/deprecated.mdx +27 -0
  138. package/llm-docs/guides/relay-resolvers/derived-fields.mdx +127 -0
  139. package/llm-docs/guides/relay-resolvers/descriptions.mdx +44 -0
  140. package/llm-docs/guides/relay-resolvers/enabling.mdx +41 -0
  141. package/llm-docs/guides/relay-resolvers/errors.mdx +64 -0
  142. package/llm-docs/guides/relay-resolvers/field-arguments.mdx +63 -0
  143. package/llm-docs/guides/relay-resolvers/introduction.mdx +62 -0
  144. package/llm-docs/guides/relay-resolvers/limitations.mdx +30 -0
  145. package/llm-docs/guides/relay-resolvers/live-fields.mdx +164 -0
  146. package/llm-docs/guides/relay-resolvers/return-types.mdx +161 -0
  147. package/llm-docs/guides/relay-resolvers/suspense.mdx +41 -0
  148. package/llm-docs/guides/required-directive.mdx +240 -0
  149. package/llm-docs/guides/semantic-nullability.mdx +93 -0
  150. package/llm-docs/guides/testing-relay-components.mdx +642 -0
  151. package/llm-docs/guides/testing-relay-with-preloaded-queries.mdx +160 -0
  152. package/llm-docs/guides/throw-on-field-error-directive.mdx +58 -0
  153. package/llm-docs/guides/type-emission.mdx +414 -0
  154. package/llm-docs/home.mdx +32 -0
  155. package/llm-docs/principles-and-architecture/architecture-overview.mdx +24 -0
  156. package/llm-docs/principles-and-architecture/compiler-architecture.mdx +106 -0
  157. package/llm-docs/principles-and-architecture/runtime-architecture.mdx +249 -0
  158. package/llm-docs/principles-and-architecture/thinking-in-graphql.mdx +309 -0
  159. package/llm-docs/principles-and-architecture/thinking-in-relay.mdx +104 -0
  160. package/llm-docs/principles-and-architecture/videos.mdx +50 -0
  161. package/llm-docs/tutorial/arrays-lists.mdx +126 -0
  162. package/llm-docs/tutorial/fragments-1.mdx +487 -0
  163. package/llm-docs/tutorial/graphql.mdx +172 -0
  164. package/llm-docs/tutorial/interfaces-polymorphism.mdx +161 -0
  165. package/llm-docs/tutorial/intro.mdx +58 -0
  166. package/llm-docs/tutorial/mutations-updates.mdx +624 -0
  167. package/llm-docs/tutorial/organizing-mutations-queries-and-subscriptions.mdx +13 -0
  168. package/llm-docs/tutorial/queries-1.mdx +267 -0
  169. package/llm-docs/tutorial/queries-2.mdx +389 -0
  170. package/llm-docs/tutorial/refetchable-fragments.mdx +352 -0
  171. package/multi-actor-environment/ActorIdentifier.js.flow +2 -2
  172. package/multi-actor-environment/ActorSpecificEnvironment.js.flow +7 -7
  173. package/multi-actor-environment/ActorUtils.js.flow +1 -1
  174. package/multi-actor-environment/MultiActorEnvironment.js.flow +12 -8
  175. package/multi-actor-environment/MultiActorEnvironmentTypes.js.flow +3 -3
  176. package/mutations/RelayDeclarativeMutationConfig.js.flow +9 -9
  177. package/mutations/RelayRecordProxy.js.flow +8 -11
  178. package/mutations/RelayRecordSourceMutator.js.flow +4 -4
  179. package/mutations/RelayRecordSourceProxy.js.flow +4 -4
  180. package/mutations/RelayRecordSourceSelectorProxy.js.flow +6 -6
  181. package/mutations/applyOptimisticMutation.js.flow +2 -2
  182. package/mutations/commitMutation.js.flow +20 -16
  183. package/mutations/createUpdatableProxy.js.flow +19 -19
  184. package/mutations/readUpdatableFragment.js.flow +3 -3
  185. package/mutations/readUpdatableQuery.js.flow +3 -3
  186. package/mutations/validateMutation.js.flow +7 -7
  187. package/network/RelayNetworkTypes.js.flow +4 -4
  188. package/network/RelayObservable.js.flow +16 -14
  189. package/network/RelayQueryResponseCache.js.flow +3 -3
  190. package/network/wrapNetworkWithLogObserver.js.flow +1 -1
  191. package/package.json +2 -1
  192. package/query/GraphQLTag.js.flow +22 -10
  193. package/query/fetchQuery.js.flow +23 -10
  194. package/query/fetchQuery_DEPRECATED.js.flow +1 -1
  195. package/store/DataChecker.js.flow +43 -9
  196. package/store/NormalizationEngine.js.flow +779 -0
  197. package/store/OperationExecutor.js.flow +173 -70
  198. package/store/RelayConcreteVariables.js.flow +5 -5
  199. package/store/RelayErrorTrie.js.flow +12 -12
  200. package/store/RelayExperimentalGraphResponseHandler.js.flow +3 -3
  201. package/store/RelayExperimentalGraphResponseTransform.js.flow +10 -10
  202. package/store/RelayModernEnvironment.js.flow +41 -26
  203. package/store/RelayModernFragmentSpecResolver.js.flow +1 -1
  204. package/store/RelayModernOperationDescriptor.js.flow +1 -1
  205. package/store/RelayModernRecord.js.flow +46 -22
  206. package/store/RelayModernSelector.js.flow +21 -21
  207. package/store/RelayModernStore.js.flow +219 -58
  208. package/store/RelayOperationTracker.js.flow +2 -2
  209. package/store/RelayOptimisticRecordSource.js.flow +2 -2
  210. package/store/RelayPublishQueue.js.flow +21 -12
  211. package/store/RelayReader.js.flow +130 -58
  212. package/store/RelayRecordSource.js.flow +10 -0
  213. package/store/RelayRecordState.js.flow +1 -1
  214. package/store/RelayReferenceMarker.js.flow +5 -4
  215. package/store/RelayResponseNormalizer.js.flow +130 -54
  216. package/store/RelayStoreSubscriptions.js.flow +52 -8
  217. package/store/RelayStoreTypes.js.flow +153 -64
  218. package/store/RelayStoreUtils.js.flow +15 -7
  219. package/store/ResolverCache.js.flow +2 -2
  220. package/store/ResolverFragments.js.flow +12 -12
  221. package/store/StoreInspector.js.flow +6 -7
  222. package/store/cloneRelayHandleSourceField.js.flow +1 -1
  223. package/store/cloneRelayScalarHandleSourceField.js.flow +1 -1
  224. package/store/createRelayContext.js.flow +1 -1
  225. package/store/createRelayLoggingContext.js.flow +4 -4
  226. package/store/defaultGetDataID.js.flow +2 -2
  227. package/store/isRelayModernEnvironment.js.flow +4 -2
  228. package/store/live-resolvers/LiveResolverCache.js.flow +55 -20
  229. package/store/live-resolvers/LiveResolverSuspenseSentinel.js.flow +3 -3
  230. package/store/live-resolvers/getOutputTypeRecordIDs.js.flow +1 -1
  231. package/store/live-resolvers/isLiveStateValue.js.flow +2 -2
  232. package/store/live-resolvers/resolverDataInjector.js.flow +8 -5
  233. package/store/observeFragmentExperimental.js.flow +49 -20
  234. package/store/observeQueryExperimental.js.flow +5 -5
  235. package/store/readInlineData.js.flow +4 -4
  236. package/store/waitForFragmentExperimental.js.flow +3 -3
  237. package/subscription/requestSubscription.js.flow +7 -7
  238. package/util/NormalizationNode.js.flow +34 -32
  239. package/util/ReaderNode.js.flow +32 -30
  240. package/util/RelayConcreteNode.js.flow +5 -5
  241. package/util/RelayError.js.flow +4 -1
  242. package/util/RelayFeatureFlags.js.flow +21 -1
  243. package/util/RelayProfiler.js.flow +1 -1
  244. package/util/RelayReplaySubject.js.flow +3 -3
  245. package/util/RelayRuntimeTypes.js.flow +11 -11
  246. package/util/createPayloadFor3DField.js.flow +9 -5
  247. package/util/deepFreeze.js.flow +2 -2
  248. package/util/getFragmentIdentifier.js.flow +1 -1
  249. package/util/getPaginationMetadata.js.flow +1 -1
  250. package/util/getPaginationVariables.js.flow +1 -1
  251. package/util/getPendingOperationsForFragment.js.flow +2 -2
  252. package/util/getRefetchMetadata.js.flow +6 -5
  253. package/util/getValueAtPath.js.flow +3 -3
  254. package/util/handlePotentialSnapshotErrors.js.flow +5 -5
  255. package/util/isEmptyObject.js.flow +1 -1
  256. package/util/isPromise.js.flow +2 -2
  257. package/util/isScalarAndEqual.js.flow +1 -1
  258. package/util/recycleNodesInto.js.flow +2 -2
  259. package/util/registerEnvironmentWithDevTools.js.flow +1 -1
  260. package/util/shallowFreeze.js.flow +1 -1
  261. package/util/stableCopy.js.flow +5 -5
  262. package/util/withProvidedVariables.js.flow +14 -10
@@ -0,0 +1,161 @@
1
+ # GraphQL Types, Interfaces, and Polymorphism
2
+
3
+ In this section, we’ll see how to treat different types of nodes differently. You might notice that some of the newsfeed stories in the example app are posted by people, while others are posted by organizations. In this example, we'll enhance our hovercard by writing a fragment that selects people-specific information about people and organization-specific information about organizations.
4
+
5
+ * * *
6
+
7
+ We’ve alluded to the fact that GraphQL nodes aren’t just random bags of fields — they have types. Your GraphQL schema defines what fields each type has. For instance, it might define the `Story` type like this:
8
+
9
+ ```
10
+ type Story {
11
+ id: ID!
12
+ title: String
13
+ summary: String
14
+ createdAt: Date
15
+ poster: Actor
16
+ image: Image
17
+ }
18
+ ```
19
+
20
+ Here, some of the fields are scalars (like `String` and `ID`). Others are types defined elsewhere in the schema, like `Image` — these fields are edges to nodes of those specific types. The `!` on `ID!` means that field is non-nullable. In GraphQL, fields are normally nullable and non-nullability is the exception.
21
+
22
+ Fragments are always “on” a particular type. In our example above, `StoryFragment` is defined `on Story`. This means that you can only spread it into places in a query where a `Story` node is expected. And it means that the fragment can select just those fields that exist on the `Story` type.
23
+
24
+ Of particular interest is the `Actor` type used for the `poster` field. This type is an *interface*. That means that the `poster` of a story can be a Person, a Page, an Organization, or any other type of entity that meets the specifications for being an “Actor”.
25
+
26
+ The GraphQL schema in our example app defines an Actor as follows:
27
+
28
+ ```
29
+ interface Actor {
30
+ name: String
31
+ profilePicture: Image
32
+ joined: DateTime
33
+ }
34
+ ```
35
+
36
+ Not coincidentally this is exactly the information that we’re displaying here. There are two types in the schema that *implement* Actor, meaning that they include all the fields defined in Actor. They are declared as such:
37
+
38
+ ```
39
+ type Person implements Actor {
40
+ id: ID!
41
+ name: String
42
+ profilePicture: Image
43
+ joined: DateTime
44
+ email: String
45
+ location: Location
46
+ }
47
+
48
+ type Organization implements Actor {
49
+ id: ID!
50
+ name: String
51
+ profilePicture: Image
52
+ joined: DateTime
53
+ organizationKind: OrganizationKind
54
+ }
55
+ ```
56
+
57
+ Both of these types have `name` , `profilePicture`, and `joined`, so they can both declare that they implement Actor and thus can be used wherever an Actor is called for in the schema and in fragments. They also have other fields that are distinct to each particular type.
58
+
59
+ Let’s see how to work with interfaces more by extending the `PosterDetailsHovercardContentsBody` component to display the location of a `Person` or the organization kind of an `Organization`. These are fields that are only present on those specific types, not on the `Actor` interface.
60
+
61
+ Right now, if you’ve followed along so far, it should have a fragment defined like this (in `PosterDetailsHovercardContents.tsx`):
62
+
63
+ ```
64
+ fragment PosterDetailsHovercardContentsBodyFragment on Actor {
65
+ name
66
+ joined
67
+ profilePicture {
68
+ ...ImageFragment
69
+ }
70
+ }
71
+ ```
72
+
73
+ If you try to add a field like `organizationKind` to this fragment, you’ll get an error from the Relay compiler:
74
+
75
+ ```
76
+ ✖︎ The type `Actor` has no field organizationKind
77
+ ```
78
+
79
+ This is because when we define a fragment as being on an interface, we can only use fields from that interface. To use fields from a specific type that implements the interface, we use a *type refinement* to tell GraphQL we’re selecting fields from that type:
80
+
81
+ ```
82
+ fragment PosterDetailsHovercardContentsBodyFragment on Actor {
83
+ name
84
+ joined
85
+ profilePicture {
86
+ ...ImageFragment
87
+ }
88
+ // change
89
+ ... on Organization {
90
+ organizationKind
91
+ }
92
+ // end-change
93
+ }
94
+ ```
95
+
96
+ Go ahead and add this now. You can also add a type refinement for `Person`:
97
+
98
+ ```
99
+ fragment PosterDetailsHovercardContentsBodyFragment on Actor {
100
+ name
101
+ joined
102
+ profilePicture {
103
+ ...ImageFragment
104
+ }
105
+ ... on Organization {
106
+ organizationKind
107
+ }
108
+ // change
109
+ ... on Person {
110
+ location {
111
+ name
112
+ }
113
+ }
114
+ // end-change
115
+ }
116
+ ```
117
+
118
+ When you select a field that’s only present on some of the types that implement an interface, and the node you’re dealing with is of a different type, then you simply get `null` for the value of that field when you read it out. With that in mind, we can modify the `PosterDetailsHovercardContentsBody` component to show the location of people and organization kind of organizations:
119
+
120
+ ```
121
+ import OrganizationKind from './OrganizationKind';
122
+
123
+ function PosterDetailsHovercardContentsBody({ poster }: Props): React.ReactElement {
124
+ const data = useFragment(PosterDetailsHovercardContentsBodyFragment, poster);
125
+ return (
126
+ <>
127
+ <Image image={data.profilePicture} width={128} height={128} className="posterHovercard__image" />
128
+ <div className="posterHovercard__name">{data.name}</div>
129
+ <ul className="posterHovercard__details">
130
+ <li>Joined <Timestamp time={poster.joined} /></li>
131
+ // change
132
+ {data.location != null && (
133
+ <li>{data.location.name}</li>
134
+ )}
135
+ {data.organizationKind != null && (
136
+ <li><OrganizationKind kind={data.organizationKind} /></li>
137
+ )}
138
+ // end-change
139
+ </ul>
140
+ </>
141
+ );
142
+ }
143
+ ```
144
+
145
+ You should now see the location of people, and the organization kind for organizations:
146
+
147
+ ![An organization hovercard](/img/docs/tutorial/interfaces-organization-screenshot.png) ![A person hovercard](/img/docs/tutorial/interfaces-person-screenshot.png)
148
+
149
+ By the way, we can now understand why we had `... on Actor` in the example earlier. The `node` field can return a node of any type because any ID could be given at runtime. So the type that it gives us is `Node`, a very generic interface that can be implemented by anything that has an `id` field. We needed a type refinement to use fields from the `Actor` interface.
150
+
151
+ :::note
152
+ In the GraphQL spec and other sources, type refinements are called *inline fragments*. We call them “type refinements” instead because this terminology is more descriptive and less confusing.
153
+ :::
154
+
155
+ :::tip
156
+ If you need to do something totally different depending on what type it is, you can select a field called `__typename`, which returns a string with the name of the concrete type that you got (e.g., `"Person"` or `"Organization"`). This is a built-in feature of GraphQL.
157
+ :::
158
+
159
+ ## Summary
160
+
161
+ The `... on Type {}` syntax allows us to select fields that are only present in a specific type that implements an interface.
@@ -0,0 +1,58 @@
1
+ # Tutorial Intro
2
+
3
+ This tutorial will get you started with the most important and frequently-used features of Relay. To do that, we’ll build a simple app that displays a newsfeed. We will cover:
4
+
5
+ * How to fetch data using [Queries](./queries-1.mdx).
6
+ * How to make components self-contained by breaking [Queries](./queries-1.mdx) into [Fragments](./fragments-1.mdx).
7
+
8
+ This tutorial assumes a fair familiarity with React. If you’re still new to React, we suggest going through the [React tutorial](https://reactjs.org/tutorial/) and working with React until you’re comfortable with creating components, passing props, and using the basic hooks such as `useState`. The tutorial is based on the Web, but Relay also works great with React Native.
9
+
10
+ This tutorial is built with TypeScript, so [very basic knowledge of TypeScript](https://www.typescriptlang.org/docs/) is helpful as well — you don’t need to know anything beyond declaring and importing types and annotating functions. Relay can also be used with the Flow type system or without a type system.
11
+
12
+ :::info
13
+ **IMPORTANT**: The tutorial is meant to be gone through in order, as the exercises build on each other. You’ll be making incremental changes to an example app, so later section won’t make sense if you haven’t done the earlier sections.
14
+ :::
15
+
16
+ ## Setup
17
+
18
+ To get started, run the following commands:
19
+
20
+ ```
21
+ git clone https://github.com/relayjs/relay-examples.git
22
+ cd relay-examples/newsfeed
23
+ npm install
24
+ npm run dev
25
+ ```
26
+
27
+ This downloads a template project to get started from and starts the server. (If they don’t work, you may need to [install git](https://github.com/git-guides/install-git) or [install npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm).)
28
+
29
+ When you run `npm run dev`, several processes are started:
30
+
31
+ * A Webpack-based HTTP server that serves up the front-end code.
32
+ * A basic GraphQL server that that front-end will query to retrieve information.
33
+ * The Relay compiler, which processes the GraphQL in your app and generates additional files that Relay uses at runtime, as well as TypeScript types representing the inputs and results of your queries. It will automatically regenerate when you save changes in your files.
34
+
35
+ In the terminal output, these three processes’ log output are marked with tags: `[webpack]` in yellow, `[server]` in green, and `[relay]` in blue. Keep a look out for errors marked with `[relay]` as these are helpful if your GraphQL has any mistakes.
36
+
37
+ If you encounter errors in the `[relay]` process indicating: ```[relay] thread 'main' panicked at 'Cannot run relay in watch mode if `watchman` is not available (or explicitly disabled).'```, this means watchman is not installed or available on your system. To resolve this, you may need to [install watchman separately](https://facebook.github.io/watchman/docs/install). After installing watchman, try running `npm run dev` again.
38
+
39
+ Now that these processes are running, you should be able to open [http://localhost:3000](http://localhost:3000/) in your browser.
40
+
41
+ ![Screenshot](/img/docs/tutorial/intro-screenshot-placeholder.png)
42
+
43
+ We start from a webpage that shows a single Newsfeed story rendered with React, but the data for that story is just placeholder data hard-coded into the React components. In the rest of this tutorial, we’ll make the app functional by having it fetch data from the server, paginate over multiple stories, and update the data by commenting and liking.
44
+
45
+ ## Folder Structure
46
+
47
+ The files that make up the example app are laid out in this way:
48
+
49
+ * `src/components` — the front-end app components that we’ll be modifying and working with. Some of the important components are:
50
+ * `App.tsx` — the top-level component
51
+ * `Newsfeed.tsx` — a component that will run a query to fetch newsfeed stories and display a scrolling list of stories
52
+ * `Story.tsx` — a component that shows a single newsfeed story.
53
+ * `server` — a very basic GraphQL server that serves up example data
54
+ * `server/schema.graphql` — the GraphQL schema: it specifies what information can be queried from the server via GraphQL.
55
+
56
+ Finally, you may want to install the [Relay VSCode extension](https://marketplace.visualstudio.com/items?itemName=meta.relay) for autocomplete, errors, and other help when using VSCode.
57
+
58
+ Head over to the next section to start learning about GraphQL and Relay.