Have you ever thought about why a specific piece of technology gets popular? Usually there's never a single reason, but I do have a theory that I think is one of the primary drivers. I call it **The 5 O'Clock Rule**. With The 5 O'Clock Rule, the level of abstraction for solving a problem will bubble up until it allows the average developer to stop thinking about the problem. Unfortunately, it doesn't necessarily matter if the abstraction is elegant, or flexible, or free of leaks. What matters, for the *average* developer, is that they can close their Jira ticket and go home – no later than 5 o'clock. Harsh, I know – but I think it's fair. After all, there's a reason `is-string` gets [28 million downloads](https://www.npmjs.com/package/is-string) a week. On the flip side, there is something magical that happens when an abstraction is both elegant *and* solves The 5 O'Clock Rule. This is the story of my favorite example of a piece of technology solving The 5 O'Clock Rule. A story of how a single developer in a small town in Utah – in his spare time, created a library that is used in one out of every six React applications. For context, that means it gets downloaded 3.3 million times a week and has been downloaded 323 times since you started reading this. That library, of course, is React Query – and in order to better answer how it solves The 5 O'Clock Rule, we need to take a closer look at what problem it helps developers to stop thinking about. Believe it or not, that problem is React. To see why, we need to go back to the basics. In its most fundamental form, React is a library for building user interfaces. It's so simple that, historically, the entire mental model has often been represented as a formula where your View is simply a function of your application's State. <svg id="ReactViewEquation" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 450 150"><title>Diagram showing that view = function(state)</title> <g id="wordState" class="ReactViewEquation_word__c1wsr ReactViewEquation_wordState__yL21u"><text transform="translate(275.37 91.52)" fill="#12b5e5" font-family="Outfit-Medium, Outfit" font-size="40" font-weight="500"><tspan x="0" y="0">tate</tspan></text></g> <g id="wordFunction" class="ReactViewEquation_word__c1wsr ReactViewEquation_wordFunction__kPYP7"><text transform="translate(230.48 91.52)" fill="var(--green)" font-family="Outfit-Medium, Outfit" font-size="40" font-weight="500"><tspan x="0" y="0">unction</tspan></text></g> <g id="wordView" class="ReactViewEquation_word__c1wsr ReactViewEquation_wordView__xzgoc"><text transform="translate(116.18 91.52)" fill="var(--yellow)" font-family="Outfit-Medium, Outfit" font-size="40" font-weight="500"><tspan x="0" y="0">iew</tspan></text></g> <g id="letterV" class="ReactViewEquation_letter__TMLmD ReactViewEquation_letterV__bbYT2"><text transform="translate(156 91.52)" fill="#f9f4da" font-family="Outfit-Medium, Outfit" font-size="40" font-weight="500" class="ReactViewEquation_letter__TMLmD ReactViewEquation_letterVtext__8yQMU"><tspan x="0" y="0">v</tspan></text></g> <text transform="translate(184.36 91.52)" fill="currentColor" font-family="Outfit-Medium, Outfit" font-size="40" font-weight="500"><tspan x="0" y="0">=</tspan></text> <g id="letterF" class="ReactViewEquation_letter__TMLmD undefined"><text transform="translate(214.25 91.52)" fill="#f9f4da" font-family="Outfit-Medium, Outfit" font-size="40" font-weight="500" class="ReactViewEquation_letter__TMLmD ReactViewEquation_letterFtext__tsqiQ"><tspan x="0" y="0">f</tspan></text></g> <g id="parenS" class="ReactViewEquation_letter__TMLmD ReactViewEquation_parenS__MOB6j"><g id="letterS" class="ReactViewEquation_letter__TMLmD undefined"><text transform="translate(258.3 91.52)" fill="#f9f4da" font-family="Outfit-Medium, Outfit" font-size="40" font-weight="500" class="ReactViewEquation_letter__TMLmD ReactViewEquation_letterStext__AW0aM"><tspan x="0" y="0">s</tspan></text></g><g id="closeParen" class="ReactViewEquation_letter__TMLmD ReactViewEquation_closeParen__bzrLa"><text transform="translate(283.65 91.52)" fill="currentColor" font-family="Outfit-Medium, Outfit" font-size="40" font-weight="500"><tspan x="0" y="0">)</tspan></text></g> <text transform="translate(238.38 91.52)" fill="currentColor" font-family="Outfit-Medium, Outfit" font-size="40" font-weight="500"><tspan x="0" y="0">(</tspan></text></g></svg> All you have to do is worry about how the state in your application changes, and React will handle the rest. The primary mode of encapsulation for this concept is the component – which encapsulates both the visual representation of a particular piece of UI as well as the state and logic that goes along with it. By doing so, the same intuition you have about creating and composing together functions can directly apply to creating and composing components. However, instead of composing functions together to get some value, you can compose components together to get some UI. <svg id="ReactView" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 596 280"><title>Interactive diagram showing that a view is a function of state: when state changes the view changes</title><g font-family="Outfit-Medium, Outfit" font-size="67.72" font-weight="500"><text transform="translate(535.73 176.66)" fill="currentColor"><tspan x="0" y="0">) )</tspan></text> <text transform="translate(252.12 176.66)"><tspan x="0" y="0" fill="currentColor">= </tspan><tspan x="50.58" y="0" fill="#0ba95b">f</tspan> <tspan x="77.87" y="0" fill="currentColor">( </tspan><tspan x="125.21" y="0" fill="#f38ba3">g</tspan> <tspan x="164.14" y="0" fill="currentColor">( </tspan></text></g><g id="view"><g id="ui" stroke="#231f20" stroke-miterlimit="10"><rect x="13.81" y="46.22" width="209.97" height="227.19" rx="26.68" ry="26.68" fill="currentColor"></rect><rect x="6.25" y="38.26" width="209.97" height="227.19" rx="21.16" ry="21.16" fill="#0ba95b"></rect><rect x="26.37" y="115.44" width="173.96" height="66.96" rx="10.25" ry="10.25" fill="#231f20"></rect><rect x="23.9" y="111.61" width="173.96" height="66.96" rx="10.25" ry="10.25" fill="#f38ba3"></rect><rect x="26.37" y="63.24" width="173.96" height="38.15" rx="10.25" ry="10.25" fill="#231f20"></rect><rect x="23.74" y="59.58" width="173.96" height="38.15" rx="10.25" ry="10.25" fill="#f9f4da"></rect><rect x="26.37" y="195.35" width="173.96" height="51.67" rx="10.25" ry="10.25" fill="#231f20"></rect><rect x="24.26" y="192.46" width="173.96" height="51.67" rx="10.25" ry="10.25" fill="#f9f4da"></rect><g id="node1" class="ReactViewDupeQuery_node__ve_Bn undefined"><rect x="90.04" y="124.13" width="44.03" height="45.52" rx="10.25" ry="10.25" fill="#231f20"></rect><rect x="88.41" y="122.2" width="44.03" height="45.52" rx="10.25" ry="10.25" fill="#12b5e5"></rect></g></g><g id="pizza2" class="ReactViewDupeQuery_pizza____I1z ReactViewDupeQuery_pizza2__hFUdx" stroke="#231f20" stroke-linejoin="round" stroke-width="0.69"><path d="M95.54 173.79a4.596 4.596 0 01-2.55-4.32l1.96-44.97c-1.76-2.37-2.14-5.62-.77-8.38 1.97-3.98 6.82-5.62 10.8-3.64l33.44 16.57c3.98 1.97 5.62 6.82 3.64 10.8-1.36 2.75-4.17 4.42-7.12 4.46l-3.93 3.24-5.46 4.59s-.09.08-.14.12l-24.87 20.93a4.593 4.593 0 01-5 .6z" fill="#231f20"></path><path d="M94.75 172.12a4.596 4.596 0 01-2.55-4.32l1.96-44.97c-1.76-2.37-2.14-5.62-.77-8.38 1.97-3.98 6.82-5.62 10.8-3.64l33.44 16.57c3.98 1.97 5.62 6.82 3.64 10.8-1.36 2.75-4.17 4.42-7.12 4.46l-3.93 3.24-5.46 4.59s-.09.08-.14.12l-24.87 20.93a4.593 4.593 0 01-5 .6z" fill="#f9f4da"></path><g><path fill="#f9f4da" d="M98.57 128.02L98.95 117.76 135.27 135.76 127.29 142.33 98.57 128.02z"></path><rect x="95.21" y="122.86" width="44.24" height="6.92" rx="3.46" ry="3.46" transform="rotate(26.35 117.352 126.341)" fill="#f9f4da"></rect><path d="M96.79 168l32.56-27.4h0s.03-.04.04-.06c0 0 0-.01.01-.02 0 0 .02-.02.02-.04 0-.01 0-.02.01-.02l.02-.04v-.02s.02-.02.03-.04v-.03-.04-.03-.04-.03-.04-.03-.07s0-.03-.01-.04V140a.705.705 0 00-.24-.37l-1.56-1.24a13.71 13.71 0 00-5.17-2.56 14.28 14.28 0 01-5.39-2.67 13.71 13.71 0 00-5.17-2.56 14.28 14.28 0 01-5.39-2.67 13.71 13.71 0 00-5.17-2.56l-1.91-.48a.637.637 0 00-.45.04h-.01c-.01 0-.03.01-.04.02-.01 0-.02.01-.02.01s-.02.01-.03.02c-.01 0-.02.01-.03.02l-.03.03-.02.02-.03.03s-.01.02-.02.02-.02.02-.02.03c0 0-.01.02-.02.02s-.01.02-.02.03v.03l-.03.03v.02s-.02.03-.03.04v.02c0 .02-.01.04-.01.07h0l-1.89 42.58z" fill="#f9f4da"></path><circle cx="112.29" cy="138.44" r="4.33" fill="#231f20"></circle><path d="M120.61 146.2a4.333 4.333 0 00-5.8 1.96c-.73 1.47-.53 3.14.35 4.39l6.56-5.52c-.32-.32-.69-.61-1.12-.82zM108.17 152.92c-2.14-1.06-4.74-.18-5.8 1.96s-.18 4.74 1.96 5.8c.26.13.54.23.81.31l5.4-4.55c-.13-1.46-.97-2.81-2.38-3.51zM104.69 147.08c1.06-2.14.18-4.74-1.96-5.8-1.62-.8-3.51-.49-4.79.64l-.27 6.19c.34.36.74.69 1.22.92 2.14 1.06 4.74.18 5.8-1.96zM98.53 128.78l-.38 8.54c1.83.31 3.72-.58 4.59-2.33 1.06-2.14.18-4.74-1.96-5.8a4.27 4.27 0 00-2.25-.42z" fill="#231f20"></path></g></g><g id="taco2" class="ReactViewDupeQuery_taco__ctMTU ReactViewDupeQuery_taco2__KKBdZ"><path d="M139.39 166.33l-55.88-5.97a7.172 7.172 0 01-5.03-2.91 7.039 7.039 0 01-1.2-5.58c3.06-14.55 15.66-24.6 30.34-24.49.63-.49 1.39-.98 2.34-1.34 2.33-.88 4.46-.46 6.02-.15.3.06.7.14.97.18 2.85-1.46 6.32-.91 9 1.49.83.74 1.2.95 1.34 1.01.19 0 .51-.01.66-.02 1.19-.06 2.96-.16 4.83.8 1.82.93 2.78 2.4 3.41 3.37.15.22.31.47.38.56.15.17.64.51 1.03.78.48.33 1 .69 1.54 1.14 2.37 1.96 3.54 4.66 3.23 7.26 3.25 5.03 4.94 10.82 4.91 16.9a7.05 7.05 0 01-2.36 5.21 7.2 7.2 0 01-5.53 1.78zm-5.28-25.68h0zm-21.23-6.54h0z" fill="#231f20" stroke="#231f20" stroke-linejoin="round" stroke-width="0.7"></path><path d="M137.46 164.45l-55.88-5.97a7.172 7.172 0 01-5.03-2.91 7.039 7.039 0 01-1.2-5.58c3.06-14.55 15.66-24.6 30.34-24.49.63-.49 1.39-.98 2.34-1.34 2.33-.88 4.46-.46 6.02-.15.3.06.7.14.97.18 2.85-1.46 6.32-.91 9 1.49.83.74 1.2.95 1.34 1.01.19 0 .51-.01.66-.02 1.19-.06 2.96-.16 4.83.8 1.82.93 2.78 2.4 3.41 3.37.15.22.31.47.38.56.15.17.64.51 1.03.78.48.33 1 .69 1.54 1.14 2.37 1.96 3.54 4.66 3.23 7.26 3.25 5.03 4.94 10.82 4.91 16.9a7.05 7.05 0 01-2.36 5.21 7.2 7.2 0 01-5.53 1.78zm-5.28-25.68h0zm-21.23-6.54h0z" fill="#f9f4da" stroke="#231f20" stroke-linejoin="round" stroke-width="0.7"></path><path d="M129.03 158.87l-46.96-5.02c-1.43-.15-2.47-1.5-2.17-2.91 2.73-13.01 14.94-22.09 28.44-20.65 13.5 1.44 23.51 12.9 23.43 26.19 0 1.44-1.31 2.54-2.74 2.39z" fill="#f9f4da" stroke="#231f20" stroke-linejoin="round" stroke-width="0.7"></path><path d="M134.24 136.88c-1.03-.85-2.28-1.46-3.14-2.48-.8-.95-1.28-2.24-2.39-2.81-1.19-.61-2.63-.13-3.96-.3-1.48-.19-2.72-1.16-3.83-2.16-.84-.75-2.44-1.64-3.96-.72-2.11 1.29-4.97-.79-7.29.08-1.5.57-2.42 2.2-3.96 2.66-1.01.31-2.15.06-3.09.53-.71.35-1.18 1.07-1.41 1.82s-.26 1.55-.29 2.34l32.51 6.56c1.01-.37 2.01-1.04 2.31-2.07.37-1.28-.49-2.62-1.51-3.47zM82.44 153.89l10.53 1.13h.02c.23-.36 3.04-11.65 3.16-12.76.17-1.55-.96-2.95-2.51-3.12s-2.95.96-3.12 2.51c-.03.28 0 .55.04.81-.76.27-1.36.85-1.67 1.61-.26-.11-.54-.2-.84-.24-1.55-.17-2.95.96-3.12 2.51-.06.59.06 1.16.33 1.65-.95.37-1.68 1.24-1.79 2.33-.05.5.04.98.23 1.41-.68.45-1.17 1.18-1.27 2.05v.09z" fill="#231f20" stroke="#231f20" stroke-linejoin="round" stroke-width="0.7"></path><rect x="98.02" y="132.67" width="4.47" height="4.47" rx="0.48" ry="0.48" transform="rotate(-14.07 100.255 134.91)" fill="#f9f4da" stroke="#231f20" stroke-linejoin="round" stroke-width="0.7"></rect><rect x="92.01" y="136.33" width="4.47" height="4.47" rx="0.55" ry="0.55" transform="rotate(-28.17 94.25 138.584)" fill="#f9f4da" stroke="#231f20" stroke-linejoin="round" stroke-width="0.7"></rect><circle cx="97.25" cy="137.33" r="2.51" fill="#f9f4da" stroke="#231f20" stroke-linejoin="round" stroke-width="0.7"></circle><path d="M137.95 159.82l-46.96-5.02c-1.43-.15-2.47-1.5-2.17-2.91 2.73-13.01 14.94-22.09 28.44-20.65 13.5 1.44 23.51 12.9 23.43 26.19 0 1.44-1.31 2.54-2.74 2.39z" fill="#f9f4da" stroke="#231f20" stroke-linejoin="round" stroke-width="0.7"></path><g fill="#231f20"><path d="M134.73 149.85c.77 0 .77-1.2 0-1.2s-.77 1.2 0 1.2zM124.32 154.31c.77 0 .77-1.2 0-1.2s-.77 1.2 0 1.2zM125.44 143.84c.77 0 .77-1.2 0-1.2s-.77 1.2 0 1.2zM116.51 137.54c.77 0 .77-1.2 0-1.2s-.77 1.2 0 1.2zM106.34 141.91c.77 0 .77-1.2 0-1.2s-.77 1.2 0 1.2zM114.74 149.03c.77 0 .77-1.2 0-1.2s-.77 1.2 0 1.2zM95.85 146.13c.77 0 .77-1.2 0-1.2s-.77 1.2 0 1.2zM102.67 153.74c.77 0 .77-1.2 0-1.2s-.77 1.2 0 1.2z"></path></g></g><text transform="translate(89.48 24.96)" fill="currentColor" font-family="Paytone One" font-size="16.35"><tspan x="0" y="0">VIEW</tspan></text></g> <g id="letterS" class="ReactViewDupeQuery_letter__bRwOv undefined"><text transform="translate(478.42 176.66)" fill="#12b5e5" font-family="Outfit-Medium, Outfit" font-size="67.72" font-weight="500"><tspan x="0" y="0">s</tspan></text></g><g id="pizza1" class="ReactViewDupeQuery_pizza____I1z undefined" stroke="#231f20" stroke-linejoin="round" stroke-width="0.6"><path d="M478.94 186.39c-1.4-.7-2.27-2.16-2.2-3.72l1.69-38.75c-1.52-2.05-1.84-4.84-.66-7.22 1.7-3.43 5.87-4.84 9.3-3.14l28.82 14.28c3.43 1.7 4.84 5.87 3.14 9.3a6.958 6.958 0 01-6.14 3.84l-3.39 2.79-4.7 3.96s-.08.07-.12.1l-21.43 18.03a3.97 3.97 0 01-4.31.52z" fill="#231f20"></path><path d="M478.26 184.95c-1.4-.7-2.27-2.16-2.2-3.72l1.69-38.75c-1.52-2.05-1.84-4.84-.66-7.22 1.7-3.43 5.87-4.84 9.3-3.14l28.82 14.28c3.43 1.7 4.84 5.87 3.14 9.3a6.958 6.958 0 01-6.14 3.84l-3.39 2.79-4.7 3.96s-.08.07-.12.1l-21.43 18.03a3.97 3.97 0 01-4.31.52z" fill="#f9f4da"></path><g><path fill="#f9f4da" d="M481.55 146.94L481.88 138.11 513.18 153.61 506.31 159.28 481.55 146.94z"></path><rect x="478.66" y="142.5" width="38.12" height="5.96" rx="2.98" ry="2.98" transform="rotate(26.35 497.798 145.518)" fill="#f9f4da"></rect><path d="M480.02 181.4l28.05-23.61h0s.03-.03.04-.05c0 0 0-.01.01-.02 0 0 .01-.02.02-.03 0-.01 0-.01.01-.02l.02-.03v-.02s.02-.02.02-.03v-.02-.03-.02-.03-.03-.03-.03-.06-.03-.01a.569.569 0 00-.2-.32l-1.35-1.07c-1.31-1.04-2.83-1.8-4.45-2.21-1.7-.43-3.28-1.21-4.65-2.3a11.82 11.82 0 00-4.46-2.21c-1.7-.43-3.28-1.21-4.65-2.3a11.82 11.82 0 00-4.46-2.21l-1.65-.42a.616.616 0 00-.38.03s0 0 0 0c-.01 0-.02.01-.03.02-.01 0-.01 0-.02.01 0 0-.02.01-.03.02 0 0-.02 0-.02.02s-.02.01-.02.02l-.02.02-.02.02-.02.02c-.01.01-.01.02-.02.03 0 0-.01.01-.01.02s0 .02-.02.03v.02l-.03.03v.02s-.02.02-.02.04v.02c0 .02 0 .04-.01.06h0l-1.63 36.69z" fill="#f9f4da"></path><circle cx="493.37" cy="155.93" r="3.73" fill="#231f20"></circle><path d="M500.54 162.61a3.723 3.723 0 00-4.99 1.69c-.63 1.26-.45 2.7.3 3.78l5.66-4.76c-.28-.28-.59-.52-.96-.71zM489.82 168.4c-1.84-.91-4.08-.16-4.99 1.69a3.72 3.72 0 002.39 5.25l4.66-3.92a3.72 3.72 0 00-2.05-3.02zM486.83 163.38c.91-1.84.16-4.08-1.69-4.99-1.4-.69-3.02-.42-4.12.55l-.24 5.33c.3.31.64.59 1.05.79 1.84.91 4.08.16 4.99-1.69zM481.52 147.6l-.33 7.36c1.58.26 3.21-.5 3.95-2 .91-1.84.16-4.08-1.69-4.99-.62-.31-1.29-.41-1.94-.36z" fill="#231f20"></path></g></g><g id="taco1" class="ReactViewDupeQuery_taco__ctMTU undefined"><path d="M516.48 175.51l-48.84-5.22a6.27 6.27 0 01-4.4-2.54 6.163 6.163 0 01-1.05-4.88c2.67-12.72 13.69-21.51 26.52-21.41.55-.42 1.22-.86 2.04-1.17 2.03-.77 3.9-.4 5.26-.13.26.05.61.12.85.15 2.49-1.28 5.52-.79 7.86 1.3.73.65 1.05.83 1.17.88.17 0 .44-.01.57-.02 1.04-.06 2.59-.14 4.22.7 1.59.81 2.43 2.1 2.98 2.95.13.19.27.41.34.49.13.15.56.44.9.68.42.29.88.6 1.35.99 2.07 1.72 3.1 4.07 2.82 6.34 2.84 4.39 4.32 9.46 4.29 14.77a6.16 6.16 0 01-2.06 4.55 6.269 6.269 0 01-4.83 1.55zm-4.61-22.45h0zm-18.56-5.71h0z" fill="#231f20" stroke="#231f20" stroke-linejoin="round" stroke-width="0.61"></path><path d="M514.79 173.86l-48.84-5.22a6.27 6.27 0 01-4.4-2.54 6.163 6.163 0 01-1.05-4.88c2.67-12.72 13.69-21.51 26.52-21.41.55-.42 1.22-.86 2.04-1.17 2.03-.77 3.9-.4 5.26-.13.26.05.61.12.85.15 2.49-1.28 5.52-.79 7.86 1.3.73.65 1.05.83 1.17.88.17 0 .44-.01.57-.02 1.04-.06 2.59-.14 4.22.7 1.59.81 2.43 2.1 2.98 2.95.13.19.27.41.34.49.13.15.56.44.9.68.42.29.88.6 1.35.99 2.07 1.72 3.1 4.07 2.82 6.34 2.84 4.39 4.32 9.46 4.29 14.77a6.16 6.16 0 01-2.06 4.55 6.269 6.269 0 01-4.83 1.55zm-4.61-22.45h0zm-18.56-5.71h0z" fill="#f9f4da" stroke="#231f20" stroke-linejoin="round" stroke-width="0.61"></path><path d="M507.42 168.99l-41.04-4.39c-1.25-.13-2.16-1.31-1.9-2.55 2.39-11.37 13.06-19.31 24.86-18.05s20.55 11.27 20.48 22.89c0 1.26-1.14 2.22-2.4 2.09z" fill="#f9f4da" stroke="#231f20" stroke-linejoin="round" stroke-width="0.61"></path><path d="M511.97 149.77c-.9-.75-1.99-1.28-2.75-2.17-.7-.83-1.12-1.96-2.09-2.46-1.04-.53-2.3-.12-3.46-.26-1.29-.16-2.38-1.02-3.35-1.88-.74-.66-2.13-1.43-3.46-.63-1.84 1.12-4.35-.69-6.37.07-1.31.5-2.12 1.92-3.46 2.33-.88.27-1.88.05-2.7.47-.62.31-1.03.93-1.23 1.59s-.23 1.36-.25 2.05l28.41 5.74c.88-.33 1.76-.91 2.02-1.81.33-1.12-.42-2.29-1.32-3.03zM466.7 164.63l9.21.98h.02c.2-.31 2.65-10.18 2.76-11.16.15-1.36-.84-2.58-2.2-2.72-1.36-.15-2.58.84-2.72 2.2-.03.24 0 .48.04.71-.66.24-1.19.75-1.46 1.41-.23-.1-.47-.18-.73-.21-1.36-.15-2.58.84-2.72 2.2-.06.52.06 1.02.29 1.44-.83.33-1.47 1.08-1.57 2.03-.05.44.03.86.2 1.24-.6.39-1.03 1.03-1.11 1.8v.08z" fill="#231f20" stroke="#231f20" stroke-linejoin="round" stroke-width="0.61"></path><rect x="480.32" y="146.09" width="3.91" height="3.91" rx="0.42" ry="0.42" transform="rotate(-14.07 482.293 148.038)" fill="#f9f4da" stroke="#231f20" stroke-linejoin="round" stroke-width="0.61"></rect><rect x="475.06" y="149.29" width="3.91" height="3.91" rx="0.49" ry="0.49" transform="rotate(-28.17 477.062 151.238)" fill="#f9f4da" stroke="#231f20" stroke-linejoin="round" stroke-width="0.61"></rect><circle cx="479.64" cy="150.16" r="2.19" fill="#f9f4da" stroke="#231f20" stroke-linejoin="round" stroke-width="0.61"></circle><path d="M515.22 169.82l-41.04-4.39c-1.25-.13-2.16-1.31-1.9-2.55 2.39-11.37 13.06-19.31 24.86-18.05s20.55 11.27 20.48 22.89c0 1.26-1.14 2.22-2.4 2.09z" fill="#f9f4da" stroke="#231f20" stroke-linejoin="round" stroke-width="0.61"></path><g fill="#231f20"><path d="M512.4 161.11c.68 0 .68-1.05 0-1.05s-.68 1.05 0 1.05zM503.31 165c.68 0 .68-1.05 0-1.05s-.68 1.05 0 1.05zM504.28 155.85c.68 0 .68-1.05 0-1.05s-.68 1.05 0 1.05zM496.48 150.35c.68 0 .68-1.05 0-1.05s-.68 1.05 0 1.05zM487.59 154.17c.68 0 .68-1.05 0-1.05s-.68 1.05 0 1.05zM494.93 160.39c.68 0 .68-1.05 0-1.05s-.68 1.05 0 1.05zM478.42 157.86c.68 0 .68-1.05 0-1.05s-.68 1.05 0 1.05zM484.38 164.5c.68 0 .68-1.05 0-1.05s-.68 1.05 0 1.05z"></path></g></g></svg> In fact, when you think about composition in React, odds are you think in terms of this UI composition since it's what React is so good at. The problem is in the real world, there's more to building an app than just the UI layer. It's not uncommon to need to compose and reuse *non-visual* logic as well. This is the fundamental problem that React hooks were created to solve. Just like a component enabled the composition and reusability of UI, hooks enabled the composition and reusability of non-visual logic. - useState create a value that is preserved across renders and triggers a re-render when it changes - useEffect synchronize a component with some external system - useRef create a value that is preserved across renders, but won't trigger a re-render when it changes - useContext get access to what was passed to a Context's Provider - useReducer create a value that is preserved across renders and triggers a re-render when it changes, using the reducer pattern - useMemo cache the result of a calculation between renders - useCallback cache a function between renders - useLayoutEffect synchronize a component with some external system, \*before\* the browser paints the screen - **useAnything** part of what makes hooks so composable is you can create your own hooks which leverage React hooks or other custom hooks The release of hooks ushered in a new era of React – the one I like to call the How the h\*ck do we fetch data? era. What's interesting about all of the built-in hooks that React comes with, as you've probably experienced first hand, is that none of them are dedicated to arguably the most common use-case for building a real world web app – data fetching. The closest we can get out of the box with React is `fetch` ing data inside of `useEffect`, and then preserving the response with `useState`. You've undoubtedly seen something like this before. We're fetching some data from the PokéAPI and showing it to the view – easy enough. The problem is this is "tutorial" code and unfortunately, you can't write "tutorial" code at work. The first problem, as you may have noticed if you played with the app, is we're not handling any loading states. This leads to one of the two deadliest UX sins – cumulative layout shift. There are a few ways to solve this – the simplest being to just show an empty card when the request is in-flight. To do that, let's add some more state, set it to `true` by default, then set it `false` once the request is complete. We'll then use that `loading` state to determine if we should show the Pokémon or not. Better, but unfortunately it's still "tutorial" code. As is, because we're not handling failed requests to the PokéAPI, there's a scenario where our app commits the second of the deadliest UX sins – the infinite loading screen. Let's take another crack at it by adding in some `error` state. Much better. Now our app is handling the three most common states of a network request – loading, success, and error. Because we've told `useEffect` to synchronize our local `pokemon` state with the PokéAPI according to `id`, we've taken what has historically been the most complex part of building a web app, an asynchronous side effect, and made it an implementation detail behind simply updating `id`. Unfortunately, we're still not *quite* done yet. In fact, as is, our code contains the *worst* kind of bug – one that is both inconspicuous and deceptively wasteful. Can you spot it? If not, Whenever we call `fetch`, because it's an asynchronous request, we have no idea how long that specific request will take to resolve. It's completely possible that, while we're in the process of waiting for a response, the user clicks one of our buttons, which causes a re-render, which causes our effect to run again with a different `id`. In this scenario, we now have two requests in flight, both with different `id` s. Worse, we have no way of knowing which one will resolve first. In both scenarios, we're calling `setPokemon` when the request resolves. That means, because we don't know in which order they'll resolve, `pokemon`, and therefore our UI, will eventually be *whatever request was resolved last*. AKA, we have a race condition. <svg id="asyncOutOfSync" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 514 233"><title>Interactive diagram showing multiple data requests returning asynchronously resulting in a mismatch between ID and view</title> <g><g><rect x="173.23" y="82.09" width="163.96" height="114.95" rx="26.68" ry="26.68" fill="currentColor" stroke="#231f20" stroke-miterlimit="10"></rect><g><path d="M186.83 74.62h121.65c11.4 0 20.66 9.26 20.66 20.66v72.64c0 11.4-9.26 20.66-20.66 20.66H186.83c-11.4 0-20.66-9.26-20.66-20.66V95.28c0-11.4 9.26-20.66 20.66-20.66z" fill="#0f0d0e"></path><path d="M308.48 75.12c11.11 0 20.16 9.04 20.16 20.16v72.64c0 11.11-9.04 20.16-20.16 20.16H186.83c-11.11 0-20.16-9.04-20.16-20.16V95.28c0-11.11 9.04-20.16 20.16-20.16h121.65m0-1H186.83c-11.68 0-21.16 9.47-21.16 21.16v72.64c0 11.68 9.47 21.16 21.16 21.16h121.65c11.68 0 21.16-9.47 21.16-21.16V95.28c0-11.68-9.47-21.16-21.16-21.16z" fill="#f9f4da"></path></g></g><g><text transform="translate(222.24 136.56)" fill="#f9f4da" font-family="FiraCode-Regular, 'Fira Code'" font-size="19.29"><tspan x="0" y="0">id:</tspan></text><g id="id1" class="AsyncOutOfSync_id__o6_BX AsyncOutOfSync_id1__4lp5O"><text transform="translate(263.33 136.56)" fill="#f9f4da" font-family="FiraCode-Regular, 'Fira Code'" font-size="19.29"><tspan x="0" y="0">1</tspan></text></g> <g id="id2" class="AsyncOutOfSync_id__o6_BX AsyncOutOfSync_id2__8Wg7p"><text transform="translate(263.33 136.56)" fill="#f9f4da" font-family="FiraCode-Regular, 'Fira Code'" font-size="19.29"><tspan x="0" y="0">2</tspan></text></g> <g id="id3" class="AsyncOutOfSync_id__o6_BX AsyncOutOfSync_id3__Myh9g"><text transform="translate(263.33 136.56)" fill="#f9f4da" font-family="FiraCode-Regular, 'Fira Code'" font-size="19.29"><tspan x="0" y="0">3</tspan></text></g> <text transform="translate(179.63 99.11)" fill="#f9f4da" font-family="FiraCode-Regular, 'Fira Code'" font-size="16"><tspan x="0" y="0">{</tspan></text> <text transform="translate(179.63 170.87)" fill="#f9f4da" font-family="FiraCode-Regular, 'Fira Code'" font-size="16"><tspan x="0" y="0">}</tspan></text></g></g> <g id="dataArrowBlue2" stroke="#231f20" class="AsyncOutOfSync_arrow__6YTGA AsyncOutOfSync_dataArrowBlue2__xuD_Y"><circle cx="46.34" cy="128.45" r="16.26" fill="#12b5e5" stroke-miterlimit="10"></circle><g stroke-linecap="round" stroke-linejoin="round"><path fill="#0f0d0e" d="M36.68 128.3L53.69 128.3"></path><path fill="none" d="M48.56 135.48L54.88 128.3 48.56 121.42"></path></g></g><g id="dataArrowPink2" class="AsyncOutOfSync_arrow__6YTGA AsyncOutOfSync_dataArrowPink2__LGMtH"><circle cx="46.34" cy="128.45" r="16.26" fill="#f38ba3"></circle><g stroke="#231f20" stroke-linecap="round" stroke-linejoin="round"><path fill="#0f0d0e" d="M36.68 128.3L53.69 128.3"></path><path fill="none" d="M48.56 135.48L54.88 128.3 48.56 121.42"></path></g></g><g id="dataArrowBlue1" stroke="#231f20" class="AsyncOutOfSync_arrow__6YTGA AsyncOutOfSync_dataArrowBlue1__Uxdnl"><circle cx="196.32" cy="128.45" r="16.26" fill="#12b5e5" stroke-miterlimit="10"></circle><g stroke-linecap="round" stroke-linejoin="round"><path fill="#0f0d0e" d="M205.98 128.6L188.97 128.6"></path><path fill="none" d="M194.11 121.42L187.78 128.6 194.11 135.48"></path></g></g><g id="dataArrowPink1" class="AsyncOutOfSync_arrow__6YTGA AsyncOutOfSync_dataArrowPink1__sP6n9"><circle cx="196.32" cy="128.45" r="16.26" fill="#f38ba3"></circle><g stroke="#231f20" stroke-linecap="round" stroke-linejoin="round"><path fill="#0f0d0e" d="M205.98 128.6L188.97 128.6"></path><path fill="none" d="M194.11 121.42L187.78 128.6 194.11 135.48"></path></g></g><g id="dataOutline1" class="AsyncOutOfSync_dataOutline__RKzsL AsyncOutOfSync_dataOutline1__23O1J"><path d="M46.34 77.69c.09 0 .18.02.26.07l39.17 23.53.09.09c.02.02.04.03.06.06.05.08.09.17.09.27v12.43c0 .17-.08.33-.23.42l-6.02 3.93 6 3.61.09.09c.02.02.04.03.06.06.05.08.09.17.09.27v12.43c0 .17-.08.33-.23.42l-6.01 3.93 5.99 3.6.09.09c.02.02.04.03.06.06.05.08.09.17.09.27v12.43c0 .17-.08.33-.23.42l-39.17 25.61c-.08.05-.18.08-.27.08s-.19-.03-.27-.08L6.9 156.19a.504.504 0 01-.23-.42v-12.43c0-.1.04-.19.09-.27l.06-.06c.03-.03.05-.07.09-.09l5.99-3.6-6.01-3.93a.504.504 0 01-.23-.42v-12.43c0-.1.04-.19.09-.27l.06-.06c.03-.03.05-.07.09-.09l6-3.61-6.02-3.93a.504.504 0 01-.23-.42v-12.43c0-.1.04-.19.09-.27l.06-.06c.03-.03.05-.07.09-.09l39.17-23.53c.08-.05.17-.07.26-.07m0-4c-.82 0-1.63.22-2.33.65L4.85 97.87c-.35.21-.66.46-.93.76-.18.18-.33.37-.47.58-.49.72-.76 1.57-.78 2.44v12.51c0 1.52.76 2.93 2.03 3.76l.68.45-.53.32c-.35.21-.65.46-.93.76-.18.18-.33.37-.47.58-.49.71-.76 1.56-.77 2.43v12.51c0 1.52.76 2.93 2.03 3.76l.67.44-.52.31c-.35.21-.66.46-.93.76-.18.18-.33.37-.47.58-.49.71-.76 1.56-.78 2.43v12.51c0 1.52.76 2.93 2.03 3.76l39.18 25.61c.75.48 1.59.73 2.46.73s1.72-.25 2.45-.72l39.19-25.62a4.485 4.485 0 002.04-3.77v-12.43-.08c-.02-.87-.29-1.72-.79-2.45-.13-.19-.29-.38-.46-.56-.28-.3-.58-.55-.93-.76l-.52-.32.67-.44a4.485 4.485 0 002.04-3.77v-12.43-.08c-.02-.87-.29-1.72-.79-2.45-.13-.19-.28-.38-.46-.56-.28-.3-.58-.55-.93-.76l-.53-.32.68-.44a4.485 4.485 0 002.04-3.77V101.7v-.08c-.02-.87-.29-1.72-.79-2.45-.13-.2-.29-.39-.46-.57-.28-.3-.58-.55-.92-.76L48.7 74.31c-.69-.42-1.5-.64-2.32-.64z" fill="#12b5e5"></path></g><g id="dataOutline2" class="AsyncOutOfSync_dataOutline__RKzsL AsyncOutOfSync_dataOutline2__xPrrD"><path d="M46.34 77.69c.09 0 .18.02.26.07l39.17 23.53.09.09c.02.02.04.03.06.06.05.08.09.17.09.27v12.43c0 .17-.08.33-.23.42l-6.02 3.93 6 3.61.09.09c.02.02.04.03.06.06.05.08.09.17.09.27v12.43c0 .17-.08.33-.23.42l-6.01 3.93 5.99 3.6.09.09c.02.02.04.03.06.06.05.08.09.17.09.27v12.43c0 .17-.08.33-.23.42l-39.17 25.61c-.08.05-.18.08-.27.08s-.19-.03-.27-.08L6.9 156.19a.504.504 0 01-.23-.42v-12.43c0-.1.04-.19.09-.27l.06-.06c.03-.03.05-.07.09-.09l5.99-3.6-6.01-3.93a.504.504 0 01-.23-.42v-12.43c0-.1.04-.19.09-.27l.06-.06c.03-.03.05-.07.09-.09l6-3.61-6.02-3.93a.504.504 0 01-.23-.42v-12.43c0-.1.04-.19.09-.27l.06-.06c.03-.03.05-.07.09-.09l39.17-23.53c.08-.05.17-.07.26-.07m0-4c-.82 0-1.63.22-2.33.65L4.85 97.87c-.35.21-.66.46-.93.76-.18.18-.33.37-.47.58-.49.72-.76 1.57-.78 2.44v12.51c0 1.52.76 2.93 2.03 3.76l.68.45-.53.32c-.35.21-.65.46-.93.76-.18.18-.33.37-.47.58-.49.71-.76 1.56-.77 2.43v12.51c0 1.52.76 2.93 2.03 3.76l.67.44-.52.31c-.35.21-.66.46-.93.76-.18.18-.33.37-.47.58-.49.71-.76 1.56-.78 2.43v12.51c0 1.52.76 2.93 2.03 3.76l39.18 25.61c.75.48 1.59.73 2.46.73s1.72-.25 2.45-.72l39.19-25.62a4.485 4.485 0 002.04-3.77v-12.43-.08c-.02-.87-.29-1.72-.79-2.45-.13-.19-.29-.38-.46-.56-.28-.3-.58-.55-.93-.76l-.52-.32.67-.44a4.485 4.485 0 002.04-3.77v-12.43-.08c-.02-.87-.29-1.72-.79-2.45-.13-.19-.28-.38-.46-.56-.28-.3-.58-.55-.93-.76l-.53-.32.68-.44a4.485 4.485 0 002.04-3.77V101.7v-.08c-.02-.87-.29-1.72-.79-2.45-.13-.2-.29-.39-.46-.57-.28-.3-.58-.55-.92-.76L48.7 74.31c-.69-.42-1.5-.64-2.32-.64z" fill="#f38ba3"></path></g><g id="database" fill="#0f0d0e" stroke="currentColor" stroke-linejoin="round" class="fill-gray-25 dark:fill-brand-coal"><g><path d="M46.34 132.24L7.17 143.34 7.17 155.77 46.34 181.37 85.52 155.77 85.52 143.34 46.34 132.24z"></path><path d="M46.34 119.81L7.17 143.34 46.34 168.95 85.52 143.34 46.34 119.81z"></path><path d="M46.34 168.95L46.34 181.37"></path></g><g><path d="M46.34 111.44L7.17 122.54 7.17 134.97 46.34 160.57 85.52 134.97 85.52 122.54 46.34 111.44z"></path><path d="M46.34 99.01L7.17 122.54 46.34 148.15 85.52 122.54 46.34 99.01z"></path><path d="M46.34 148.15L46.34 160.57"></path></g><g><path d="M46.34 90.62L7.17 101.73 7.17 114.15 46.34 139.76 85.52 114.15 85.52 101.73 46.34 90.62z"></path><path d="M46.34 78.2L7.17 101.73 46.34 127.33 85.52 101.73 46.34 78.2z"></path><path d="M46.34 127.33L46.34 139.76"></path></g></g><text transform="translate(23.95 17.67)" fill="currentColor" font-family="PaytoneOne-Regular, 'Paytone One'" font-size="16.35"><tspan x="0" y="0">DATA</tspan></text> <text transform="translate(407.32 17.77)" fill="currentColor" font-family="PaytoneOne-Regular, 'Paytone One'" font-size="16.35"><tspan x="0" y="0">VIEW</tspan></text> <g><g><path d="M384.18 46.22h101.57c14.45 0 26.18 11.73 26.18 26.18v128.23c0 14.45-11.73 26.18-26.18 26.18H384.18c-14.45 0-26.18-11.73-26.18-26.18V72.4c0-14.45 11.73-26.18 26.18-26.18z" fill="#0f0d0e"></path><path d="M485.74 46.72c14.16 0 25.68 11.52 25.68 25.68v128.23c0 14.16-11.52 25.68-25.68 25.68H384.17c-14.16 0-25.68-11.52-25.68-25.68V72.4c0-14.16 11.52-25.68 25.68-25.68h101.57m0-1H384.17c-14.73 0-26.68 11.94-26.68 26.68v128.23c0 14.73 11.94 26.68 26.68 26.68h101.57c14.73 0 26.68-11.94 26.68-26.68V72.4c0-14.73-11.94-26.68-26.68-26.68z" fill="#f9f4da"></path></g><rect x="349.94" y="37.76" width="154.93" height="181.58" rx="21.16" ry="21.16" fill="#f9f4da" stroke="#231f20" stroke-miterlimit="10"></rect><g id="view1" class="AsyncOutOfSync_view__LEoGk AsyncOutOfSync_view1__Gft2F"><g><rect x="371.2" y="66.69" width="115.05" height="65.35" rx="10.25" ry="10.25" fill="#0f0d0e" stroke="#0f0d0e" stroke-miterlimit="10"></rect><rect x="368.57" y="63.04" width="115.05" height="65.35" rx="10.25" ry="10.25" fill="#f9f4da" stroke="#0f0d0e" stroke-miterlimit="10"></rect><text transform="translate(423.25 101.17)" fill="#0f0d0e" font-family="Outfit-Medium, Outfit" font-size="16" font-weight="500"><tspan x="0" y="0">1</tspan></text></g> <g stroke="#0f0d0e" stroke-miterlimit="10"><rect x="371.2" y="145.12" width="115.05" height="39.63" rx="10.25" ry="10.25" fill="#0f0d0e"></rect><rect x="368.57" y="141.47" width="115.05" height="39.63" rx="10.25" ry="10.25" fill="#f9f4da"></rect></g></g><g id="view2" class="AsyncOutOfSync_view__LEoGk AsyncOutOfSync_view2__V3qtE"><g><rect x="371.2" y="66.69" width="115.05" height="65.35" rx="10.25" ry="10.25" fill="#0f0d0e" stroke="#0f0d0e" stroke-miterlimit="10"></rect><rect x="368.57" y="63.04" width="115.05" height="65.35" rx="10.25" ry="10.25" fill="#12b5e5" stroke="#0f0d0e" stroke-miterlimit="10"></rect><text transform="translate(421.76 101.17)" fill="#0f0d0e" font-family="Outfit-Medium, Outfit" font-size="16" font-weight="500"><tspan x="0" y="0">2</tspan></text></g> <g stroke="#0f0d0e" stroke-miterlimit="10"><rect x="371.2" y="145.12" width="115.05" height="39.63" rx="10.25" ry="10.25" fill="#0f0d0e"></rect><rect x="368.57" y="141.47" width="115.05" height="39.63" rx="10.25" ry="10.25" fill="#12b5e5"></rect></g></g><g id="view3" class="AsyncOutOfSync_view__LEoGk AsyncOutOfSync_view3__Dd9Ho"><g><rect x="371.2" y="66.69" width="115.05" height="65.35" rx="10.25" ry="10.25" fill="#0f0d0e" stroke="#0f0d0e" stroke-miterlimit="10"></rect><rect x="368.57" y="63.04" width="115.05" height="65.35" rx="10.25" ry="10.25" fill="#f38ba3" stroke="#0f0d0e" stroke-miterlimit="10"></rect><text transform="translate(421.77 101.17)" fill="#0f0d0e" font-family="Outfit-Medium, Outfit" font-size="16" font-weight="500"><tspan x="0" y="0">3</tspan></text></g><g stroke="#0f0d0e" stroke-miterlimit="10"><rect x="371.2" y="145.12" width="115.05" height="39.63" rx="10.25" ry="10.25" fill="#0f0d0e"></rect><rect x="368.57" y="141.47" width="115.05" height="39.63" rx="10.25" ry="10.25" fill="#f38ba3"></rect></g></g><rect x="408.93" y="199.37" width="36.96" height="8.73" rx="2.69" ry="2.69" fill="#fcba28" stroke="#0f0d0e" stroke-miterlimit="10" class="fill-brand-purple dark:fill-brand-yellow"></rect></g><g id="loaderView" class="AsyncOutOfSync_loader__1aejt"><path d="M430.26 119.14h0c0 3.08-2.5 5.58-5.58 5.58s-5.58-2.5-5.58-5.58 2.5-5.58 5.58-5.58v-4.31c-5.47 0-9.9 4.43-9.9 9.9s4.43 9.9 9.9 9.9 9.9-4.43 9.9-9.9h-4.31z" fill="#0f0d0e" stroke="#0f0d0e" stroke-linejoin="round"></path></g></svg> To make it worse, you'll also get a flash of the Pokémon that resolves first, before the second one does. You can see this in action by playing around with the app. Change the active Pokémon as fast as you can and watch what happens (it's even more obvious if you throttle your network). That's a pretty subpar experience. How would you go about fixing it? By going deeper down the `useEffect` rabbit hole. Really what we want to do is to tell React to ignore any responses that come from requests that were made in effects that are no longer relevant. In order to do that, of course, we need a way to know if an effect is the latest one. If not, then we should ignore the response and **not** `setPokemon` inside of it. Ideally, something like this. ```js try { const res = await fetch(\`https://pokeapi.co/api/v2/pokemon/${id}\`) if (ignore) { return } if (res.ok === false) { throw new Error(\`Error fetching pokemon #${id}\`) } const json = await res.json() setPokemon(json) setLoading(false) } catch (e) { setError(e.message) setLoading(false) } ``` To do this, we can utilize `useEffect` 's cleanup function. If you return a function from your effect, React will call that function each time before it ever calls your effect again, and then one final time when the component is removed from the DOM. We can see this in action by adding a cleanup function to our effect that logs the `id` that the effect is associated with. Now play around with the app and notice the logs. Specifically, think of how we can leverage this knowledge of our cleanup function in order to ignore stale responses. Notice that the cleanup function is only called for `id` s that are no longer relevant. This makes sense because the cleanup function for the most recent effect won't be called until either *another* effect runs (making it stale) or the component has been removed from the DOM (irrelevant in this scenario). We can use this knowledge, along with the **Power of JavaScript™** to fix our problem. Whenever the effect runs, let's make a variable called `ignore` and set it to `false`. Then, whenever the cleanup function runs (which we know will only happen when the effect is stale), we'll set `ignore` to `true`. Then, all we have to do before we call `setPokemon` or `setError`, is check to see if `ignore` is `true`. If it is, then we'll do nothing. Now, regardless of how many times `id` changes, we'll ignore every response that isn't in the most recent effect. This not only makes our app more , but it also improves the UX since React will now only re-render with the latest Pokémon. So at this point we've got to be finished, right 😅? If you were to make a PR with this code at work, more than likely someone would ask you to abstract all the logic for handling the `fetch` request into a custom hook. If you did that, you'd have two options. Either create a `usePokemon` hook, or create a more generic `useQuery` hook that could be used for any kind of network request. Assuming you went with the latter, it would probably look something like this. I still remember how proud I was when I first made this abstraction. Surely a custom hook like this would be a game changer for making network requests in a React app. That is, until I started using it. As is, our custom hook doesn't address *another* fundamental problem of using state and effects for data fetching: data duplication. By default, the fetched data is only ever local to the component that fetched it – that's how React works. That means, for every component that needs the same data, we have to refetch it. That seems minor, but it's not. Every component will have its own *instance* of the state and every component has to show a loading indicator to the user while it gets it. Even worse, it's possible that while `fetch` ing to the same endpoint, one request could fail while the other succeeds. Or, one `fetch` could lead to data that is different than a subsequent request. Imagine fetching twice from the GitHub API, once receiving that an issue is `open` and soon after that it's `closed` because it was fixed. <svg id="asyncPredictability" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 360 244"><title>Interactive diagram showing two components requesting data at slightly different times resulting in different data returned</title> <g><rect x="190.26" y="43.72" width="163.96" height="87.32" rx="26.68" ry="26.68" fill="currentColor" stroke="#231f20" stroke-miterlimit="10"></rect><g><rect x="185.21" y="38.26" width="162.96" height="86.32" rx="20.66" ry="20.66" fill="#0f0d0e"></rect><path d="M327.51 38.76c11.11 0 20.16 9.04 20.16 20.16v45.01c0 11.11-9.04 20.16-20.16 20.16H205.86c-11.11 0-20.16-9.04-20.16-20.16V58.91c0-11.11 9.04-20.16 20.16-20.16h121.65m0-1H205.86c-11.68 0-21.16 9.47-21.16 21.16v45.01c0 11.68 9.47 21.16 21.16 21.16h121.65c11.68 0 21.16-9.47 21.16-21.16V58.91c0-11.68-9.47-21.16-21.16-21.16z" fill="#f9f4da"></path></g></g><g><rect x="190.26" y="151.09" width="163.96" height="87.32" rx="26.68" ry="26.68" fill="currentColor" stroke="#231f20" stroke-miterlimit="10"></rect><g><path d="M205.87 145.62h121.64c11.4 0 20.66 9.26 20.66 20.66v45c0 11.4-9.26 20.66-20.66 20.66H205.86c-11.4 0-20.66-9.26-20.66-20.66v-45.01c0-11.4 9.26-20.66 20.66-20.66z" fill="#0f0d0e"></path><path d="M327.51 146.12c11.11 0 20.16 9.04 20.16 20.16v45.01c0 11.11-9.04 20.16-20.16 20.16H205.86c-11.11 0-20.16-9.04-20.16-20.16v-45.01c0-11.11 9.04-20.16 20.16-20.16h121.65m0-1H205.86c-11.68 0-21.16 9.47-21.16 21.16v45.01c0 11.68 9.47 21.16 21.16 21.16h121.65c11.68 0 21.16-9.47 21.16-21.16v-45.01c0-11.68-9.47-21.16-21.16-21.16z" fill="#f9f4da"></path></g></g><g id="loader2" class="AsyncPredictability_loader__Jjvrh undefined"><path d="M273.83 189.77h0c0 3.94-3.2 7.14-7.14 7.14s-7.14-3.2-7.14-7.14 3.2-7.14 7.14-7.14v-5.51c-6.99 0-12.65 5.66-12.65 12.65s5.67 12.65 12.65 12.65 12.65-5.66 12.65-12.65h-5.51z" fill="#231f20" stroke="#f9f4da" stroke-linejoin="round"></path></g><g id="loader1" class="AsyncPredictability_loader__Jjvrh undefined"><path d="M273.83 82.24h0c0 3.94-3.2 7.14-7.14 7.14s-7.14-3.2-7.14-7.14 3.2-7.14 7.14-7.14v-5.51c-6.99 0-12.65 5.66-12.65 12.65s5.67 12.65 12.65 12.65 12.65-5.66 12.65-12.65h-5.51z" fill="#231f20" stroke="#f9f4da" stroke-linejoin="round"></path></g><g id="square2" class="AsyncPredictability_shape__gQqqS AsyncPredictability_square2__rG9mu"><path fill="#12b5e5" d="M252.18 172.63H281.2V201.65H252.18z"></path></g><g id="square1" class="AsyncPredictability_shape__gQqqS AsyncPredictability_square1__3Qfx8"><path fill="#12b5e5" d="M252.18 66.91H281.2V95.92999999999999H252.18z"></path></g><g id="triangle2" class="AsyncPredictability_shape__gQqqS AsyncPredictability_triangle2__dO6bP"><path fill="#12b5e5" d="M281.2 201.64L252.18 201.64 266.69 172.63 281.2 201.64z"></path></g><g id="triangle1" class="AsyncPredictability_shape__gQqqS AsyncPredictability_triangle1__AJw0Y"><path fill="#12b5e5" d="M281.2 95.92L252.18 95.92 266.69 66.91 281.2 95.92z"></path></g><g id="dataArrowTop2" stroke="#231f20" class="AsyncPredictability_arrow___aE7C AsyncPredictability_arrowTop__2BsD_ AsyncPredictability_arrowReceive__QEh3q"><circle cx="46.34" cy="103.77" r="16.26" fill="#12b5e5" stroke-miterlimit="10"></circle><g stroke-linecap="round" stroke-linejoin="round"><path fill="#0f0d0e" d="M36.68 103.62L53.69 103.62"></path><path fill="none" d="M48.56 110.8L54.88 103.62 48.56 96.74"></path></g></g><g id="dataArrowTop1" stroke="#231f20" class="AsyncPredictability_arrow___aE7C AsyncPredictability_arrowTop__2BsD_ AsyncPredictability_arrowRequest__vW9wF"><circle cx="219.01" cy="103.77" r="16.26" fill="#12b5e5" stroke-miterlimit="10"></circle><g stroke-linecap="round" stroke-linejoin="round"><path fill="#0f0d0e" d="M228.67 103.92L211.66 103.92"></path><path fill="none" d="M216.79 96.74L210.47 103.92 216.79 110.8"></path></g></g><g id="dataArrowBottom2" stroke="#231f20" class="AsyncPredictability_arrow___aE7C AsyncPredictability_arrowBottom__lDMT2 AsyncPredictability_arrowReceive__QEh3q"><circle cx="46.34" cy="167.04" r="16.26" fill="#12b5e5" stroke-miterlimit="10"></circle><g stroke-linecap="round" stroke-linejoin="round"><path fill="#0f0d0e" d="M36.68 166.89L53.69 166.89"></path><path fill="none" d="M48.56 174.07L54.88 166.89 48.56 160.01"></path></g></g><g id="dataArrowBottom1" stroke="#231f20" class="AsyncPredictability_arrow___aE7C AsyncPredictability_arrowBottom__lDMT2 AsyncPredictability_arrowRequest__vW9wF"><circle cx="219.01" cy="167.04" r="16.26" fill="#12b5e5" stroke-miterlimit="10"></circle><g stroke-linecap="round" stroke-linejoin="round"><path fill="#0f0d0e" d="M228.67 167.19L211.66 167.19"></path><path fill="none" d="M216.79 160.01L210.47 167.19 216.79 174.07"></path></g></g><g id="dataOutline" class="AsyncPredictability_dataOutline__GANv4"><path d="M46.34 83.45c.09 0 .18.02.26.07l39.17 23.53.09.09c.02.02.04.03.06.06.05.08.09.17.09.27v12.43c0 .17-.08.33-.23.42l-6.02 3.93 6 3.61.09.09c.02.02.04.03.06.06.05.08.09.17.09.27v12.43c0 .17-.08.33-.23.42l-6.01 3.93 5.99 3.6.09.09c.02.02.04.03.06.06.05.08.09.17.09.27v12.43c0 .17-.08.33-.23.42l-39.17 25.61c-.08.05-.18.08-.27.08s-.19-.03-.27-.08L6.9 161.95a.504.504 0 01-.23-.42V149.1c0-.1.04-.19.09-.27l.06-.06c.03-.03.05-.07.09-.09l5.99-3.6-6.01-3.93a.504.504 0 01-.23-.42V128.3c0-.1.04-.19.09-.27l.06-.06c.03-.03.05-.07.09-.09l6-3.61-6.02-3.93a.504.504 0 01-.23-.42v-12.43c0-.1.04-.19.09-.27l.06-.06c.03-.03.05-.07.09-.09l39.17-23.53c.08-.05.17-.07.26-.07m0-4c-.82 0-1.63.22-2.33.65L4.85 103.63c-.35.21-.66.46-.93.76-.18.18-.33.37-.47.58a4.5 4.5 0 00-.78 2.44v12.51c0 1.52.76 2.93 2.03 3.76l.68.45-.53.32c-.35.21-.65.46-.93.76-.18.18-.33.37-.47.58-.49.71-.76 1.56-.77 2.43v12.51c0 1.52.76 2.93 2.03 3.76l.67.44-.52.31c-.35.21-.66.46-.93.76-.18.18-.33.37-.47.58-.49.71-.76 1.56-.78 2.43v12.51c0 1.52.76 2.93 2.03 3.76l39.18 25.61c.75.48 1.59.73 2.46.73s1.72-.25 2.45-.72l39.19-25.62a4.485 4.485 0 002.04-3.77v-12.43-.08c-.02-.87-.29-1.72-.79-2.45-.13-.19-.29-.38-.46-.56-.28-.3-.58-.55-.93-.76l-.52-.32.67-.44a4.485 4.485 0 002.04-3.77v-12.43-.08c-.02-.87-.29-1.72-.79-2.45-.13-.19-.28-.38-.46-.56-.28-.3-.58-.55-.93-.76l-.53-.32.68-.44a4.485 4.485 0 002.04-3.77v-12.43-.08c-.02-.87-.29-1.72-.79-2.45-.13-.2-.29-.38-.46-.56-.28-.3-.58-.55-.92-.76L48.7 80.08c-.69-.42-1.5-.64-2.32-.64z" fill="#12b5e5"></path></g><g id="database" fill="#0f0d0e" stroke="currentColor" stroke-linejoin="round" class="fill-gray-25 dark:fill-brand-coal"><g><path d="M46.34 138L7.17 149.1 7.17 161.53 46.34 187.13 85.52 161.53 85.52 149.1 46.34 138z"></path><path d="M46.34 125.57L7.17 149.1 46.34 174.71 85.52 149.1 46.34 125.57z"></path><path d="M46.34 174.71L46.34 187.13"></path></g><g><path d="M46.34 117.2L7.17 128.3 7.17 140.73 46.34 166.33 85.52 140.73 85.52 128.3 46.34 117.2z"></path><path d="M46.34 104.77L7.17 128.3 46.34 153.91 85.52 128.3 46.34 104.77z"></path><path d="M46.34 153.91L46.34 166.33"></path></g><g><path d="M46.34 96.38L7.17 107.49 7.17 119.91 46.34 145.52 85.52 119.91 85.52 107.49 46.34 96.38z"></path><path d="M46.34 83.96L7.17 107.49 46.34 133.09 85.52 107.49 46.34 83.96z"></path><path d="M46.34 133.09L46.34 145.52"></path></g></g><text transform="translate(23.95 17.67)" fill="currentColor" font-family="PaytoneOne-Regular, 'Paytone One'" font-size="16.35"><tspan x="0" y="0">DATA</tspan></text> <text transform="translate(211.69 17.67)" fill="currentColor" font-family="PaytoneOne-Regular, 'Paytone One'" font-size="16.35"><tspan x="0" y="0">COMPONENTS</tspan></text></svg> All the predictability that React offers just went out the window. It may seem unwarranted, but these are the kinds of problems that you will run into when you're fetching async data in a real-world application. To make it worse, these also just happen to be the kinds of problems that very few people think about. Now if you're an experienced React dev, you might be thinking that if the problem is that we're fetching the same data multiple times, can't we just move that state up to the nearest parent component and pass it down via props? <svg id="stateLiftOverview" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 383 350"><title>Interactive diagram showing state lifting to the parent component</title><g id="componentShadows"><path fill="currentColor" d="M240.94 18.82v60.79c0 7.24-1.66 13.9-13.9 13.9H156c-1.73 0-3.38-.33-4.91-.91h-2.07c2.55 3.12 6.43 5.13 10.78 5.13h71.04c7.68 0 13.9-6.22 13.9-13.9V28.34c0-3.69-1.46-7.02-3.8-9.52ZM240.94 139.06v60.79c0 7.24-1.66 13.9-13.9 13.9H156c-1.73 0-3.38-.33-4.91-.91h-2.07c2.55 3.12 6.43 5.13 10.78 5.13h71.04c7.68 0 13.9-6.22 13.9-13.9v-55.49c0-3.69-1.46-7.02-3.8-9.52ZM376.04 139.06v60.79c0 7.24-1.66 13.9-13.9 13.9H291.1c-1.73 0-3.38-.33-4.91-.91h-2.07c2.55 3.12 6.43 5.13 10.78 5.13h71.04c7.68 0 13.9-6.22 13.9-13.9v-55.49c0-3.69-1.46-7.02-3.8-9.52ZM105.93 139.06v60.79c0 7.24-1.66 13.9-13.9 13.9H21c-1.73 0-3.38-.33-4.91-.91h-2.07c2.55 3.12 6.43 5.13 10.78 5.13h71.03c7.68 0 13.9-6.22 13.9-13.9v-55.49c0-3.69-1.46-7.02-3.8-9.52ZM105.93 256.64v60.79c0 7.24-1.66 13.9-13.9 13.9H21c-1.73 0-3.38-.33-4.91-.91h-2.07c2.55 3.12 6.43 5.13 10.78 5.13h71.03c7.68 0 13.9-6.22 13.9-13.9v-55.49c0-3.69-1.46-7.02-3.8-9.52ZM240.98 256.64v60.79c0 7.24-1.66 13.9-13.9 13.9h-71.04c-1.73 0-3.38-.33-4.91-.91h-2.07c2.55 3.12 6.43 5.13 10.78 5.13h71.04c7.68 0 13.9-6.22 13.9-13.9v-55.49c0-3.69-1.46-7.02-3.8-9.52Z"></path><rect width="98.88" height="83.34" x="277.16" y="130.42" fill="#0f0d0e" rx="10.25" ry="10.25"></rect><rect width="98.88" height="83.34" x="142.11" y="130.42" fill="#0f0d0e" rx="10.25" ry="10.25"></rect><rect width="98.88" height="83.34" x="7.05" y="247.99" fill="#0f0d0e" rx="10.25" ry="10.25"></rect><rect width="98.88" height="83.34" x="142.11" y="247.99" fill="#0f0d0e" rx="10.25" ry="10.25"></rect><rect width="98.88" height="83.34" x="7.05" y="130.42" fill="#0f0d0e" rx="10.25" ry="10.25"></rect><rect width="98.88" height="83.34" x="142.07" y="10.18" fill="#0f0d0e" rx="10.25" ry="10.25"></rect></g><g id="treeLines" opacity=".7" fill="none" stroke="currentColor" stroke-miterlimit="10"><path d="M191.55 93.51L191.55 130.42"></path><path d="M56.49 130.61L56.49 112.73 328.5 112.73 328.5 130.48"></path><path d="M56.49 213.27L56.49 248.55"></path><path d="M56.49 231.7L191.55 231.7 191.55 248.55"></path></g><g id="pushLeft"><g id="pushSquareLeft" class="LiftStateDupeQuery_push__YtgbP LiftStateDupeQuery_pushSquareLeft__sJXz4"><path fill="#fc7428" d="M175.85 36.27H207.14V67.56H175.85z"></path></g></g><g id="pushRight"><g id="pushSquareRight" class="LiftStateDupeQuery_push__YtgbP LiftStateDupeQuery_pushSquareRight__e0r6E"><path fill="#fc7428" d="M175.85 36.27H207.14V67.56H175.85z"></path></g></g><g id="componentFills" opacity="0.7" fill="#0f0d0e"><rect x="277.16" y="130.42" width="98.88" height="83.34" rx="10.25" ry="10.25"></rect><rect x="7.05" y="247.99" width="98.88" height="83.34" rx="10.25" ry="10.25"></rect></g><g id="childLeft" class="LiftStateDupeQuery_childLeft___D1g0"><g id="propSquareLeft" class="LiftStateDupeQuery_prop__YHAvP LiftStateDupeQuery_propSquareLeft__7uKlF"><path fill="#fc7428" d="M40.76 274.06H72.05V305.35H40.76z"></path></g><g id="liftSquareLeft" class="LiftStateDupeQuery_lift__GfS9W LiftStateDupeQuery_liftSquareLeft__EZ87a"><path fill="#12b5e5" d="M40.76 274.06H72.05V305.35H40.76z"></path></g></g><rect id="componentFill1" x="7.05" y="130.42" width="98.88" height="83.34" rx="10.25" ry="10.25" fill="#0f0d0e" opacity="0.7"></rect><g id="childRight"><g id="propSquareRight" class="LiftStateDupeQuery_prop__YHAvP LiftStateDupeQuery_propSquareRight__tfWZj"><path fill="#fc7428" d="M312.85 156.44H344.14000000000004V187.73H312.85z"></path></g><g id="liftSquareRight" class="LiftStateDupeQuery_lift__GfS9W LiftStateDupeQuery_liftSquareRight__j_p7v"><path fill="#12b5e5" d="M312.85 156.44H344.14000000000004V187.73H312.85z"></path></g></g><rect id="componentFillParent" x="142.07" y="10.18" width="98.88" height="83.34" rx="10.25" ry="10.25" fill="#0f0d0e" opacity="0.7"></rect><g id="parent" class="LiftStateDupeQuery_parent__AktRL"><g id="stateSquareParent" class="LiftStateDupeQuery_state__DeHK5 LiftStateDupeQuery_stateSquareParent__2gm1k"><path fill="#12b5e5" d="M175.85 36.31H207.14V67.6H175.85z"></path></g></g><g id="componentOutlines" fill="#f9f4da"><path d="M365.79 131.42c5.1 0 9.25 4.15 9.25 9.25v62.84c0 5.1-4.15 9.25-9.25 9.25h-78.38c-5.1 0-9.25-4.15-9.25-9.25v-62.84c0-5.1 4.15-9.25 9.25-9.25h78.38m0-1h-78.38c-5.66 0-10.25 4.59-10.25 10.25v62.84c0 5.66 4.59 10.25 10.25 10.25h78.38c5.66 0 10.25-4.59 10.25-10.25v-62.84c0-5.66-4.59-10.25-10.25-10.25zM230.74 131.42c5.1 0 9.25 4.15 9.25 9.25v62.84c0 5.1-4.15 9.25-9.25 9.25h-78.38c-5.1 0-9.25-4.15-9.25-9.25v-62.84c0-5.1 4.15-9.25 9.25-9.25h78.38m0-1h-78.38c-5.66 0-10.25 4.59-10.25 10.25v62.84c0 5.66 4.59 10.25 10.25 10.25h78.38c5.66 0 10.25-4.59 10.25-10.25v-62.84c0-5.66-4.59-10.25-10.25-10.25zM95.69 248.99c5.1 0 9.25 4.15 9.25 9.25v62.84c0 5.1-4.15 9.25-9.25 9.25H17.3c-5.1 0-9.25-4.15-9.25-9.25v-62.84c0-5.1 4.15-9.25 9.25-9.25h78.39m0-1H17.3c-5.66 0-10.25 4.59-10.25 10.25v62.84c0 5.66 4.59 10.25 10.25 10.25h78.39c5.66 0 10.25-4.59 10.25-10.25v-62.84c0-5.66-4.59-10.25-10.25-10.25zM230.74 248.99c5.1 0 9.25 4.15 9.25 9.25v62.84c0 5.1-4.15 9.25-9.25 9.25h-78.38c-5.1 0-9.25-4.15-9.25-9.25v-62.84c0-5.1 4.15-9.25 9.25-9.25h78.38m0-1h-78.38c-5.66 0-10.25 4.59-10.25 10.25v62.84c0 5.66 4.59 10.25 10.25 10.25h78.38c5.66 0 10.25-4.59 10.25-10.25v-62.84c0-5.66-4.59-10.25-10.25-10.25zM95.69 131.42c5.1 0 9.25 4.15 9.25 9.25v62.84c0 5.1-4.15 9.25-9.25 9.25H17.3c-5.1 0-9.25-4.15-9.25-9.25v-62.84c0-5.1 4.15-9.25 9.25-9.25h78.39m0-1H17.3c-5.66 0-10.25 4.59-10.25 10.25v62.84c0 5.66 4.59 10.25 10.25 10.25h78.39c5.66 0 10.25-4.59 10.25-10.25v-62.84c0-5.66-4.59-10.25-10.25-10.25zM230.7 11.18c5.1 0 9.25 4.15 9.25 9.25v62.84c0 5.1-4.15 9.25-9.25 9.25h-78.38c-5.1 0-9.25-4.15-9.25-9.25V20.42c0-5.1 4.15-9.25 9.25-9.25h78.38m0-1h-78.38c-5.66 0-10.25 4.59-10.25 10.25v62.84c0 5.66 4.59 10.25 10.25 10.25h78.38c5.66 0 10.25-4.59 10.25-10.25V20.42c0-5.66-4.59-10.25-10.25-10.25z"></path></g></svg> Or better, put the fetched data on context so that it's available to any component that needs it? <svg id="contextTeleport" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 520 338"><title>Interactive diagram showing a parent component passing state to child components via props contrasted with context teleporting state directly to child components</title><g id="componentShadows"><g fill="#0f0d0e"><rect x="384.32" y="145.42" width="55.45" height="46.74" rx="5.8" ry="5.8"></rect><rect x="231.42" y="145.42" width="55.45" height="46.74" rx="5.8" ry="5.8"></rect><rect x="384.32" y="78.87" width="55.45" height="46.74" rx="5.8" ry="5.8"></rect><rect x="307.84" y="78.87" width="55.45" height="46.74" rx="5.8" ry="5.8"></rect><rect x="231.42" y="78.87" width="55.45" height="46.74" rx="5.8" ry="5.8"></rect><rect x="155.03" y="78.87" width="55.45" height="46.74" rx="5.8" ry="5.8"></rect><rect x="78.56" y="78.87" width="55.45" height="46.74" rx="5.8" ry="5.8"></rect><rect x="155.03" y="145.38" width="55.45" height="46.74" rx="5.8" ry="5.8"></rect><rect x="78.56" y="145.38" width="55.45" height="46.74" rx="5.8" ry="5.8"></rect><rect x="155.03" y="211.96" width="55.45" height="46.74" rx="5.8" ry="5.8"></rect><rect x="78.56" y="211.96" width="55.45" height="46.74" rx="5.8" ry="5.8"></rect><rect x="155.03" y="278.51" width="55.45" height="46.74" rx="5.8" ry="5.8"></rect><rect x="78.56" y="278.51" width="55.45" height="46.74" rx="5.8" ry="5.8"></rect><rect x="2.15" y="145.38" width="55.45" height="46.74" rx="5.8" ry="5.8"></rect><rect x="2.15" y="211.96" width="55.45" height="46.74" rx="5.8" ry="5.8"></rect><rect x="2.15" y="278.51" width="55.45" height="46.74" rx="5.8" ry="5.8"></rect><rect x="231.42" y="10.82" width="55.45" height="46.74" rx="5.8" ry="5.8"></rect><rect x="460.78" y="145.42" width="55.45" height="46.74" rx="5.8" ry="5.8"></rect><rect x="384.32" y="211.96" width="55.45" height="46.74" rx="5.8" ry="5.8"></rect><rect x="460.78" y="211.96" width="55.45" height="46.74" rx="5.8" ry="5.8"></rect><rect x="384.32" y="278.51" width="55.45" height="46.74" rx="5.8" ry="5.8"></rect><rect x="307.84" y="211.96" width="55.45" height="46.74" rx="5.8" ry="5.8"></rect><rect x="231.42" y="211.96" width="55.45" height="46.74" rx="5.8" ry="5.8"></rect><rect x="307.84" y="278.51" width="55.45" height="46.74" rx="5.8" ry="5.8"></rect><rect x="460.78" y="278.51" width="55.45" height="46.74" rx="5.8" ry="5.8"></rect></g><path d="M287.15 15.07v34.41c0 4.1-.94 7.87-7.87 7.87h-40.21a7.8 7.8 0 01-2.78-.52h-1.17a7.862 7.862 0 006.1 2.9h40.21c4.34 0 7.87-3.52 7.87-7.87v-31.4c0-2.09-.82-3.98-2.15-5.39zM287.15 83.12v34.41c0 4.1-.94 7.87-7.87 7.87h-40.21a7.8 7.8 0 01-2.78-.52h-1.17a7.862 7.862 0 006.1 2.9h40.21c4.34 0 7.87-3.52 7.87-7.87V88.5c0-2.09-.82-3.98-2.15-5.39zM363.61 83.12v34.41c0 4.1-.94 7.87-7.87 7.87h-40.21a7.8 7.8 0 01-2.78-.52h-1.17a7.862 7.862 0 006.1 2.9h40.21c4.34 0 7.87-3.52 7.87-7.87V88.5c0-2.09-.82-3.98-2.15-5.39zM439.99 83.12v34.41c0 4.1-.94 7.87-7.87 7.87h-40.21a7.8 7.8 0 01-2.78-.52h-1.17a7.862 7.862 0 006.1 2.9h40.21c4.34 0 7.87-3.52 7.87-7.87V88.5c0-2.09-.82-3.98-2.15-5.39zM516.49 149.67v34.41c0 4.1-.94 7.87-7.87 7.87h-40.21a7.8 7.8 0 01-2.78-.52h-1.17a7.862 7.862 0 006.1 2.9h40.21c4.34 0 7.87-3.52 7.87-7.87v-31.41c0-2.09-.82-3.98-2.15-5.39zM516.49 216.26v34.41c0 4.1-.94 7.87-7.87 7.87h-40.21a7.8 7.8 0 01-2.78-.52h-1.17a7.862 7.862 0 006.1 2.9h40.21c4.34 0 7.87-3.52 7.87-7.87v-31.41c0-2.09-.82-3.98-2.15-5.39zM516.49 282.75v34.41c0 4.1-.94 7.87-7.87 7.87h-40.21a7.8 7.8 0 01-2.78-.52h-1.17a7.862 7.862 0 006.1 2.9h40.21c4.34 0 7.87-3.52 7.87-7.87v-31.41c0-2.09-.82-3.98-2.15-5.39zM439.99 149.67v34.41c0 4.1-.94 7.87-7.87 7.87h-40.21a7.8 7.8 0 01-2.78-.52h-1.17a7.862 7.862 0 006.1 2.9h40.21c4.34 0 7.87-3.52 7.87-7.87v-31.41c0-2.09-.82-3.98-2.15-5.39zM210.74 83.12v34.41c0 4.1-.94 7.87-7.87 7.87h-40.21a7.8 7.8 0 01-2.78-.52h-1.17a7.862 7.862 0 006.1 2.9h40.21c4.34 0 7.87-3.52 7.87-7.87V88.5c0-2.09-.82-3.98-2.15-5.39zM134.27 83.12v34.41c0 4.1-.94 7.87-7.87 7.87H86.19a7.8 7.8 0 01-2.78-.52h-1.17a7.862 7.862 0 006.1 2.9h40.21c4.34 0 7.87-3.52 7.87-7.87V88.5c0-2.09-.82-3.98-2.15-5.39zM134.27 149.67v34.41c0 4.1-.94 7.87-7.87 7.87H86.19a7.8 7.8 0 01-2.78-.52h-1.17a7.862 7.862 0 006.1 2.9h40.21c4.34 0 7.87-3.52 7.87-7.87v-31.41c0-2.09-.82-3.98-2.15-5.39zM57.83 149.67v34.41c0 4.1-.94 7.87-7.87 7.87H9.76a7.8 7.8 0 01-2.78-.52H5.81a7.862 7.862 0 006.1 2.9h40.2c4.34 0 7.87-3.52 7.87-7.87v-31.41c0-2.09-.82-3.98-2.15-5.39zM57.83 216.26v34.41c0 4.1-.94 7.87-7.87 7.87H9.76a7.8 7.8 0 01-2.78-.52H5.81a7.862 7.862 0 006.1 2.9h40.2c4.34 0 7.87-3.52 7.87-7.87v-31.41c0-2.09-.82-3.98-2.15-5.39zM57.83 282.75v34.41c0 4.1-.94 7.87-7.87 7.87H9.76a7.8 7.8 0 01-2.78-.52H5.81a7.862 7.862 0 006.1 2.9h40.2c4.34 0 7.87-3.52 7.87-7.87v-31.41c0-2.09-.82-3.98-2.15-5.39zM210.74 149.67v34.41c0 4.1-.94 7.87-7.87 7.87h-40.21a7.8 7.8 0 01-2.78-.52h-1.17a7.862 7.862 0 006.1 2.9h40.21c4.34 0 7.87-3.52 7.87-7.87v-31.41c0-2.09-.82-3.98-2.15-5.39zM287.17 149.67v34.41c0 4.1-.94 7.87-7.87 7.87h-40.21a7.8 7.8 0 01-2.78-.52h-1.17a7.862 7.862 0 006.1 2.9h40.21c4.34 0 7.87-3.52 7.87-7.87v-31.41c0-2.09-.82-3.98-2.15-5.39zM363.61 216.26v34.41c0 4.1-.94 7.87-7.87 7.87h-40.21a7.8 7.8 0 01-2.78-.52h-1.17a7.862 7.862 0 006.1 2.9h40.21c4.34 0 7.87-3.52 7.87-7.87v-31.41c0-2.09-.82-3.98-2.15-5.39zM439.99 216.26v34.41c0 4.1-.94 7.87-7.87 7.87h-40.21a7.8 7.8 0 01-2.78-.52h-1.17a7.862 7.862 0 006.1 2.9h40.21c4.34 0 7.87-3.52 7.87-7.87v-31.41c0-2.09-.82-3.98-2.15-5.39zM134.27 216.26v34.41c0 4.1-.94 7.87-7.87 7.87H86.19a7.8 7.8 0 01-2.78-.52h-1.17a7.862 7.862 0 006.1 2.9h40.21c4.34 0 7.87-3.52 7.87-7.87v-31.41c0-2.09-.82-3.98-2.15-5.39zM210.74 216.26v34.41c0 4.1-.94 7.87-7.87 7.87h-40.21a7.8 7.8 0 01-2.78-.52h-1.17a7.862 7.862 0 006.1 2.9h40.21c4.34 0 7.87-3.52 7.87-7.87v-31.41c0-2.09-.82-3.98-2.15-5.39zM287.17 216.26v34.41c0 4.1-.94 7.87-7.87 7.87h-40.21a7.8 7.8 0 01-2.78-.52h-1.17a7.862 7.862 0 006.1 2.9h40.21c4.34 0 7.87-3.52 7.87-7.87v-31.41c0-2.09-.82-3.98-2.15-5.39zM363.61 282.75v34.41c0 4.1-.94 7.87-7.87 7.87h-40.21a7.8 7.8 0 01-2.78-.52h-1.17a7.862 7.862 0 006.1 2.9h40.21c4.34 0 7.87-3.52 7.87-7.87v-31.41c0-2.09-.82-3.98-2.15-5.39zM439.99 282.75v34.41c0 4.1-.94 7.87-7.87 7.87h-40.21a7.8 7.8 0 01-2.78-.52h-1.17a7.862 7.862 0 006.1 2.9h40.21c4.34 0 7.87-3.52 7.87-7.87v-31.41c0-2.09-.82-3.98-2.15-5.39zM134.27 282.75v34.41c0 4.1-.94 7.87-7.87 7.87H86.19a7.8 7.8 0 01-2.78-.52h-1.17a7.862 7.862 0 006.1 2.9h40.21c4.34 0 7.87-3.52 7.87-7.87v-31.41c0-2.09-.82-3.98-2.15-5.39zM210.74 282.75v34.41c0 4.1-.94 7.87-7.87 7.87h-40.21a7.8 7.8 0 01-2.78-.52h-1.17a7.862 7.862 0 006.1 2.9h40.21c4.34 0 7.87-3.52 7.87-7.87v-31.41c0-2.09-.82-3.98-2.15-5.39z" fill="currentColor"></path></g><g id="treeLines" opacity="0.7" fill="none" stroke="currentColor" stroke-miterlimit="10"><path d="M259.2 57.34L259.2 78.88"></path><path d="M106.32 78.34L106.32 68.22 412.07 68.22 412.07 79.09"></path><path d="M182.76 125.13L182.76 145.38"></path><path d="M106.32 125.13L106.32 145.63"></path><path d="M182.76 201.9L106.32 201.9 106.32 212.18"></path><path d="M336.71 68.22L336.71 78.84"></path><path d="M182.76 68.22L182.76 78.84"></path><path d="M260.13 191.5L260.13 211.98"></path><path d="M412.07 124.87L412.07 145.44"></path><path d="M182.76 191.72L182.76 212.08"></path><path d="M29.88 191.72L29.88 212.08"></path><path d="M260.13 202.28L412.07 202.28 412.07 211.82"></path><path d="M336.57 258.21L336.57 278.73"></path><path d="M336.57 268.99L413.01 268.99 413.01 278.53"></path><path d="M412.07 135.9L488.51 135.9 488.51 145.44"></path><path d="M106.32 257.96L106.32 278.73"></path><path d="M106.32 268.74L182.76 268.74 182.76 278.28"></path><path d="M106.32 268.74L29.88 268.74 29.88 278.28"></path><path d="M336.57 211.82L336.57 202.28"></path><path d="M488.51 191.26L488.51 212.26"></path><path d="M488.51 257.86L488.51 279.02"></path><path d="M182.76 135.56L259.2 135.56 259.2 145.1"></path><path d="M106.32 135.56L29.88 135.56 29.88 145.1"></path></g><g id="pushContainer"><g id="push"><g id="push6" class="ContextTeleportDupeQuery_push__PTwDD undefined"><path fill="#fc7428" d="M250.34 24.97H268.05V42.68H250.34z"></path></g><g id="push5" class="ContextTeleportDupeQuery_push__PTwDD ContextTeleportDupeQuery_push5__IN3XT"><path fill="#fc7428" d="M250.34 24.97H268.05V42.68H250.34z"></path></g><g id="push4" class="ContextTeleportDupeQuery_push__PTwDD ContextTeleportDupeQuery_push4__L_09D"><path fill="#fc7428" d="M250.34 24.97H268.05V42.68H250.34z"></path></g><g id="push3" class="ContextTeleportDupeQuery_push__PTwDD ContextTeleportDupeQuery_push3__L5JDW"><path fill="#fc7428" d="M250.34 24.97H268.05V42.68H250.34z"></path></g><g id="push2" class="ContextTeleportDupeQuery_push__PTwDD ContextTeleportDupeQuery_push2__aRDnR"><path fill="#fc7428" d="M250.34 24.97H268.05V42.68H250.34z"></path></g><g id="push1" class="ContextTeleportDupeQuery_push__PTwDD ContextTeleportDupeQuery_push1__QNG6V"><path fill="#fc7428" d="M250.34 24.97H268.05V42.68H250.34z"></path></g></g><g id="componentFills" opacity="0.7" fill="#0f0d0e"><rect x="231.68" y="11.04" width="54.94" height="46.3" rx="5.3" ry="5.3"></rect><rect x="78.82" y="79.09" width="54.94" height="46.3" rx="5.3" ry="5.3"></rect><rect x="155.29" y="79.09" width="54.94" height="46.3" rx="5.3" ry="5.3"></rect><rect x="308.1" y="79.09" width="54.94" height="46.3" rx="5.3" ry="5.3"></rect><rect x="384.57" y="79.09" width="54.94" height="46.3" rx="5.3" ry="5.3"></rect><rect x="78.82" y="145.63" width="54.94" height="46.3" rx="5.3" ry="5.3"></rect><rect x="155.29" y="145.63" width="54.94" height="46.3" rx="5.3" ry="5.3"></rect><rect x="231.7" y="145.63" width="54.94" height="46.3" rx="5.3" ry="5.3"></rect><rect x="78.82" y="212.18" width="54.94" height="46.3" rx="5.3" ry="5.3"></rect><rect x="78.82" y="278.73" width="54.94" height="46.3" rx="5.3" ry="5.3"></rect><rect x="308.14" y="278.73" width="54.94" height="46.3" rx="5.3" ry="5.3"></rect><rect x="308.14" y="212.18" width="54.94" height="46.3" rx="5.3" ry="5.3"></rect><rect x="461.04" y="145.63" width="54.94" height="46.3" rx="5.3" ry="5.3"></rect><rect x="461.01" y="212.18" width="54.94" height="46.3" rx="5.3" ry="5.3"></rect></g><g id="props"><g id="prop6" class="ContextTeleportDupeQuery_prop__zRo_a undefined"><path fill="#fc7428" d="M326.78 292.6H344.48999999999995V310.31H326.78z"></path></g><g id="prop5" class="ContextTeleportDupeQuery_prop__zRo_a undefined"><path fill="#fc7428" d="M97.46 292.6H115.16999999999999V310.31H97.46z"></path></g><g id="prop4" class="ContextTeleportDupeQuery_prop__zRo_a undefined"><path fill="#fc7428" d="M479.66 226.05H497.37V243.76000000000002H479.66z"></path></g><g id="prop2" class="ContextTeleportDupeQuery_prop__zRo_a undefined"><path fill="#fc7428" d="M97.46 159.53H115.16999999999999V177.24H97.46z"></path></g><g id="prop1" class="ContextTeleportDupeQuery_prop__zRo_a undefined"><path fill="#fc7428" d="M327.25 92.96H344.96V110.66999999999999H327.25z"></path></g></g></g><g id="context"><g id="context6" class="ContextTeleportDupeQuery_context__yD0py"><path fill="#12b5e5" d="M403.22 292.6H420.93V310.31H403.22z"></path></g><g id="context5" class="ContextTeleportDupeQuery_context__yD0py"><path fill="#12b5e5" d="M173.85 292.6H191.56V310.31H173.85z"></path></g><g id="context4" class="ContextTeleportDupeQuery_context__yD0py"><path fill="#12b5e5" d="M251.28 226.05H268.99V243.76000000000002H251.28z"></path></g><g id="context3" class="ContextTeleportDupeQuery_context__yD0py"><path fill="#12b5e5" d="M21.02 226.05H38.730000000000004V243.76000000000002H21.02z"></path></g><g id="context2" class="ContextTeleportDupeQuery_context__yD0py"><path fill="#12b5e5" d="M403.22 159.51H420.93V177.22H403.22z"></path></g><g id="context1" class="ContextTeleportDupeQuery_context__yD0py"><path fill="#12b5e5" d="M173.85 159.51H191.56V177.22H173.85z"></path></g></g><g id="state"><path fill="#12b5e5" d="M250.31 24.97H268.02V42.68H250.31z"></path></g><g id="componentOutlines2" fill="#f9f4da"><path d="M357.82 79.23c2.65 0 4.8 2.15 4.8 4.8v35.57c0 2.65-2.15 4.8-4.8 4.8h-44.36c-2.65 0-4.8-2.15-4.8-4.8V84.03c0-2.65 2.15-4.8 4.8-4.8h44.36m0-1h-44.36c-3.2 0-5.8 2.6-5.8 5.8v35.57c0 3.2 2.6 5.8 5.8 5.8h44.36c3.2 0 5.8-2.6 5.8-5.8V84.03c0-3.2-2.6-5.8-5.8-5.8zM281.38 79.23c2.65 0 4.8 2.15 4.8 4.8v35.57c0 2.65-2.15 4.8-4.8 4.8h-44.36c-2.65 0-4.8-2.15-4.8-4.8V84.03c0-2.65 2.15-4.8 4.8-4.8h44.36m0-1h-44.36c-3.2 0-5.8 2.6-5.8 5.8v35.57c0 3.2 2.6 5.8 5.8 5.8h44.36c3.2 0 5.8-2.6 5.8-5.8V84.03c0-3.2-2.6-5.8-5.8-5.8zM204.94 145.78c2.65 0 4.8 2.15 4.8 4.8v35.57c0 2.65-2.15 4.8-4.8 4.8h-44.36c-2.65 0-4.8-2.15-4.8-4.8v-35.57c0-2.65 2.15-4.8 4.8-4.8h44.36m0-1h-44.36c-3.2 0-5.8 2.6-5.8 5.8v35.57c0 3.2 2.6 5.8 5.8 5.8h44.36c3.2 0 5.8-2.6 5.8-5.8v-35.57c0-3.2-2.6-5.8-5.8-5.8zM281.38 145.78c2.65 0 4.8 2.15 4.8 4.8v35.57c0 2.65-2.15 4.8-4.8 4.8h-44.36c-2.65 0-4.8-2.15-4.8-4.8v-35.57c0-2.65 2.15-4.8 4.8-4.8h44.36m0-1h-44.36c-3.2 0-5.8 2.6-5.8 5.8v35.57c0 3.2 2.6 5.8 5.8 5.8h44.36c3.2 0 5.8-2.6 5.8-5.8v-35.57c0-3.2-2.6-5.8-5.8-5.8zM434.25 145.78c2.65 0 4.8 2.15 4.8 4.8v35.57c0 2.65-2.15 4.8-4.8 4.8h-44.36c-2.65 0-4.8-2.15-4.8-4.8v-35.57c0-2.65 2.15-4.8 4.8-4.8h44.36m0-1h-44.36c-3.2 0-5.8 2.6-5.8 5.8v35.57c0 3.2 2.6 5.8 5.8 5.8h44.36c3.2 0 5.8-2.6 5.8-5.8v-35.57c0-3.2-2.6-5.8-5.8-5.8zM204.94 79.23c2.65 0 4.8 2.15 4.8 4.8v35.57c0 2.65-2.15 4.8-4.8 4.8h-44.36c-2.65 0-4.8-2.15-4.8-4.8V84.03c0-2.65 2.15-4.8 4.8-4.8h44.36m0-1h-44.36c-3.2 0-5.8 2.6-5.8 5.8v35.57c0 3.2 2.6 5.8 5.8 5.8h44.36c3.2 0 5.8-2.6 5.8-5.8V84.03c0-3.2-2.6-5.8-5.8-5.8zM128.5 79.23c2.65 0 4.8 2.15 4.8 4.8v35.57c0 2.65-2.15 4.8-4.8 4.8H84.14c-2.65 0-4.8-2.15-4.8-4.8V84.03c0-2.65 2.15-4.8 4.8-4.8h44.36m0-1H84.14c-3.2 0-5.8 2.6-5.8 5.8v35.57c0 3.2 2.6 5.8 5.8 5.8h44.36c3.2 0 5.8-2.6 5.8-5.8V84.03c0-3.2-2.6-5.8-5.8-5.8zM52.06 145.78c2.65 0 4.8 2.15 4.8 4.8v35.57c0 2.65-2.15 4.8-4.8 4.8H7.7c-2.65 0-4.8-2.15-4.8-4.8v-35.57c0-2.65 2.15-4.8 4.8-4.8h44.36m0-1H7.7c-3.2 0-5.8 2.6-5.8 5.8v35.57c0 3.2 2.6 5.8 5.8 5.8h44.36c3.2 0 5.8-2.6 5.8-5.8v-35.57c0-3.2-2.6-5.8-5.8-5.8zM128.5 145.78c2.65 0 4.8 2.15 4.8 4.8v35.57c0 2.65-2.15 4.8-4.8 4.8H84.14c-2.65 0-4.8-2.15-4.8-4.8v-35.57c0-2.65 2.15-4.8 4.8-4.8h44.36m0-1H84.14c-3.2 0-5.8 2.6-5.8 5.8v35.57c0 3.2 2.6 5.8 5.8 5.8h44.36c3.2 0 5.8-2.6 5.8-5.8v-35.57c0-3.2-2.6-5.8-5.8-5.8zM52.06 212.32c2.65 0 4.8 2.15 4.8 4.8v35.57c0 2.65-2.15 4.8-4.8 4.8H7.7c-2.65 0-4.8-2.15-4.8-4.8v-35.57c0-2.65 2.15-4.8 4.8-4.8h44.36m0-1H7.7c-3.2 0-5.8 2.6-5.8 5.8v35.57c0 3.2 2.6 5.8 5.8 5.8h44.36c3.2 0 5.8-2.6 5.8-5.8v-35.57c0-3.2-2.6-5.8-5.8-5.8zM52.06 278.87c2.65 0 4.8 2.15 4.8 4.8v35.57c0 2.65-2.15 4.8-4.8 4.8H7.7c-2.65 0-4.8-2.15-4.8-4.8v-35.57c0-2.65 2.15-4.8 4.8-4.8h44.36m0-1H7.7c-3.2 0-5.8 2.6-5.8 5.8v35.57c0 3.2 2.6 5.8 5.8 5.8h44.36c3.2 0 5.8-2.6 5.8-5.8v-35.57c0-3.2-2.6-5.8-5.8-5.8zM434.25 79.23c2.65 0 4.8 2.15 4.8 4.8v35.57c0 2.65-2.15 4.8-4.8 4.8h-44.36c-2.65 0-4.8-2.15-4.8-4.8V84.03c0-2.65 2.15-4.8 4.8-4.8h44.36m0-1h-44.36c-3.2 0-5.8 2.6-5.8 5.8v35.57c0 3.2 2.6 5.8 5.8 5.8h44.36c3.2 0 5.8-2.6 5.8-5.8V84.03c0-3.2-2.6-5.8-5.8-5.8zM510.69 145.78c2.65 0 4.8 2.15 4.8 4.8v35.57c0 2.65-2.15 4.8-4.8 4.8h-44.36c-2.65 0-4.8-2.15-4.8-4.8v-35.57c0-2.65 2.15-4.8 4.8-4.8h44.36m0-1h-44.36c-3.2 0-5.8 2.6-5.8 5.8v35.57c0 3.2 2.6 5.8 5.8 5.8h44.36c3.2 0 5.8-2.6 5.8-5.8v-35.57c0-3.2-2.6-5.8-5.8-5.8zM510.69 212.32c2.65 0 4.8 2.15 4.8 4.8v35.57c0 2.65-2.15 4.8-4.8 4.8h-44.36c-2.65 0-4.8-2.15-4.8-4.8v-35.57c0-2.65 2.15-4.8 4.8-4.8h44.36m0-1h-44.36c-3.2 0-5.8 2.6-5.8 5.8v35.57c0 3.2 2.6 5.8 5.8 5.8h44.36c3.2 0 5.8-2.6 5.8-5.8v-35.57c0-3.2-2.6-5.8-5.8-5.8zM510.69 279.53c2.65 0 4.8 2.15 4.8 4.8v35.57c0 2.65-2.15 4.8-4.8 4.8h-44.36c-2.65 0-4.8-2.15-4.8-4.8v-35.57c0-2.65 2.15-4.8 4.8-4.8h44.36m0-1h-44.36c-3.2 0-5.8 2.6-5.8 5.8v35.57c0 3.2 2.6 5.8 5.8 5.8h44.36c3.2 0 5.8-2.6 5.8-5.8v-35.57c0-3.2-2.6-5.8-5.8-5.8zM204.94 212.32c2.65 0 4.8 2.15 4.8 4.8v35.57c0 2.65-2.15 4.8-4.8 4.8h-44.36c-2.65 0-4.8-2.15-4.8-4.8v-35.57c0-2.65 2.15-4.8 4.8-4.8h44.36m0-1h-44.36c-3.2 0-5.8 2.6-5.8 5.8v35.57c0 3.2 2.6 5.8 5.8 5.8h44.36c3.2 0 5.8-2.6 5.8-5.8v-35.57c0-3.2-2.6-5.8-5.8-5.8zM281.38 212.32c2.65 0 4.8 2.15 4.8 4.8v35.57c0 2.65-2.15 4.8-4.8 4.8h-44.36c-2.65 0-4.8-2.15-4.8-4.8v-35.57c0-2.65 2.15-4.8 4.8-4.8h44.36m0-1h-44.36c-3.2 0-5.8 2.6-5.8 5.8v35.57c0 3.2 2.6 5.8 5.8 5.8h44.36c3.2 0 5.8-2.6 5.8-5.8v-35.57c0-3.2-2.6-5.8-5.8-5.8zM128.5 212.32c2.65 0 4.8 2.15 4.8 4.8v35.57c0 2.65-2.15 4.8-4.8 4.8H84.14c-2.65 0-4.8-2.15-4.8-4.8v-35.57c0-2.65 2.15-4.8 4.8-4.8h44.36m0-1H84.14c-3.2 0-5.8 2.6-5.8 5.8v35.57c0 3.2 2.6 5.8 5.8 5.8h44.36c3.2 0 5.8-2.6 5.8-5.8v-35.57c0-3.2-2.6-5.8-5.8-5.8zM357.82 212.32c2.65 0 4.8 2.15 4.8 4.8v35.57c0 2.65-2.15 4.8-4.8 4.8h-44.36c-2.65 0-4.8-2.15-4.8-4.8v-35.57c0-2.65 2.15-4.8 4.8-4.8h44.36m0-1h-44.36c-3.2 0-5.8 2.6-5.8 5.8v35.57c0 3.2 2.6 5.8 5.8 5.8h44.36c3.2 0 5.8-2.6 5.8-5.8v-35.57c0-3.2-2.6-5.8-5.8-5.8zM434.25 212.32c2.65 0 4.8 2.15 4.8 4.8v35.57c0 2.65-2.15 4.8-4.8 4.8h-44.36c-2.65 0-4.8-2.15-4.8-4.8v-35.57c0-2.65 2.15-4.8 4.8-4.8h44.36m0-1h-44.36c-3.2 0-5.8 2.6-5.8 5.8v35.57c0 3.2 2.6 5.8 5.8 5.8h44.36c3.2 0 5.8-2.6 5.8-5.8v-35.57c0-3.2-2.6-5.8-5.8-5.8zM204.94 278.87c2.65 0 4.8 2.15 4.8 4.8v35.57c0 2.65-2.15 4.8-4.8 4.8h-44.36c-2.65 0-4.8-2.15-4.8-4.8v-35.57c0-2.65 2.15-4.8 4.8-4.8h44.36m0-1h-44.36c-3.2 0-5.8 2.6-5.8 5.8v35.57c0 3.2 2.6 5.8 5.8 5.8h44.36c3.2 0 5.8-2.6 5.8-5.8v-35.57c0-3.2-2.6-5.8-5.8-5.8zM128.5 278.87c2.65 0 4.8 2.15 4.8 4.8v35.57c0 2.65-2.15 4.8-4.8 4.8H84.14c-2.65 0-4.8-2.15-4.8-4.8v-35.57c0-2.65 2.15-4.8 4.8-4.8h44.36m0-1H84.14c-3.2 0-5.8 2.6-5.8 5.8v35.57c0 3.2 2.6 5.8 5.8 5.8h44.36c3.2 0 5.8-2.6 5.8-5.8v-35.57c0-3.2-2.6-5.8-5.8-5.8zM357.82 278.87c2.65 0 4.8 2.15 4.8 4.8v35.57c0 2.65-2.15 4.8-4.8 4.8h-44.36c-2.65 0-4.8-2.15-4.8-4.8v-35.57c0-2.65 2.15-4.8 4.8-4.8h44.36m0-1h-44.36c-3.2 0-5.8 2.6-5.8 5.8v35.57c0 3.2 2.6 5.8 5.8 5.8h44.36c3.2 0 5.8-2.6 5.8-5.8v-35.57c0-3.2-2.6-5.8-5.8-5.8zM434.25 278.87c2.65 0 4.8 2.15 4.8 4.8v35.57c0 2.65-2.15 4.8-4.8 4.8h-44.36c-2.65 0-4.8-2.15-4.8-4.8v-35.57c0-2.65 2.15-4.8 4.8-4.8h44.36m0-1h-44.36c-3.2 0-5.8 2.6-5.8 5.8v35.57c0 3.2 2.6 5.8 5.8 5.8h44.36c3.2 0 5.8-2.6 5.8-5.8v-35.57c0-3.2-2.6-5.8-5.8-5.8zM281.36 11.18c2.65 0 4.8 2.15 4.8 4.8v35.56c0 2.65-2.15 4.8-4.8 4.8H237c-2.65 0-4.8-2.15-4.8-4.8V15.98c0-2.65 2.15-4.8 4.8-4.8h44.36m0-1H237c-3.2 0-5.8 2.6-5.8 5.8v35.56c0 3.2 2.6 5.8 5.8 5.8h44.36c3.2 0 5.8-2.6 5.8-5.8V15.98c0-3.2-2.6-5.8-5.8-5.8z"></path></g></svg> or Sure, and if we did that, we'd probably end up with something like this. Well, it works – but this is the exact type of code that future you will hate current you for. The biggest change (besides all the Context mess) is since our state is now "global", it needs to be able to store `data` | `loading` | `error` states for multiple `url` s. To achieve that, we had to make our state an object where the `url` itself is the key. Now, every time we call `useQuery` with a `url`, we'll read from the existing state if it exists, or `fetch` if it doesn't. ```js useQuery('/api/rankings') // fetches useQuery('/api/rankings') // from cache ``` With that, we've just introduced a small, in-memory and predictability has been restored. Unfortunately, we've traded in our *predictability* problem for an *optimization* problem. As you might know, React Context isn't a tool that's particularly good at distributing dynamic data throughout an application since it lacks a fundamental trait of state managers: being able to subscribe to *pieces* of your state. As is, any component that calls `useQuery` will be subscribed to the whole `QueryContext`, and therefore, will re-render whenever *anything* changes – even if the change isn't related to the `url` it cares about. Also, if two components call `useQuery` with the same `url` at the same time, unless we can figure out how to dedupe multiple requests, our app will still make two requests since `useEffect` is still called once per component. Oh and since we've introduced a cache, we also need to introduce a way to invalidate it – and as you may know, . What started out as a simple, innocent pattern for fetching data in a React application has become a coffin of complexity – and unfortunately, there's not just one thing to blame. 1. `useEffect` is [confusing](https://stackoverflow.com/questions/tagged/react-hooks?tab=Votes). 2. Context often becomes confusing over time. 3. Combining `useState`, `useEffect`, and Context together in an attempt to "manage" state will lead to pain and suffering. 4. We're treating *asynchronous* state as if it were *synchronous* state. At this point #1-3 should be obvious, so let's dive into #4. Synchronous state is state that we're typically used to when working in the browser. It's *our* state, which is why it's often called *client state*. We can rely on it to be instantly available when we need it, and no one else can manipulate it, so it's always up-to-date. ## Client State 1. 1.Client owned: It's always up-to-date. 2. 2.Our state: Only we can change it 3. 3.Usually ephemeral: It goes away when the browser is closed. 4. 4.Synchronous: It's instantly available. All these traits make client state easy to work with since it's predictable. There isn't much that can go wrong if we're the only ones who can make updates to it. Asynchronous state, on the other hand, is state that is *not* ours. We have to get it from somewhere else, usually a server, which is why it's often called *server state*. It persists, usually in a database, which means it's not . This makes managing it, particularly over time, tricky. ## Server State 1. 1.Server owned: What we see is only a snapshot (which can be outdated). 2. 2.Owned by many users: Multiple users could change the data. 3. 3.Persisted remotely: It exists across browsing sessions. 4. 4.Asynchronous: It takes a bit of time for the data to go from the server to the client. Though it's far too common, it's problematic to treat these two kinds of states as equal. To manage client state in a React app, we have lots of options available, starting from the built-in hooks like `useState` and `useReducer`, all the way up to community maintained solutions like `redux` or `zustand`. But what are our options for managing server state in a React app? Historically, there weren't many. That is, until React Query came along. Ironically, you may have heard that React Query is "the missing piece for data fetching in React". That couldn't be further from the truth. In fact... React Query is not a data fetching library And that's a good thing! Because it should be clear by now that data fetching itself is not the hard part - it's *managing* that data over time that is. And while React Query goes very well *with* data fetching, a better way to describe it is as an async state manager that is also acutely aware of the needs of server state. In fact, React Query doesn't even fetch any data for you. YOU provide it a promise (whether from `fetch`, `axios`, `graphql`, `IndexedDB`, etc.), and React Query will then take the data that the promise resolves with and make it available wherever you need it throughout your entire application. From there, it can handle all of the dirty work that you're either unaware of, or you shouldn't be thinking about. 1. 1.Cache management 2. 2.Cache invalidation 3. 3.Auto refetching 4. 4.Scroll recovery 5. 5.Offline support 6. 6.Window focus refetching 7. 7.Dependent queries 8. 8.Paginated queries 9. 9.Request cancellation 10. 10.Prefetching 11. 11.Polling 12. 12.Mutations 13. 13.Infinite scrolling 14. 14.Data selectors 15. 15.\+ More And the best part about it? You can stop trying to figure out how `useEffect` works – which is why it solves the **5 o'clock rule**. ![Query.gg: The Official React Query Course. Master React Query with Mystifying Ease.](https://ui.dev/images/QueryGGPitch.svg) After close to a year of work, we’re very tired – but also very excited to announce that [query.gg](https://query.gg/) is now available! It’s our take on a modern, interactive React Query course built in close collaboration with the React Query team. [Join now](https://query.gg/)