1"use strict";(self.webpackChunk=self.webpackChunk||[]).push([["17185"],{26677(e,n,r){r.r(n),r.d(n,{metadata:()=>i,default:()=>p,frontMatter:()=>d,contentTitle:()=>o,toc:()=>h,assets:()=>c});var i=JSON.parse('{"id":"api-reference/graphql/graphql-directives","title":"GraphQL Directives","description":"API Reference for GraphQL directives","source":"@site/versioned_docs/version-v18.0.0/api-reference/graphql/graphql-directives.md","sourceDirName":"api-reference/graphql","slug":"/api-reference/graphql-and-directives/","permalink":"/docs/v18.0.0/api-reference/graphql-and-directives/","draft":false,"unlisted":false,"editUrl":"https://github.com/facebook/relay/tree/main/website/versioned_docs/version-v18.0.0/api-reference/graphql/graphql-directives.md","tags":[],"version":"v18.0.0","frontMatter":{"id":"graphql-directives","title":"GraphQL Directives","slug":"/api-reference/graphql-and-directives/","description":"API Reference for GraphQL directives","keywords":["GraphQL","Directive","arguments","argumentDefinitions","connection","relay","inline","provider"]},"sidebar":"docs","previous":{"title":"Runtime Functions","permalink":"/docs/v18.0.0/api-reference/relay-resolvers/runtime-functions/"},"next":{"title":"Testing Relay Components","permalink":"/docs/v18.0.0/guides/testing-relay-components/"}}'),t=r(74848),a=r(28453),s=r(86898),l=r(17352);let d={id:"graphql-directives",title:"GraphQL Directives",slug:"/api-reference/graphql-and-directives/",description:"API Reference for GraphQL directives",keywords:["GraphQL","Directive","arguments","argumentDefinitions","connection","relay","inline","provider"]},o,c={},h=[{value:"<code>@arguments</code>",id:"arguments",level:2},{value:"<code>@argumentDefinitions</code>",id:"argumentdefinitions",level:2},{value:"Provided Variables",id:"provided-variables",level:3},{value:"<code>@catch</code>",id:"catch",level:2},{value:"<code>@connection(key: String!, filters: [String])</code>",id:"connectionkey-string-filters-string",level:2},{value:"<code>@refetchable(queryName: String!, directives: [String], preferFetchable: Boolean)</code>",id:"refetchablequeryname-string-directives-string-preferfetchable-boolean",level:2},{value:"<code>@relay(plural: Boolean)</code>",id:"relayplural-boolean",level:2},{value:"<code>@required</code>",id:"required",level:2},{value:"<code>@throwOnFieldError</code>",id:"throwonfielderror",level:2},{value:"<code>@semanticNonNull</code>",id:"semanticnonnull",level:2},{value:"<code>@alias</code>",id:"alias",level:2},{value:"<code>@inline</code>
1",id:"inline",level:2},{value:"<code>@relay(mask: Boolean)</code>",id:"relaymask-boolean",level:2},{value:"<code>@waterfall</code>",id:"waterfall",level:2}];function u(e){let n={a:"a",code:"code",em:"em",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,a.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(n.p,{children:["Relay uses directives to add additional information to GraphQL documents, which\nare used by the ",(0,t.jsx)(n.a,{href:"../../guides/compiler/",children:"Relay compiler"})," to generate the\nappropriate runtime artifacts. These directives only appear in your application\ncode and are removed from requests sent to your GraphQL server."]}),"\n",(0,t.jsx)(l.OssOnly,{children:(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Note:"})," The Relay compiler will maintain any directives supported by your server (such as ",(0,t.jsx)(n.code,{children:"@include"})," or ",(0,t.jsx)(n.code,{children:"@skip"}),") so they remain part of the request to the GraphQL server and won't alter generated runtime artifacts."]})}),"\n",(0,t.jsx)(l.FbInternalOnly,{children:(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Note:"})," The Relay compiler will maintain any directives supported by your server (such as ",(0,t.jsx)(n.code,{children:"@include"})," or ",(0,t.jsx)(n.code,{children:"@skip"}),") so they remain part of the request to the GraphQL server and won't alter generated runtime artifacts. Additional directives are documented ",(0,t.jsx)(n.a,{href:"https://www.internalfb.com/intern/wiki/GraphQL/APIs_and_References/Directives/#graphql-standard",children:"here"}),"."]})}),"\n",(0,t.jsx)(n.h2,{id:"arguments",children:(0,t.jsx)(n.code,{children:"@arguments"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"@arguments"})," is a directive used to pass arguments to a fragment that was\ndefined using ",(0,t.jsx)(n.a,{href:"#argumentdefinitions",children:(0,t.jsx)(n.code,{children:"@argumentDefinitions"})}),". For example:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-graphql",children:"query TodoListQuery($userID: ID) {\n ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here\n}\n"})}),"\n",(0,t.jsx)(n.h2,{id:"argumentdefinitions",children:(0,t.jsx)(n.code,{children:"@argumentDefinitions"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"@argumentDefinitions"})," is a directive used to specify arguments taken by a\nfragment. For example:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-graphql",children:'fragment TodoList_list on TodoList\n@argumentDefinitions(\n count: {type: "Int", defaultValue: 10} # Optional argument\n userID: {type: "ID"} # Required argument\n) {\n title\n todoItems(userID: $userID, first: $count) {\n # Use fragment arguments here as variables\n ...TodoItem_item\n }\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"provided-variables",children:"Provided Variables"}),"\n",(0,t.jsx)(n.p,{children:"A provided variable is a special fragment variable whose value is supplied by a\nspecified provider function at runtime. This simplifies supplying device\nattributes, user experiment flags, and other runtime constants to graphql\nfragments."}),"\n",(0,t.jsx)(n.p,{children:"To add a provided variable:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["add an argument with ",(0,t.jsx)(n.code,{children:'provider: "[JSModule].relayprovider"'})," to\n",(0,t.jsx)(n.code,{children:"@argumentDefinitions"})]}),"\n",(0,t.jsxs)(n.li,{children:["ensure that ",(0,t.jsx)(n.code,{children:"[JSModule].relayprovider.js"})," exists and exports a ",(0,t.jsx)(n.code,{children:"get()"}),"\nfunction","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"get"})," should return the same value on every call for a given run."]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-graphql",children:'fragment TodoItem_item on TodoList\n@argumentDefinitions(\n include_timestamp: {\n type: "Boolean!"\n provider: "Todo_ShouldIncludeTimestamp.relayprovider"\n }\n) {\n timestamp @include(if: $include_timestamp)\n text\n}\n'})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-javascript",children:"// Todo_ShouldIncludeTimestamp.relayprovider.js\nexport default {\n get(): boolean {\n // must al
1ways return true or false for a given run\n return check('todo_should_include_timestamp');\n },\n};\n"})}),"\n",(0,t.jsx)(n.p,{children:"Notes:"}),"\n",(0,t.jsx)(l.FbInternalOnly,{children:(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Even though fragments declare provided variables in ",(0,t.jsx)(n.code,{children:"argumentDefinitions"}),",\ntheir parent cannot pass provided variables through ",(0,t.jsx)(n.code,{children:"@arguments"}),"."]}),"\n",(0,t.jsx)(n.li,{children:"An argument definition cannot specify both a provider and a defaultValue."}),"\n",(0,t.jsxs)(n.li,{children:["If the modified fragment is included in operations that use hack preloaders\n(",(0,t.jsx)(n.code,{children:"@preloadable(hackPreloader: true)"}),"), you will need to manually add provided\nvariables when calling ",(0,t.jsx)(n.code,{children:"RelayPreloader::gen"}),".","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Hack's typechecker will fail with\n",(0,t.jsx)(n.code,{children:"The field __relay_internal__pv__[JsModule] is missing."})]}),"\n",(0,t.jsxs)(n.li,{children:["We strongly encourage switching to\n",(0,t.jsx)(n.a,{href:"../../guides/entrypoints/using-entrypoints/",children:"Entrypoints"})," if possible."]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.em,{children:"Unstable / subject to change"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Relay transforms provided variables to operation root variables and renames\nthem to ",(0,t.jsx)(n.code,{children:"__relay_internal__pv__[JsModule]"}),".","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Only relevant if you are debugging a query that uses provided variables."}),"\n"]}),"\n"]}),"\n"]}),"\n"]}),"\n"]})}),"\n",(0,t.jsx)(l.OssOnly,{children:(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Even though fragments declare provided variables in ",(0,t.jsx)(n.code,{children:"argumentDefinitions"}),",\ntheir parent cannot pass provided variables through ",(0,t.jsx)(n.code,{children:"@arguments"}),"."]}),"\n",(0,t.jsx)(n.li,{children:"An argument definition cannot specify both a provider and a defaultValue."}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.em,{children:"Unstable / subject to change"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Relay transforms provided variables to operation root variables and renames\nthem to ",(0,t.jsx)(n.code,{children:"__relay_internal__pv__[JsModule]"}),".","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Only relevant if you are debugging a query that uses provided variables."}),"\n"]}),"\n"]}),"\n"]}),"\n"]}),"\n"]})}),"\n",(0,t.jsx)(n.h2,{id:"catch",children:(0,t.jsx)(n.code,{children:"@catch"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"@catch"})," is a directive you can add to fields in your Relay queries to declare\nhow field-level exceptions are handled in runtime."]}),"\n",(0,t.jsxs)(n.p,{children:["See also ",(0,t.jsx)(n.a,{href:"../../guides/catch-directive/",children:"the @catch guide"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"connectionkey-string-filters-string",children:(0,t.jsx)(n.code,{children:"@connection(key: String!, filters: [String])"})}),"\n",(0,t.jsxs)(n.p,{children:["With ",(0,t.jsx)(n.code,{children:"usePaginationFragment"}),", Relay expects connection fields to be annotated\nwith a ",(0,t.jsx)(n.code,{children:"@connection"})," directive. For more detailed information and an example,\ncheck out the\n",(0,t.jsxs)(n.a,{href:"../../guided-tour/list-data/rendering-connections",children:["docs on ",(0,t.jsx)(n.code,{children:"usePaginationFragment"})]}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"refetchablequeryname-string-directives-string-preferfetchable-boolean",children:(0,t.jsx)(n.code,{children:"@refetchable(queryName: String!, directives: [String], preferFetchable: Boolean)"})}),"\n",(0,t.jsxs)(n.p,{children:["With ",(0,t.jsx)(n.code,{children:"useRefetchableFragment"})," and ",(0,t.jsx)(n.code,{children:"usePaginationFragment"}),", Relay expects a\n",(0,t.jsx)(n.code,{children:"@refetchable"})," directive. The ",(0,t.jsx)(n.code,{children:"@refetchable"}),' directive can only be added to\nfragments that are "refetchable", that is, on fragments that are declared on\n',(0,t.jsx)(n.code,{children:"Viewer"})," or ",(0,t.jsx)(n.code,{children:"Query"})," types, or on a type that implements ",(0,t.jsx)(n.code,{children:"Node"}
1)," (i.e. a type that\nhas an id). The ",(0,t.jsx)(n.code,{children:"@refetchable"})," directive will autogenerate a query with the\nspecified ",(0,t.jsx)(n.code,{children:"queryName"}),". This will also generate Flow types for the query,\navailable to import from the generated file: ",(0,t.jsx)(n.code,{children:"<queryName>.graphql.js"}),". For more\ndetailed information and examples, check out the docs on\n",(0,t.jsx)(n.a,{href:"../use-refetchable-fragment/",children:(0,t.jsx)(n.code,{children:"useRefetchableFragment"})})," or\n",(0,t.jsx)(n.a,{href:"../use-pagination-fragment/",children:(0,t.jsx)(n.code,{children:"usePaginationFragment"})}),"."]}),"\n",(0,t.jsxs)(n.p,{children:["Optionally, you can pass in a list of directives to add to the autogenerated\nquery. For example, this can be used to add the ",(0,t.jsx)(n.code,{children:"@relay_test_operation"}),"\ndirective for ",(0,t.jsx)(n.a,{href:"../../guides/testing-relay-components",children:"testing"}),":"]}),"\n",(0,t.jsxs)(n.p,{children:["[Optional] ",(0,t.jsx)(n.code,{children:"preferFetchable: Boolean"})]}),"\n",(0,t.jsxs)(n.p,{children:["This argument tells the Relay compiler to prefer generating\n",(0,t.jsx)(n.code,{children:"fetch_MyType(): MyType"})," queries for types that implement the ",(0,t.jsx)(n.code,{children:"Node"})," interface.\nThis is useful for schemas that have adopted the ",(0,t.jsx)(n.code,{children:"@strong"})," and ",(0,t.jsx)(n.code,{children:"@fetchable"}),"\nserver annotations for types. You can directly fetch concrete objects without\nneeding to refine ",(0,t.jsx)(n.code,{children:"Node"})," interface to a specific type."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-javascript",children:'graphql`\n fragment FriendsListComponent_user on User\n @refetchable(\n queryName: "FriendsListFetchQuery"\n directives: ["@relay_test_operation"]\n ) {\n ...\n }\n`;\n'})}),"\n",(0,t.jsx)(n.h2,{id:"relayplural-boolean",children:(0,t.jsx)(n.code,{children:"@relay(plural: Boolean)"})}),"\n",(0,t.jsxs)(n.p,{children:["When defining a fragment for use with a Fragment container, you can use the\n",(0,t.jsx)(n.code,{children:"@relay(plural: true)"})," directive to indicate that container expects the prop for\nthat fragment to be a list of items instead of a single item. A query or parent\nthat spreads a ",(0,t.jsx)(n.code,{children:"@relay(plural: true)"})," fragment should do so within a plural\nfield (ie a field backed by a\n",(0,t.jsx)(n.a,{href:"http://graphql.org/learn/schema/#lists-and-non-null",children:"GraphQL list"}),". For\nexample:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-javascript",children:"// Plural fragment definition\ngraphql`\n fragment TodoItems_items on TodoItem @relay(plural: true) {\n id\n text\n }\n`;\n\n// Plural fragment usage: note the parent type is a list of items (`TodoItem[]`)\nfragment TodoApp_app on App {\n items {\n // parent type is a list here\n ...TodoItem_items\n }\n}\n"})}),"\n",(0,t.jsx)(n.h2,{id:"required",children:(0,t.jsx)(n.code,{children:"@required"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"@required"})," is a directive you can add to fields in your Relay queries to\ndeclare how null values should be handled at runtime."]}),"\n",(0,t.jsxs)(n.p,{children:["See also ",(0,t.jsx)(n.a,{href:"../../guides/required-directive/",children:"the @required guide"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"throwonfielderror",children:(0,t.jsx)(n.code,{children:"@throwOnFieldError"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"@throwOnFieldError"})," is a directive you can add to your Relay queries and fragments to have Relay throw if any field errors are encountered when reading the query or fragment. Adding the directive will allow Relay to generate non-null types for any fields marked as ",(0,t.jsx)(n.code,{children:"@semanticNonNull"})," in the schema."]}),"\n",(0,t.jsxs)(n.p,{children:["See also ",(0,t.jsx)(n.a,{href:"../../guides/throw-on-field-error-directive/",children:"the @throwOnFieldError guide"}),"."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsxs)(n.strong,{children:["Read more about Relay's experimental support for\n",(0,t.jsx)(n.a,{href:"/docs/v18.0.0/guides/semantic-nullability/",children:"Semantic Nullability"}),"."]})}),"\n",(0,t.jsx)(n.h2,{id:"semanticnonnull",children:(0,t.jsx)(n.code,{children:"@semanticNonNull"})}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.code,{children:"@semanticNonNull"})," directive can be added to fields in your schema to\nindicate that the field is non-nullable in the semantic sense, but that the\nclient should still be prepared to handle errors."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsxs)(n.strong,{children:["Read more about Relay's experimental support for\n",(0,t.jsx)(n.a,{href:"/docs/v18.0.0/guides/semantic-nullability/",children:"Semantic Nullability"}),"."]})}),"\n",(0,t.jsx)(n.h2,{id:"alias",children:(0,t.jsx)(n.code,{children:"@alias"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"@alias"})," is a directive that allows you to give a fragment spread or inline\nfragment an alias, similar to a field alias. This is useful when you want to\nconditionally include a fragment and check if it was fetched, or otherwise group\ndata together."]}),"\n",(0,t.jsxs)(n.p,{children:["For fragment spreads, the alias will default to the fragment name. For inline\nfragments, the alias will default to the type name. If you wish to
1supply your\nown name, or you have an inline fragment without any type condition, you can\nspecify the alias using the ",(0,t.jsx)(n.code,{children:"as"})," argument."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-graphql",children:'fragment MyFragment on User {\n ... on User @alias(as: "myGreatAlias") {\n name\n }\n}\n'})}),"\n",(0,t.jsxs)(n.p,{children:["See also ",(0,t.jsx)(n.a,{href:"../../guides/alias-directive/",children:"the @alias guide"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"inline",children:(0,t.jsx)(n.code,{children:"@inline"})}),"\n",(0,t.jsxs)(n.p,{children:["The hooks APIs that Relay exposes allow you to read data from the store only\nduring the render phase. In order to read data from outside of the render phase\n(or from outside of React), Relay exposes the ",(0,t.jsx)(n.code,{children:"@inline"})," directive. The data from\na fragment annotated with ",(0,t.jsx)(n.code,{children:"@inline"})," can be read using ",(0,t.jsx)(n.code,{children:"readInlineData"}),"."]}),"\n",(0,t.jsxs)(n.p,{children:["In the example below, the function ",(0,t.jsx)(n.code,{children:"processItemData"})," is called from a React\ncomponent. It requires an item object with a specific set of fields. All React\ncomponents that use this function should spread the ",(0,t.jsx)(n.code,{children:"processItemData_item"}),"\nfragment to ensure all of the correct item data is loaded for this function."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-javascript",children:"import {graphql, readInlineData} from 'react-relay';\n\n// non-React function called from React\nfunction processItemData(itemRef) {\n const item = readInlineData(\n graphql`\n fragment processItemData_item on Item @inline {\n title\n price\n creator {\n name\n }\n }\n `,\n itemRef,\n );\n sendToThirdPartyApi({\n title: item.title,\n price: item.price,\n creatorName: item.creator.name,\n });\n}\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-javascript",children:"export default function MyComponent({item}) {\n function handleClick() {\n processItemData(item);\n }\n\n const data = useFragment(\n graphql`\n fragment MyComponent_item on Item {\n ...processItemData_item\n title\n }\n `,\n item,\n );\n\n return <button onClick={handleClick}>Process {item.title}</button>;\n}\n"})}),"\n",(0,t.jsx)(n.h2,{id:"relaymask-boolean",children:(0,t.jsx)(n.code,{children:"@relay(mask: Boolean)"})}),"\n",(0,t.jsxs)(n.p,{children:["It is not recommended to use ",(0,t.jsx)(n.code,{children:"@relay(mask: false)"}),". Please instead consider\nusing the ",(0,t.jsx)(n.code,{children:"@inline"})," fragment."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"@relay(mask: false)"})," can be used to prevent data masking; when including a\nfragment and annotating it with ",(0,t.jsx)(n.code,{children:"@relay(mask: false)"}),", its data will be\navailable directly to the parent instead of being masked for a different\ncontainer."]}),"\n",(0,t.jsxs)(n.p,{children:["Applied to a fragment definition, ",(0,t.jsx)(n.code,{children:"@relay(mask: false)"})," changes the generated\nFlow types to be better usable when the fragment is included with the same\ndirective. The Flow types will no longer be exact objects and no longer contain\ninternal marker fields."]}),"\n",(0,t.jsx)(n.p,{children:"This may be helpful to reduce redundant fragments when dealing with nested or\nrecursive data within a single Component."}),"\n",(0,t.jsxs)(n.p,{children:["Keep in mind that it is typically considered an ",(0,t.jsx)(n.strong,{children:"anti-pattern"})," to create a\nsingle fragment shared across many containers. Abusing this directive could\nresult in over-fetching in your application."]}),"\n",(0,t.jsxs)(n.p,{children:["In the example below, the ",(0,t.jsx)(n.code,{children:"user"})," prop will include the data for ",(0,t.jsx)(n.code,{children:"id"})," and ",(0,t.jsx)(n.code,{children:"name"}),"\nfields wherever ",(0,t.jsx)(n.code,{children:"...Component_internUser"}
1)," is included, instead of Relay's normal\nbehavior to mask those fields:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-javascript",children:"graphql`\n fragment Component_internUser on InternUser @relay(mask: false) {\n id\n name\n }\n`;\n"})}),"\n",(0,t.jsx)(n.h2,{id:"waterfall",children:(0,t.jsx)(n.code,{children:"@waterfall"})}),"\n",(0,t.jsxs)(n.p,{children:["With ",(0,t.jsx)(n.a,{href:"/docs/v18.0.0/guides/relay-resolvers/introduction",children:"Relay Resolvers"})," it's\npossible to create client-defined edges in the graph which point to server\ntypes. When reading these edge fields, Relay is forced to lazily fetch the\nserver data for the edge. This will force Relay to make a second request to the\nserver to fetch the data for the edge."]}),"\n",(0,t.jsxs)(n.p,{children:["To highlight this tradeoff both in the editor and during code review, the Relay\ncompiler expects all reads of these fields to be annotated as ",(0,t.jsx)(n.code,{children:"@waterfall"}),"."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-graphql",children:"fragment EditPost on DraftPost {\n author @waterfall {\n name\n }\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["See the ",(0,t.jsx)(n.a,{href:"/docs/v18.0.0/guides/relay-resolvers/return-types/#server-types",children:"Return Type"}),"\nportion of the Relay Resolvers guide for more information."]}),"\n",(0,t.jsx)(s.A,{})]})}function p(e={}){let{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(u,{...e})}):u(e)}},86898(e,n,r){r.d(n,{A:()=>m});var i=r(74848),t=r(95310),a=r(17352),s=r(96540);function l(){let e=window.encodeURI(JSON.stringify({title:"Feedback about "+window.location.pathname,description:"**!!! Required !!!**\n\nPlease modify the task description to let us know how the docs can be improved.\n\n**Please do not ask support questions via this form! Instead, ask in fburl.com/relay_support**",tag_ids:{add:[0xac96423e5b680,0x64079768ac750]}}));window.open("https://www.internalfb.com/tasks/?n="+e)}function d({children:e}){return(0,i.jsxs)("div",{className:"docsRating",id:"docsRating",children:[(0,i.jsx)("hr",{}),e]})}let o=()=>{let[e,n]=s.useState(!1),r=e=>{n(!0),window.ga&&window.ga("send",{hitType:"event",eventCategory:"button",eventAction:"feedback",eventValue:e})};return e?"Thank you for letting us know!":(0,i.jsxs)(i.Fragment,{children:["Is this page useful?",(0,i.jsx)("svg",{className:"i_thumbsup",alt:"Like",id:"docsRating-like",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 81.13 89.76",onClick:()=>r(1),children:(0,i.jsx)("path",{d:"M22.9 6a18.57 18.57 0 002.67 8.4 25.72 25.72 0 008.65 7.66c3.86 2 8.67 7.13 13.51 11 3.86 3.11 8.57 7.11 11.54 8.45s13.59.26 14.64 1.17c1.88 1.63 1.55 9-.11 15.25-1.61 5.86-5.96 10.55-6.48 16.86-.4 4.83-2.7 4.88-10.93 4.88h-1.35c-3.82 0-8.24 2.93-12.92 3.62a68 68 0 01-9.73.5c-3.57 0-7.86-.08-13.25-.08-3.56 0-4.71-1.83-4.71-4.48h8.42a3.51 3.51 0 000-7H12.28a2.89 2.89 0 01-2.88-2.88 1.91 1.91 0 01.77-1.78h16.46a3.51 3.51 0 000-7H12.29c-3.21 0-4.84-1.83-4.84-4a6.41 6.41 0 011.17-3.78h19.06a3.5 3.5 0 100-7H9.75A3.51 3.51 0 016 42.27a3.45 3.45 0 013.75-3.48h13.11c5.61 0 7.71-3 5.71-5.52-4.43-4.74-10.84-12.62-11-18.71-.15-6.51 2.6-7.83 5.36-8.56m0-6a6.18 6.18 0 00-1.53.2c-6.69 1.77-10 6.65-9.82 14.5.08 5.09 2.99 11.18 8.52 18.09H9.74a9.52 9.52 0 00-6.23 16.9 12.52 12.52 0 00-2.07 6.84 9.64 9.64 0 003.65 7.7 7.85 7.85 0 00-1.7 5.13 8.9 8.9 0 005.3 8.13 6 6 0 00-.26 1.76c0 6.37 4.2 10.48 10.71 10.48h13.25a73.75 73.75 0 0010.6-.56 35.89 35.89 0 007.58-2.18 17.83 17.83 0 014.48-1.34h1.35c4.69 0 7.79 0 10.5-1 3.85-1.44 6-4.59 6.41-9.38.2-2.46 1.42-4.85 2.84-7.62a41.3 41.3 0 003.42-8.13 48 48 0 001.59-10.79c.1-5.13-1-8.48-3.35-10.55-2.16-1.87-4.64-1.87-9.6-1.88a46.86 46.86 0 01-6.64-.29c-1.92-.94-5.72-4-8.51-6.3l-1.58-1.28c-1.6-1.3-3.27-2.79-4.87-4.23-3.33-3-6.47-5.79-9.61-7.45a20.2 20.2 0 01-6.43-5.53 12.44 12.44 0 01-1.72-5.36 6 6 0 00-6-5.86z"})}),(0,i.jsx)("svg",{className:"i_thumbsdown",alt:"Dislike",id:"docsRating-dislike",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 81.13 89.76",onClick:()=>r(0),children:(0,i.jsx)("path",{d:"M22.9 6a18.57 18.57 0 002.67 8.4 25.72 25.72 0 008.65 7.66c3.86 2 8.67 7.13 13.51 11 3.86 3.11 8.57 7.11 11.54 8.45s13.59.26 14.64 1.17c1.88 1.63 1.55 9-.11 15.25-1.61 5.86-5.96 10.55-6.48 16.86-.4 4.83-2.7 4.88-10.93 4.88h-1.35c-3.82 0-8.24 2.93-12.92 3.62a68 68 0 01-9.73.5c-3.57 0-7.86-.08-13.25-.08-3.56 0-4.71-1.83-4.71-4.48h8.42a3.51 3.51 0 000-7H12.28a2.89 2.89 0 01-2.88-2.88 1.91 1.91 0 01.77-1.78h16.46a3.51 3.51 0 000-7H12.29c-3.21 0-4.84-1.83-4.84-4a6.41 6.41 0 011.17-3.78h19.06a3.5 3.5 0 100-7H9.75A3.51 3.51 0 016 42.27a3.45 3.45 0 013.75-3.48h13.11c5.61 0 7.71-3 5.71-5.52-4.43-4.74-10.84-12.62-11-18.71-.15-6.51 2.6-7.83 5.36-8.56m0-6a6.18 6.18 0 00-1.53.2c-6.69 1.77-10 6.65-9.82 14.5.08 5.09 2.99 11.18 8.52 18.09H9.74a9.52 9.52 0 00-6.23 16.9 12.52 12.52 0 00-2.07 6.84 9.64 9.64 0 003.65 7.7 7.85 7.85 0 00-1.7 5.13 8.9 8.9 0 005.3 8.13 6 6 0 00-.26 1.76c0 6.37 4.2 10.48 10.71 10.48h13.25a73.75 73.75 0 0010.6-.56 35.89 35.89 0 007.58-2.18 17.83 17.83 0 014.48-1.34h1.35c4.69 0 7.79 0 10.5-1 3.85-1.44 6-4.59 6.41-9.38.2-2.46 1.42-4.85 2.84-7.62a41.3 41.3 0 003.42-8.13 48 48 0 001.59-10.79c.1-5.13-1-8.48-3.35-10.55-2.16-1.87-4.64-1.87-9.6-1.88a46.86 46.86 0 01-6.64-.29c-1.92-.94-5.72-4-8.51-6.3l-1.58-1.28c-1.6-1.3-3.27-2.79-4.87-4.23-3.33-3-6.47-5.79-9.61-7.45a20.2 20.2 0 01-6.43-5.53 12.44 12.44 0 01-1.72-5.36 6 6 0 00-6-5.86z"})})]})},c=()=>(0,i.jsxs)("p",{children:["Let us know how these docs can be improved by",(0,i.jsx)("a",{className:"button",role:"button",tabIndex:0,onClick:l,children:"Filing a task"})]}),h=()=>(0,i.jsxs)("p",{children:["Help us make the site even better by"," ",(0,i.jsx)(t.default,{to:"https://www.surveymonkey.com/r/FYC9TCJ",children:"answering a few quick questions"}),"."]}),u=()=>(0,i.jsxs)(d,{children:[(0,i.jsx)(c,{}),(0,i.jsx)(o,{}),(0,i.jsx)(h,{})]}),p=()=>(0,i.jsxs)(d,{children:[(0,i.jsx)(o,{}),(0,i.jsx)(h,{})]}),m=()=>(0,a.fbContent)({internal:(0,i.jsx)(u,{}),external:(0,i.jsx)(p,{})})},28453(e,n,r){r.d(n,{R:()=>s,x:()=>l});var i=r(96540);let t={},a=i.createContext(t);function s(e){let n=i.useContext(a);return i.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:s(e.components),i.createElement(a.Provider,{value:n},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.