1"use strict";(self.webpackChunk=self.webpackChunk||[]).push([["12026"],{92046(e,n,i){i.r(n),i.d(n,{metadata:()=>t,default:()=>u,frontMatter:()=>d,contentTitle:()=>l,toc:()=>c,assets:()=>o});var t=JSON.parse('{"id":"guided-tour/reusing-cached-data/filling-in-missing-data","title":"Filling in Missing Data (Missing Field Handlers)","description":"Relay guide to filling in missing data","source":"@site/versioned_docs/version-v19.0.0/guided-tour/reusing-cached-data/filling-in-missing-data.md","sourceDirName":"guided-tour/reusing-cached-data","slug":"/guided-tour/reusing-cached-data/filling-in-missing-data/","permalink":"/docs/v19.0.0/guided-tour/reusing-cached-data/filling-in-missing-data/","draft":false,"unlisted":false,"editUrl":"https://github.com/facebook/relay/tree/main/website/versioned_docs/version-v19.0.0/guided-tour/reusing-cached-data/filling-in-missing-data.md","tags":[],"version":"v19.0.0","frontMatter":{"id":"filling-in-missing-data","title":"Filling in Missing Data (Missing Field Handlers)","slug":"/guided-tour/reusing-cached-data/filling-in-missing-data/","description":"Relay guide to filling in missing data","keywords":["missing field handler","missing data"]},"sidebar":"docs","previous":{"title":"Rendering Partially Cached Data","permalink":"/docs/v19.0.0/guided-tour/reusing-cached-data/rendering-partially-cached-data/"},"next":{"title":"Retaining Queries","permalink":"/docs/v19.0.0/guided-tour/accessing-data-without-react/retaining-queries/"}}'),a=i(74848),s=i(28453),r=i(86898);i(17352);let d={id:"filling-in-missing-data",title:"Filling in Missing Data (Missing Field Handlers)",slug:"/guided-tour/reusing-cached-data/filling-in-missing-data/",description:"Relay guide to filling in missing data",keywords:["missing field handler","missing data"]},l,o={},c=[];function h(e){let n={code:"code",em:"em",li:"li",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.p,{children:"In the previous section we covered how to reuse data that is fully or partially cached, however there are cases in which Relay can't automatically tell that it can reuse some of the data it already has from other queries in order to fulfill a specific query. Specifically, Relay knows how to reuse data that is cached for a query that has been fetched before; that is, if you fetch the exact same query twice, Relay will know that it has the data cached for that query the second time it tries to evaluate it."}),"\n",(0,a.jsx)(n.p,{children:"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:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-js",children:"// Query 1\n\nquery UserQuery {\n user(id: 4) {\n name\n }\n}\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-js",children:"// Query 2\n\nquery NodeQuery {\n node(id: 4) {\n ... on User {\n name\n }\n }\n}\n"})}),"\n",(0,a.jsxs)(n.p,{children:["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 ",(0,a.jsx)(n.code,{children:"node(id: 4)"})," ",(0,a.jsx)(n.em,{children:'"is the same as"'})," ",(0,a.jsx)(n.code,{children:"user(id: 4)"}),"."]}),"\n",(0,a.jsxs)(n.p,{children:["To do so, we can provide ",(0,a.jsx)(n.code,{children:"missingFieldHandlers"})," to the ",(0,a.jsx)(n.code,{children:"RelayEnvironment"})," which specifies this knowledge."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-js",children:"const {ROOT_TYPE, Environment} = require('relay-runtime');\n\nconst missingFieldHandlers = [\n {\n handle(field, record, argValues): ?string {\n // Make sure to add a handler for the node field\n if (\n record != null &&\n record.getType() === ROOT_TYPE &&\n field.name === 'node' &&\n argValues.hasOwnProperty('id')\n ) {\n return argValues.id\n }\n if (\n record != null &&\n record.getType() === ROOT_TYPE &&\n field.name === 'user' &&\n argValues.hasOwnProperty('id')\n ) {\n // If field is user(id: $id), look up the record by the value of $id\n return argValues.id;\n }\n if (\n record != null &&\n record.getType() === ROOT_TYPE &&\n field.name === 'story' &&\n argValues.hasOwnProperty('story_id')\n ) {\n // If field is story(story_id: $story_id), look up the record by the\n // value of $story_id.\n return argValues.story_id;\n }\n return undefined;\n },\n kind: 'linked',\n },\n];\n\nconst environment = new Environment({/*...*/, missingFieldHandlers});\n"})}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"missingFieldHandlers"})," is an array of ",(0,a.jsx)(n.em,{children:"handlers"}),". Each handler must specify a ",(0,a.jsx)(n.code,{children:"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:","\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.em,{children:"'scalar'"}),": This represents a field that contains a scalar value, for example a number or a string."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.em,{children:"'linked'"}),": This represents a field that references another object, i.e. not a scalar."]}),"\n"]}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["The ",(0,a.jsx)(n.code,{children:"handle"})," function takes the field that is missing, the record that field belongs to, and any arguments that were passed to the field in the current execution of the query.","\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["When handling a ",(0,a.jsx)(n.em,{children:"'scalar'"})," field, the handle function should return a scalar value, in order to use as the value for a missing field"]}),"\n",(0,a.jsxs)(n.li,{children:["When handling a ",(0,a.jsx)(n.em,{children:"'linked'"})," field*,* the handle function should return an ",(0,a.jsx)(n.em,{children:"ID"}),", referencing another object in the store that should be use in place of the missing field. **"]}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(n.li,{children:"As Relay attempts to fulfill a query from the local cache, whenever it detects any missing data, it will run any of the provided missing field handlers that match the field type before definitively declaring that the data is missing."}),"\n"]}),"\n",(0,a.jsx)(r.A,{})]})}function u(e={}){let{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(h,{...e})}):h(e)}},86898(e,n,i){i.d(n,{A:()=>f});var t=i(74848),a=i(95310),s=i(17352),r=i(96540);function d(){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_
1support**",tag_ids:{add:[0xac96423e5b680,0x64079768ac750]}}));window.open("https://www.internalfb.com/tasks/?n="+e)}function l({children:e}){return(0,t.jsxs)("div",{className:"docsRating",id:"docsRating",children:[(0,t.jsx)("hr",{}),e]})}let o=()=>{let[e,n]=r.useState(!1),i=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,t.jsxs)(t.Fragment,{children:["Is this page useful?",(0,t.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:()=>i(1),children:(0,t.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,t.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:()=>i(0),children:(0,t.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,t.jsxs)("p",{children:["Let us know how these docs can be improved by",(0,t.jsx)("a",{className:"button",role:"button",tabIndex:0,onClick:d,children:"Filing a task"})]}),h=()=>(0,t.jsxs)("p",{children:["Help us make the site even better by"," ",(0,t.jsx)(a.default,{to:"https://www.surveymonkey.com/r/FYC9TCJ",children:"answering a few quick questions"}),"."]}),u=()=>(0,t.jsxs)(l,{children:[(0,t.jsx)(c,{}),(0,t.jsx)(o,{}),(0,t.jsx)(h,{})]}),g=()=>(0,t.jsxs)(l,{children:[(0,t.jsx)(o,{}),(0,t.jsx)(h,{})]}),f=()=>(0,s.fbContent)({internal:(0,t.jsx)(u,{}),external:(0,t.jsx)(g,{})})},28453(e,n,i){i.d(n,{R:()=>r,x:()=>d});var t=i(96540);let a={},s=t.createContext(a);function r(e){let n=t.useContext(s);return t.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),t.createElement(s.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.