<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Juan Pablo Djeredjian</title>
    <description>The latest articles on DEV Community by Juan Pablo Djeredjian (@juandj).</description>
    <link>https://dev.to/juandj</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F299631%2F77ba682e-3eeb-42df-813e-03214bb9795a.jpeg</url>
      <title>DEV Community: Juan Pablo Djeredjian</title>
      <link>https://dev.to/juandj</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/juandj"/>
    <language>en</language>
    <item>
      <title>How I use Claude Code to accelerate my software engineering job and improve my life</title>
      <dc:creator>Juan Pablo Djeredjian</dc:creator>
      <pubDate>Mon, 26 Jan 2026 03:28:54 +0000</pubDate>
      <link>https://dev.to/juandj/how-i-use-claude-code-to-accelerate-my-software-engineering-job-and-improve-my-life-8o7</link>
      <guid>https://dev.to/juandj/how-i-use-claude-code-to-accelerate-my-software-engineering-job-and-improve-my-life-8o7</guid>
      <description>&lt;p&gt;Claude Code has taken the software engineering world by storm and it's changing how the field looks in leaps and bounds. Prominent engineers are proudly saying that they're writing 0 lines of code already. &lt;a href="https://x.com/rakyll/status/2007239758158975130" rel="noopener noreferrer"&gt;Jaana Dogan&lt;/a&gt;, a Principal Engineer at Google working on Gemini, recently shared that she gave Claude Code a description of a distributed agent orchestrator problem, and it generated in about an hour what her team had been trying to build for the past year. She was careful to clarify: this was a proof-of-concept, not production-ready code. It still required validation, security reviews, performance testing. But still. An hour versus a year. Even with all the caveats, that's a staggering shift.&lt;/p&gt;

&lt;p&gt;My feeling after working with Claude Code this year is actually: the upside is so huge that I'm surprised I'm not seeing it reflected in the amount of apps, features, and sheer progress in the software world. And I don't think we're in an early adoption phase anymore, as many argue. I think writing code has been commoditized already, and that just means the bottleneck has simply moved elsewhere: to generating new ideas, to testing and releasing, and above all, to distribution. The AI-generated apps might already be there, flooding the market; we're just not aware of them. They simply don't reach us.&lt;/p&gt;

&lt;p&gt;And yet, while this is all exciting, it's also incredibly anxiety inducing. If you're a software engineer, you're probably feeling it too. Every week there's a new announcement, a new capability, a new "this changes everything" moment. And you're left wondering: am I keeping up? Am I falling behind? Will I still have a job in two years?&lt;/p&gt;

&lt;p&gt;I don't have answers to those questions, I think nobody does yet for sure. But what I can tell you is how I've been using these tools to become significantly more productive, and how that productivity has actually made my job more enjoyable, not less. The more I use AI, the more I realize that the engineers who learn to collaborate effectively with these tools will have a massive advantage. That's what this post is about.&lt;/p&gt;

&lt;h2&gt;
  
  
  Section 1: Software Engineering
&lt;/h2&gt;

&lt;p&gt;I'm not here to rehash Claude Code's features. Plenty of guides cover CLAUDE.md files, /commands, and skills. If you want a great starting point, &lt;a href="https://x.com/bcherny/status/2007179832300581177" rel="noopener noreferrer"&gt;Boris Cherny's thread&lt;/a&gt; (he created Claude Code) is excellent. His most striking revelation: "In the last thirty days, 100% of my contributions to Claude Code were written by Claude Code." And that includes 100% of the code written for the Claude Cowork project!&lt;/p&gt;

&lt;p&gt;So, let me share what I've actually learned from almost a year of daily use. These aren't smart ways to use Claude's features, they're habits, workflows, and mental models that emerged from daily use. Things that simply weren't practical before Claude Code made them possible, but now are the very core of how I work as a software engineer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Understand EVERYTHING
&lt;/h3&gt;

&lt;p&gt;Joining a company used to mean months of gradual ramp-up. You'd slowly build mental models of different features, ask the same questions repeatedly, and forget half of what you learned. Today, there's no excuse for that.&lt;/p&gt;

&lt;p&gt;With Claude Code, I send agents to investigate entire services, and point it to Jira tickets, GitHub PRs, Slack threads, whatever expands context. Then I have it produce an exhaustive, didactic guide in markdown and save it to a dedicated &lt;code&gt;AI_DOCS/&lt;/code&gt; folder in my repo.&lt;/p&gt;

&lt;p&gt;Ask it to make extensive use of ASCII diagrams. Claude Code with Opus 4.5 really excels at this and is a wonder at explaining complex, multi-repo data flows and architectures.&lt;/p&gt;

&lt;p&gt;Here's what I have Claude document for every major service:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Architecture overview&lt;/li&gt;
&lt;li&gt;API endpoints and their purposes&lt;/li&gt;
&lt;li&gt;Database collections and schemas&lt;/li&gt;
&lt;li&gt;External service dependencies&lt;/li&gt;
&lt;li&gt;Key files and their relationships&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One of my guides distills dozens of conversations, PRs, and debugging sessions into a single source of truth. That's months of accumulated understanding I never have to rebuild.&lt;/p&gt;

&lt;p&gt;The prompt pattern I use looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;Explore [SERVICE/FEATURE] and create comprehensive documentation:
&lt;span class="p"&gt;
1.&lt;/span&gt; Executive Summary - what is its core purpose?
&lt;span class="p"&gt;2.&lt;/span&gt; Architecture - how is it structured? Include ASCII diagrams.
&lt;span class="p"&gt;3.&lt;/span&gt; Data Flows - how does data move in and out? Visualize with diagrams.
&lt;span class="p"&gt;4.&lt;/span&gt; API Routes - what endpoints does it expose?
&lt;span class="p"&gt;5.&lt;/span&gt; Database - what does it store? Include schema overview.
&lt;span class="p"&gt;6.&lt;/span&gt; External Dependencies - what other services does it call? How?
&lt;span class="p"&gt;7.&lt;/span&gt; Key Files - where's the important logic?
&lt;span class="p"&gt;8.&lt;/span&gt; Common Gotchas - what breaks? What's confusing? What's undocumented?
&lt;span class="p"&gt;9.&lt;/span&gt; Common Operations - how do you test/deploy/debug it?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is your treasure. Every time you revisit that system, debug something adjacent, or tackle a related feature, you have instant context, both for yourself and to feed back to Claude. The knowledge compounds instead of evaporating.&lt;/p&gt;

&lt;h3&gt;
  
  
  Give Claude access to every possible tool
&lt;/h3&gt;

&lt;p&gt;Claude will be able to use all tools at your disposal faster, more efficiently and deeper than you. There are some tools which I think are essential, and you'd be shooting yourself in the foot by not having them.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 If both options exist, I prefer CLIs to MCPs (which fill up the context and can be slow). CLIs are extremely capable and fast and will give you the same features (or more) than its respective MCP.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here's my essential toolkit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub CLI&lt;/strong&gt;: For PRs, issues, checking CI status, everything. Claude can create PRs, review code, check workflow runs, all without leaving the terminal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS CLI&lt;/strong&gt;: For debugging Lambda logs, checking SQS queues, DynamoDB queries. Also Localstack for local dev, which uses the same CLI interface.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Logs (Datadog)&lt;/strong&gt;: We use Datadog, so I have Claude query logs directly. When debugging production issues, this is invaluable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database (mongosh)&lt;/strong&gt;: Give Claude access to staging, and if you can, read access to prod. If you can't, staging should suffice to answer questions like understanding schemas or checking data states.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Slack MCP&lt;/strong&gt;: This one's super important. So much historical knowledge and context is trapped in Slack (Searchable Log of All Conversation and Knowledge!). The point is, your LLM needs to access this data in a way that doesn't require you to copy paste.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Atlassian MCP&lt;/strong&gt;: For Jira tickets and Confluence pages. Here I do use an MCP because I found the API to be annoying to work with directly.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Make all knowledge LLM-consumable
&lt;/h3&gt;

&lt;p&gt;Every startup has that ONE person who knows how feature X works, what that esoteric Clojure project does, or how to wire up Salesforce in local dev. In the past, you'd schedule a meeting, frantically take notes, maybe record it. Then good luck rewatching that hour-long video every time you needed to follow the steps.&lt;/p&gt;

&lt;p&gt;Here's the trick: AI can extract that tribal knowledge and turn it into permanent, queryable documentation.&lt;/p&gt;

&lt;p&gt;A Meeting Copilot summary won't cut it here. When you need extensive detail (steps to follow, historical decisions, specific commands), a summary loses too much. You need the raw material: video + transcript.&lt;/p&gt;

&lt;p&gt;Here's what I do:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Record the knowledge transfer.&lt;/strong&gt; Send a Meeting Copilot, or just screen-record while the expert walks you through the process.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Get video + transcript.&lt;/strong&gt; You want both. The transcript captures what was said, but the screen shares show what was &lt;em&gt;done&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Extract frames from the video.&lt;/strong&gt; Claude can't process video directly (yet), but it can process images. I use ffmpeg to grab a frame every few seconds:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ffmpeg &lt;span class="nt"&gt;-i&lt;/span&gt; meeting_recording.mp4 &lt;span class="nt"&gt;-vf&lt;/span&gt; &lt;span class="s2"&gt;"fps=1/3"&lt;/span&gt; frames/frame_%04d.png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Point Claude at the frames + transcript.&lt;/strong&gt; Ask it to create a detailed guide, using the frames as inline screenshots matched to the relevant steps.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The results are remarkable. Claude produced a step-by-step guide with screenshots accurately selected based on what was being discussed at each moment, pulling information from both the transcript and the shared screen.&lt;/p&gt;

&lt;p&gt;Now you have a guide you'll never need to remake. But here's the real payoff: feed that guide back to Claude, and it can probably do the task for you.&lt;/p&gt;

&lt;p&gt;This is what I mean by making knowledge LLM-consumable. Extract tribal knowledge once, and it becomes available to AI forever. The expert's time is captured, not lost.&lt;/p&gt;

&lt;h3&gt;
  
  
  Learn in context
&lt;/h3&gt;

&lt;p&gt;Learning a new technology used to be tedious. Read the docs, try their toy examples, maybe spin up a starter boilerplate. But those never felt like real use cases. You'd understand the syntax without understanding how it fits into a real codebase with real constraints.&lt;/p&gt;

&lt;p&gt;Claude Code flips this. Instead of learning in isolation, I learn in context: my actual app, my actual complexity, my actual requirements.&lt;/p&gt;

&lt;p&gt;Here's what that looks like:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ask Claude: "What would [technology X] give me in this app? What are the tradeoffs?"&lt;/li&gt;
&lt;li&gt;Have it actually implement it&lt;/li&gt;
&lt;li&gt;Ask it to swap in a competing option&lt;/li&gt;
&lt;li&gt;Compare them side by side, in your codebase&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A real example: I was building an app that needed agentic workflows and wanted to evaluate frameworks: OpenAI Agents SDK, Claude Agents SDK, Google ADK, and AWS Strands. I had Claude build a POC with the OpenAI SDK first, explaining the architecture and tradeoffs as it went. Once I understood how that worked, I opened multiple Claude terminals and asked it to rebuild the same functionality with each of the other frameworks, documenting the differences.&lt;/p&gt;

&lt;p&gt;Within an afternoon, I had four working implementations and a clear sense of the tradeoffs. All in running code I could modify and extend.&lt;/p&gt;

&lt;p&gt;Then I pushed further. I'd heard vaguely that Temporal could help with "long-running workflows" and human-in-the-loop patterns, but I didn't know how that would fit or help my app.&lt;/p&gt;

&lt;p&gt;So I asked Claude: "What Temporal features could help me here?" It returned seven specific use cases, including the exact scenario I needed, each with proposal of parts of my codebase where it could help, with diffs and explanations for each.&lt;/p&gt;

&lt;p&gt;But I didn't stop there. After going through the recommendations and understanding the proposals, I asked: "So, why is Temporal necessary? Can't I achieve this without it?" And it showed me a side-by-side comparison of both architectures, with side by side code samples pulled directly from the app I'd already built.&lt;/p&gt;

&lt;p&gt;That's the difference. Real comparisons, in your code, for your use case. So you can learn and understand by making sense of new things in a context that actually matters and makes senses to you.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use multiple AI tools together
&lt;/h3&gt;

&lt;p&gt;Every model has blind spots. On any given run, one might miss an edge case, another might over-engineer, another might take a completely different architectural approach. When you run the same complex task through multiple models and compare their outputs, the differences themselves reveal tradeoffs you wouldn't have considered.&lt;/p&gt;

&lt;p&gt;For any non-trivial task, I'll prompt:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claude (via Claude Code)&lt;/li&gt;
&lt;li&gt;Codex (OpenAI)&lt;/li&gt;
&lt;li&gt;Gemini CLI (subsidized right now, basically free)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then I compare their approaches. Sometimes one spots edge cases the others missed. Sometimes they propose completely different architectures. By combining insights from multiple outputs, I often end up with a more robust implementation than any single model would have produced alone.&lt;/p&gt;

&lt;p&gt;I also do cross-model review. After one AI generates a plan or code, I have another review it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;Here is a plan that Claude generated for [TASK]:
[Paste the plan]

Please review this plan and identify:
&lt;span class="p"&gt;1.&lt;/span&gt; Potential edge cases not covered
&lt;span class="p"&gt;2.&lt;/span&gt; Security concerns
&lt;span class="p"&gt;3.&lt;/span&gt; Performance implications
&lt;span class="p"&gt;4.&lt;/span&gt; Missing error handling
&lt;span class="p"&gt;5.&lt;/span&gt; Simpler alternative approaches
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Think of it as an AI forum. You put models in healthy competition, letting them challenge and refine each other's thinking. The result is better than what any single model would produce, and you get there faster than going back and forth with just one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Section 2: How to use Claude Code to improve your life
&lt;/h2&gt;

&lt;p&gt;A few weeks ago I read &lt;a href="https://x.com/mollycantillon/status/2008918474006122936" rel="noopener noreferrer"&gt;Molly Cantillon's "The Personal Panopticon"&lt;/a&gt; and it broke something in my brain.&lt;/p&gt;

&lt;p&gt;Her core insight is this: we are drowning in data about ourselves and yet we remain catastrophically blind. Our commitments exist in six different apps and cohere in none. Our finances are scattered across brokerages that refuse to talk to each other. Our goals live in some forgotten note from January. We have more information about ourselves than any human in history, and we can barely see any of it.&lt;/p&gt;

&lt;p&gt;Her solution to this problem is simple: Build your own panopticon. Put yourself in the tower. Use Claude Code as the apparatus of sight, but point it inward.&lt;/p&gt;

&lt;p&gt;She runs multiple Claude Code instances in parallel, each watching a different part of her life. Finances, health, email, personal projects. Her finances get synthesized overnight from multiple brokerages, cross-referenced with market data, and she wakes up to a brief. Her product metrics get pulled automatically and turned into actionable insights. Her email reaches inbox zero with auto-drafted replies she just reviews.&lt;/p&gt;

&lt;p&gt;I'm not there yet. But I started building toward it.&lt;/p&gt;

&lt;p&gt;I have a main folder with a &lt;code&gt;CLAUDE.md&lt;/code&gt; file where I let Claude know basically everything about me, or tell it what external data sources to pull from to know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Who I am: name, age, where I'm from, where I live&lt;/li&gt;
&lt;li&gt;Family situation: married, one kid, another on the way&lt;/li&gt;
&lt;li&gt;What I do for a living, what company I work for&lt;/li&gt;
&lt;li&gt;What my skills and gaps are&lt;/li&gt;
&lt;li&gt;How much I make per year&lt;/li&gt;
&lt;li&gt;How much my wife makes per year&lt;/li&gt;
&lt;li&gt;What our expenditures are (rent, utilities, subscriptions, everything)&lt;/li&gt;
&lt;li&gt;What our assets are (savings, investments, property)&lt;/li&gt;
&lt;li&gt;What my schedule looks like on an average day&lt;/li&gt;
&lt;li&gt;General life objectives (retirement goals, travel plans, where we want to live long term)&lt;/li&gt;
&lt;li&gt;Near term projects (learning a new skill, home renovation, job considerations)&lt;/li&gt;
&lt;li&gt;Health information relevant to decisions&lt;/li&gt;
&lt;li&gt;Important relationships and commitments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Yes, basically everything there is to know about me. I know how that sounds. But I've realized that the more Claude knows, the more useful it becomes. When I ask "should I take this job offer?" it doesn't give me generic advice about pros and cons. It knows my financial situation, my career trajectory, my family plans, my risk tolerance. It can actually reason about MY situation, not some hypothetical person's.&lt;/p&gt;

&lt;p&gt;To start this out, I asked ChatGPT (which has the memory feature) to create a comprehensive personal profile guide to be consumed by Claude Code. Since ChatGPT already knew a lot about me from our conversations over the past year, it was able to compile a pretty good starting point. Then I reviewed it, added details, corrected things it got wrong, and now I keep it updated as things change.&lt;/p&gt;

&lt;p&gt;Some real question Claude has helped me answer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Financial planning: "Given our income, expenses, and the baby coming, can we afford to move to a bigger apartment?"&lt;/li&gt;
&lt;li&gt;Schedule optimization: "I want to start running again but my mornings are packed. Look at my routine and suggest where."&lt;/li&gt;
&lt;li&gt;Decision making: "My manager offered me this role change. Here's what I know about it. What am I not considering?"&lt;/li&gt;
&lt;li&gt;Goal tracking: "It's been 3 months since I set these goals. Pull up the file and help me review progress."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And unlike a human advisor who you'd have to re-explain your whole situation to every single time, Claude just reads the file and has full context immediately.&lt;/p&gt;

&lt;p&gt;I'm also starting to play with &lt;a href="https://github.com/clawdbot/clawdbot" rel="noopener noreferrer"&gt;Clawdbot&lt;/a&gt;, a self-hosted assistant that connects Claude to my messaging apps. So instead of opening a terminal, I can just message my AI through WhatsApp or Telegram, from anywhere.&lt;/p&gt;

&lt;p&gt;Cantillon ends her essay with: "The tools of synthesis belong to the individual now. Govern yourself accordingly."&lt;/p&gt;

&lt;p&gt;I'm trying to.&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>ai</category>
      <category>productivity</category>
      <category>programming</category>
    </item>
    <item>
      <title>Combining the power of React Query and GraphQL for data fetching and state management</title>
      <dc:creator>Juan Pablo Djeredjian</dc:creator>
      <pubDate>Tue, 02 Nov 2021 19:53:32 +0000</pubDate>
      <link>https://dev.to/juandj/combining-the-power-of-react-query-and-graphql-for-data-fetching-and-state-management-34h1</link>
      <guid>https://dev.to/juandj/combining-the-power-of-react-query-and-graphql-for-data-fetching-and-state-management-34h1</guid>
      <description>&lt;p&gt;On the &lt;a href="(https://dev.to/juandj/using-react-query-to-solve-state-management-in-your-react-app-4kf9)"&gt;first part&lt;/a&gt; of this series, we took a look at how, at my present company, we had the chance of starting a greenfield project, and could choose the libraries that we considered best for the jobs. We chose React Query to handle state management in our React app, and, because our backend team was delayed providing the API that was needed for the projects, we used a fake API to get the library working, and demo its functionality.&lt;/p&gt;

&lt;p&gt;All was going according to plan until we had a meeting with the backend team, and Connor, one of the engineers, set us up for a surprise: "We have been thinking and discussing this for a while, and we consider that the best solution we can offer you is to build a GraphQL server you can use to query and mutate the data".&lt;/p&gt;

&lt;p&gt;GraphQL? That was a first. Our company has many backend applications, some offering REST API services and other are message queues working with RabbitMQ, but GraphQL was definitely not under anyone's radar.&lt;/p&gt;

&lt;p&gt;But as I started thinking about it, it slowly started having more and more sense. The frontend application we were building would need to display lots of data in many different shapes, with some pages showing tables with rows containing only a certain selection of properties of the data, other pages showing data summaries, and in most cases we would need to build advanced filtering functionality. GraphQL's ability to serve the exact data requested by the user would save us a huge effort of re-formatting it in the frontend, prevent us from over or under-fetching, and basically tailoring every request we made exactly to our needs.&lt;/p&gt;

&lt;p&gt;It sounded good in theory... but we had already set up our up to use React Query as our data fetching library (and state management solution!), making requests to a REST endpoint. Would be need to throw everything away and start from scratch with something like Apollo?&lt;/p&gt;

&lt;p&gt;It took only a small revisit to the React Query docs to realize that this wasn't the case. As we said on the first part of this series, React Query's fetching mechanisms are agnostically built on &lt;strong&gt;Promises&lt;/strong&gt;, so it can be used with literally any asynchronous data fetching client, such as Axios, the native &lt;strong&gt;fetch&lt;/strong&gt; and even GraphQL!&lt;/p&gt;

&lt;p&gt;The library's docs recommended a mysterious tool for leveraging the combined power of React Query and GraphQL: &lt;a href="https://www.graphql-code-generator.com/" rel="noopener noreferrer"&gt;GraphQL-Codegen&lt;/a&gt;. What was that? I had no idea at the moment, but it promised type safety, and code generation for "ready-to-use React Hooks, based on your GraphQL operations".&lt;/p&gt;

&lt;p&gt;Digging a little deeper into the code generator's docs, we started to understand: "When we develop a GraphQL backend, there would be many instances where we would find ourselves writing the same things which are already described by the GraphQL schema [...] By analyzing the schema and parsing it, GraphQL Code Generator can output code at a wide variety of formats".&lt;/p&gt;

&lt;p&gt;The best way to understand that is to take a look at an example of what GraphQL-Codegen does: it takes (reads!) our schema and produces -in our case- TypeScript types that we can use all across our applications, that we otherwise would have needed to write from scratch.&lt;/p&gt;

&lt;p&gt;So, as the example in the docs show, provided we have the following GraphQL schema ir our app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;schema&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Mutation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;updateUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;!,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;UpdateUserInput&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;input&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;UpdateUserInput&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then GraphQL-Codegen will produce the following TypeScript types:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Maybe&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/** All built-in and custom scalars, mapped to their actual values */&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Scalars&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;String&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;Float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Author&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;__typename&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Author&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Scalars&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Int&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Scalars&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;String&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Scalars&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;String&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;Maybe&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Maybe&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Post&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;AuthorPostsArgs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;findTitle&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;Maybe&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Scalars&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;String&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;__typename&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Post&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Scalars&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Int&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Scalars&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;String&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;author&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;__typename&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Query&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;Maybe&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Maybe&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Post&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OK! So far so good! But what exactly does this have to do with React Query?&lt;/p&gt;

&lt;p&gt;To understand the real power of React Query + GraphQL + GraphQL-Codegen we need get our hands dirty.&lt;/p&gt;

&lt;h2&gt;
  
  
  Replacing our fake REST API with a fake GraphQL API
&lt;/h2&gt;

&lt;p&gt;While the discussions continued with our backend of how their application would be structured, we decided to modify the proof of concept that we had already built (and saw in part 1 of this series) and re-write it to query and mutate data with GraphQL. &lt;/p&gt;

&lt;p&gt;However, for that we had used the fake API service JSONPlaceholder. That would not help us anymore, as it provides a REST interface for fetching and updating mock resources. We needed a GraphQL API!&lt;/p&gt;

&lt;p&gt;Enter GraphQLZero to the rescue: an online GraphQL API both powered by JSONPlaceholder and serving its same data, as well as providing the schemas! Exactly what we needed.&lt;/p&gt;

&lt;p&gt;So taking as a starting point the demo we had built as seen in Part 1, we started by adding the GraphQL schema that we would feed the Code Generator, a simplified version of &lt;a href="https://graphqlzero.almansi.me/api" rel="noopener noreferrer"&gt;the schema provided by GraphQLZero.&lt;/a&gt; We thus created the &lt;code&gt;schema.graphql&lt;/code&gt; file on inside a new &lt;code&gt;/graphql&lt;/code&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="c"&gt;# Example schema taken from https://graphqlzero.almansi.me/api and simplified&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Mutation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;updateUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;!,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;UpdateUserInput&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;deleteUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;input&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;UpdateUserInput&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;input&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;AddressInput&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;street&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;suite&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;zipcode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can take a look at &lt;a href="https://graphql.org/learn/schema/" rel="noopener noreferrer"&gt;the detailed docs on what GraphQL schemas are and how to write them&lt;/a&gt;, but as you can see from our file, we defined the schema for a &lt;code&gt;User&lt;/code&gt; with a set of properties, as well as the &lt;code&gt;Query&lt;/code&gt; to retrieve one or many of them, and &lt;code&gt;Mutations&lt;/code&gt; to update and delete them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating our GraphQL documents
&lt;/h2&gt;

&lt;p&gt;The next step was to define our GraphQL documents. There are actually four types: &lt;code&gt;[query&lt;/code&gt;s, &lt;code&gt;mutation&lt;/code&gt;s, &lt;code&gt;fragment&lt;/code&gt;s and &lt;code&gt;subscription&lt;/code&gt;](&lt;a href="https://graphql.org/learn/queries/)s" rel="noopener noreferrer"&gt;https://graphql.org/learn/queries/)s&lt;/a&gt;, but for our use case we needed only queries -to fetch the data- and mutations -to update data-, as we had declared in our &lt;code&gt;schema.graphql&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For each query and mutation that we want to perform in our application, we need to define an individual document that our GraphQL-Codegen can later understand and transform into usable TypeScript/React code.&lt;/p&gt;

&lt;p&gt;Our simplest case is the &lt;strong&gt;query&lt;/strong&gt; for retrieving an individual user: it retrieves the &lt;code&gt;id&lt;/code&gt; and &lt;code&gt;name&lt;/code&gt; of a &lt;code&gt;User&lt;/code&gt; when the &lt;code&gt;id&lt;/code&gt; is passed as a parameter. We therefore created our &lt;code&gt;user.graphql&lt;/code&gt; document file and placed it in the new &lt;code&gt;/graphql/queries&lt;/code&gt; path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;!)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We needed also an additional &lt;strong&gt;query&lt;/strong&gt; that retrieves multiple users, a &lt;code&gt;UsersPage&lt;/code&gt; object type, with two sub-properties: firstly, a &lt;code&gt;data&lt;/code&gt; object which consists of an array of &lt;code&gt;Users&lt;/code&gt;, each of which will return the &lt;code&gt;id&lt;/code&gt; and &lt;code&gt;name&lt;/code&gt; properties; secondly, a &lt;code&gt;meta&lt;/code&gt; object, which provides a &lt;code&gt;totalCount&lt;/code&gt; property (total number of &lt;code&gt;Users&lt;/code&gt; returned). We named this file &lt;code&gt;users.graphql&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;getUsers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PageQueryOptions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;totalCount&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Example of &lt;code&gt;mutation&lt;/code&gt; document&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;What about updating &lt;code&gt;User&lt;/code&gt; ? In order to do that, we need to describe a &lt;code&gt;mutation&lt;/code&gt; that updates a &lt;code&gt;User&lt;/code&gt;'s properties, by passing as parameters the &lt;code&gt;ID&lt;/code&gt; of the user to update, as well as the properties to update in the shape of &lt;code&gt;UpdateUserInput&lt;/code&gt; input type.&lt;/p&gt;

&lt;p&gt;To keep our &lt;code&gt;/graphql&lt;/code&gt; directory organized, we created a further subdirectory called &lt;code&gt;/mutations&lt;/code&gt; and saved our &lt;code&gt;updateUser.graphql&lt;/code&gt; file there:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;mutation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;updateUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;!,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;UpdateUserInput&lt;/span&gt;&lt;span class="p"&gt;!)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;updateUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything seemed to be taking shape. We had now a new &lt;code&gt;/graphql&lt;/code&gt; folder with the following tree:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;├── graphql
│   ├── mutations
│   │   └── updateUser.graphql
│   ├── queries
│   │   ├── user.graphql
│   │   └── users.graphql
│   └── schema.graphql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using GraphQL-Codegen to generate the code for us
&lt;/h2&gt;

&lt;p&gt;So far so good. But all we have up until now are just a number of GraphQL documents with not much utility per se. How do we actually use them to retrieve and modify our data?&lt;/p&gt;

&lt;p&gt;This is where GraphQL-Codegen comes into place: a tool that works as the "glue" between React-Query and GraphQL. We will use it to not only automatically generate TypeScript types based on the schema we described above, but also -and this is where it really shines- to generate ready-to-use React Hooks based on each of the documents we just wrote! &lt;/p&gt;

&lt;p&gt;So, no more writing hooks to fetch or modify data by hand, just define a GraphQL document, run the code generator, and you'll have a hook at your disposal that leverages all the power of React-Query.&lt;/p&gt;

&lt;p&gt;Let's get started with &lt;strong&gt;GraphQL-Codegen.&lt;/strong&gt; Small note before though: the tool works for a wide array of languages and libraries, not only TypeScript and GraphQL. This is just one of the things it can do, and we are using this combination because this is how our app is written and what our backend looks like. But &lt;a href="https://www.graphql-code-generator.com/docs/getting-started/index" rel="noopener noreferrer"&gt;take a look at the docs&lt;/a&gt; to see all the possibilities it offers!&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting started with GraphQL-Codegen
&lt;/h3&gt;

&lt;p&gt;To get started, we first need to install &lt;code&gt;graphql&lt;/code&gt; as well as three dev dependencies from &lt;code&gt;@grapql-codegen&lt;/code&gt; : the &lt;code&gt;cli&lt;/code&gt; for running our commands; &lt;code&gt;typescript-operations&lt;/code&gt; , a plugin that generates the TS types out of our GraphQL schema and operations, and finally &lt;code&gt;typescript-react-query&lt;/code&gt; , which generates the React Query with TS typings for us:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add graphql
yarn add &lt;span class="nt"&gt;--dev&lt;/span&gt; @graphql-codegen/cli @graphql-codegen/typescript-operations @graphql-codegen/typescript-react-query
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As a following step, let's create a script  in our &lt;code&gt;package.json&lt;/code&gt; file, that we can run to get our code automatically generated using our newly installed CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"generate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"graphql-codegen"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now we move forward to the most important step: configuring the &lt;code&gt;codegen.yml&lt;/code&gt; file. This is the configuration file where we indicate GraphQL-Codgen what file it should create, where to generate it and point to which schemas and operations it should take into account. There is also a number of additional configuration options, some of which fit our use case.&lt;/p&gt;

&lt;p&gt;Let's take a look at the finished file and then we can dive deeper into what it all means:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./graphql/schema.graphql"&lt;/span&gt;
&lt;span class="na"&gt;documents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./graphql/queries/**.graphql"&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./graphql/mutations/**.graphql"&lt;/span&gt;
&lt;span class="na"&gt;generates&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;./src/_generated.ts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;typescript&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;typescript-operations&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;typescript-react-query&lt;/span&gt;
    &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;defaultScalarType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unknown&lt;/span&gt;
      &lt;span class="na"&gt;skipTypename&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="na"&gt;fetcher&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;endpoint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://graphqlzero.almansi.me/api"&lt;/span&gt;
        &lt;span class="na"&gt;fetchParams&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;content-type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;schema&lt;/code&gt;: a path string to a local GraphQL schema file or a URL to a GraphQL schema provided externally. It should provide schemas for our data types as well as operations (Query and Mutation). This option also supports multiple schemas, that can be provided as an array of strings, and they will be merged. In our case, we point to our single &lt;code&gt;schema.graphql&lt;/code&gt; file within our &lt;code&gt;graphql&lt;/code&gt; directory.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;documents&lt;/code&gt;: a path string that points to our GraphQL documents: query, mutation, subscription and fragment. Wildcards can be used to select all &lt;code&gt;.graphql&lt;/code&gt; files under a directory: for our case, we will use an array to point to all &lt;code&gt;*.graphql&lt;/code&gt; documents within our &lt;code&gt;/graphql/queries&lt;/code&gt; and &lt;code&gt;/graphql/mutations&lt;/code&gt; directories.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;generates&lt;/code&gt;: a key-value map where the key represents an output path for the generated code and the value represents a set of options which are relevant for that specific file. We will generate our code directly within our &lt;code&gt;/src&lt;/code&gt; folder.

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;generates.plugins&lt;/code&gt;: a required list of plugins that the code generator needs to auto-generate types and hooks based on our schema and documents. For our React-Query use case we need the plugins which we have previously installed:

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;typescript&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;typescript-operations&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;typescript-react-query&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;generates.config&lt;/code&gt;: a map used to pass additional configuration to the plugins. We are currently using:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;generates.config.defaultScalarType&lt;/code&gt;: instructs the plugin to override the type that unknown scalars will have. Default value is &lt;code&gt;any&lt;/code&gt;, but our config overrides it to &lt;code&gt;unknown&lt;/code&gt; due to avoid having &lt;code&gt;any&lt;/code&gt; types in our codebase.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;generates.config.skipTypename&lt;/code&gt;: instructs the plugin not to add the &lt;code&gt;__typename&lt;/code&gt; property to the generated types. Since we do not initially need to differentiate our objects types through their type, the default value is overriden to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;generates.config.fetcher&lt;/code&gt;: customizes the &lt;code&gt;fetcher&lt;/code&gt; function we wish to use in the generated file, and that will be responsible of making requests to our backend:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;generates.config.fetcher.endpoint&lt;/code&gt;: since we will point to a unique endpoint exposed by our GraphQL server, we can configure it in this property. This prevents us from having to pass in the endpoint every time we use one of the generated React Hooks.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;generates.config.fetcher.fetchParams&lt;/code&gt;: allows to set additional parameters to our &lt;code&gt;fetcher&lt;/code&gt; function such as headers. We'll set the &lt;code&gt;content-type&lt;/code&gt; header to &lt;code&gt;application/json&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Notice that you can also configure &lt;code&gt;codgen.yml&lt;/code&gt; to create multiple generated files with their own distinct schema, operations or config &lt;a href="https://www.graphql-code-generator.com/docs/getting-started/schema-field#multiple-schemas-and-client-side-schema" rel="noopener noreferrer"&gt;by structuring the file in an alternative way.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's go ahead and run our code generator by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn generate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we take a look at the &lt;code&gt;_generated.ts&lt;/code&gt; file created within &lt;code&gt;/src&lt;/code&gt; we can first see how our &lt;code&gt;fetcher&lt;/code&gt; function was automatically generated, already pointed at our pre-defined endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fetcher&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;TVariables&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;variables&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;TVariables&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TData&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://graphqlzero.almansi.me/api&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;content-type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;variables&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;json&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's also interesting to see how the generator creates TypeScript types based on our schema. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Maybe&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Scalars&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;String&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;Float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;Maybe&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Scalars&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;String&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;Maybe&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Scalars&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ID&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;Maybe&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Scalars&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;String&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;username&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;Maybe&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Scalars&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;String&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll later use these types along our codebase. But more interestingly, let's see how our tool generated ready-to-use React hooks (based on the React-Query hooks!) that completely handle data fetching and updating.&lt;/p&gt;

&lt;p&gt;For example, let's take a look at the &lt;code&gt;useGetUserQuery&lt;/code&gt; hook, that we can use to fetch a single user by passing an &lt;code&gt;ID&lt;/code&gt; to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;UseQueryOptions&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-query&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;GetUserQuery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; 
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;GetUserQueryVariables&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Exact&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Scalars&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ID&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;GetUserDocument&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
    query getUser($id: ID!) {
      user(id: $id) {
        id
        name
      }
    }
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useGetUserQuery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;
  &lt;span class="na"&gt;TData&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="na"&gt;GetUserQuery&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;TError&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="na"&gt;unknown&lt;/span&gt;
&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;(
  variables: GetUserQueryVariables,
  options?: UseQueryOptions&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;GetUserQuery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; TError, TData&amp;gt;
) =&amp;gt;
    useQuery&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;GetUserQuery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; TError, TData&amp;gt;(
      ['getUser', variables],
      fetcher&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;GetUserQuery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; GetUserQueryVariables&amp;gt;(GetUserDocument, variables),
      options
    );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how the generator first creates the types it needs based on the schema we provided, as well as on the query document. It then uses those types to create a hook that reutilizes React Query's &lt;code&gt;useQuery&lt;/code&gt; and passes down the types as generics, the query parameters as variables, and the &lt;code&gt;fetcher&lt;/code&gt; function we saw above, which is responsible for actually making the request.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using our hooks to fetch data
&lt;/h3&gt;

&lt;p&gt;We are now ready to leverage the combined power of React Query and GraphQL. For demonstration purposes, let's create a component that takes an &lt;code&gt;id&lt;/code&gt; as input from the user of our app, calls the &lt;code&gt;useGetUserQuery&lt;/code&gt; to fetch a User from our GraphQLZero API and display it on screen.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ChangeEvent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useGetUserQuery&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./_generated&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;UserDisplay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setUserId&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updateUserId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ChangeEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLInputElement&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setUserId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;isError&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useGetUserQuery&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isError&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Error. Please reload page.&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Select a User ID between 1 and 10: &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"number"&lt;/span&gt; &lt;span class="na"&gt;min&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;max&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;updateUserId&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; 
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"userRow"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;User Id: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how we use &lt;code&gt;useGetUserQuery&lt;/code&gt; in a way that is analogous to the use of the common &lt;code&gt;useQuery&lt;/code&gt; hook provided by the React Query library. In this case, we just pass the &lt;code&gt;userId&lt;/code&gt; state as the &lt;code&gt;id&lt;/code&gt; so that every time that it updates, the hook is re-run, and a request is made to our GraphQL backend with it as a parameter! Pretty amazing stuff.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fg.recordit.co%2FRVCEE1xDIv.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fg.recordit.co%2FRVCEE1xDIv.gif" alt="graphqlreact.gif" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Wrapping it up
&lt;/h3&gt;

&lt;p&gt;We have now seen how we can leverage the combined power of React Query and GraphQL to easily and flexibly handle data fetching and updating. By simply defining our GraphQL schemas and documents and taking advantage of the fantastic GraphQL-Codgen tool, handling our data needs becomes a breeze that really accelerates the development experience, and pushes our codebases to be more maintainable with reusable types and React hooks.&lt;/p&gt;

&lt;p&gt;If you have an app that consumes a GraphQL endpoint, be sure to give these tools a try.&lt;/p&gt;

&lt;p&gt;Check out &lt;a href="https://react-query-graphql-demo.vercel.app/" rel="noopener noreferrer"&gt;the finished demo app&lt;/a&gt; and &lt;a href="https://github.com/jpdjere/react-query-graphql-demo" rel="noopener noreferrer"&gt;clone the repo&lt;/a&gt; to play around with the code.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>typescript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Using React Query to solve state management in your React app</title>
      <dc:creator>Juan Pablo Djeredjian</dc:creator>
      <pubDate>Fri, 15 Oct 2021 16:16:31 +0000</pubDate>
      <link>https://dev.to/juandj/using-react-query-to-solve-state-management-in-your-react-app-4kf9</link>
      <guid>https://dev.to/juandj/using-react-query-to-solve-state-management-in-your-react-app-4kf9</guid>
      <description>&lt;p&gt;I recently got the opportunity (and the privilege!) of starting a greenfield project at my current company, involving an frontend application for an internal tool. The devs involved had the chance to choose the tech stack that we considered convenient, and we collaboratively wrote an RFC (Request for Comment) and presented it to the rest of the company to open up our choices to discussion.&lt;/p&gt;

&lt;p&gt;One of the main points that came up -after settling for React, the lingua franca framework at our company- is how we would handle state management. Our main application uses Redux, but many other alternatives were brought up: MobX, using native hooks (a combination of useReducer + useContext), using Redux plus Redux Toolkit. I even got to know and proposed Recoil, a super exciting project -and definitely a library with one of the best presentation videos I've seen so far.&lt;/p&gt;

&lt;p&gt;But our Staff Engineer Zac came up with a different idea. Enter React-Query.&lt;/p&gt;

&lt;h3&gt;
  
  
  React Query's novel approach to state management
&lt;/h3&gt;

&lt;p&gt;"I haven't used it yet, but I love the different approach it takes to handle state within an application. It basically splits server side state out from client side state and automates a lot of stuff like re-fetching and caching", explained Zac.&lt;/p&gt;

&lt;p&gt;The idea clicked with me instantly: most of the state that React apps keep in their store is just a reflection of data persisted remotely somewhere (a User, a list of Posts, Comments, or To-Dos, for e.g.). Only a minor part of it is client-side only, and it almost always corresponds to UI/UX information, like if whether a modal is open, a sidebar expanded, etc.&lt;/p&gt;

&lt;p&gt;So the idea behind React Query is taking that majority of server-side state and handling it completely: fetching, re-fetching, storing, cacheing, updating and memoizing it in an all-in-one solution. This separations helps to reduce a lot of the boilerplate that inevitably arises with other combined client- and server-side state management tools (such as Redux).&lt;/p&gt;

&lt;p&gt;The library also offers some advanced features like "optimistic updates", in which the library assumes an update to the data will be successful before actually receiving a response from the back-end, and allows to easily roll it back if it fails, making the app seem responsive as a breeze to the user.&lt;/p&gt;

&lt;p&gt;Promising enough. We decided that we'd go with it during the Proof of Concept phase of the app and started writing code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Writing the PoC with create-react-app
&lt;/h3&gt;

&lt;p&gt;As we started working on the frontend way before our backend team had availability to build the services that would provide the data needed for the app, we decided to go forward with setting up our project with &lt;strong&gt;create-react-app with its TypeScript template&lt;/strong&gt; and React Query using JSONPlaceholder as a fake API.&lt;/p&gt;

&lt;p&gt;So, let's write some code!&lt;/p&gt;

&lt;p&gt;First, we created a new app with create-react-app's CLI and installed react-query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-react-app react-query-demo &lt;span class="nt"&gt;--template&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;typescript
&lt;span class="nb"&gt;cd &lt;/span&gt;react-query-demo
yarn add react-query
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;App.tsx&lt;/code&gt; component that comes by default looks so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;logo&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./logo.svg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./App.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"App"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;header&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"App-header"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;logo&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"App-logo"&lt;/span&gt; &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"logo"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          Edit &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;code&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;src/App.tsx&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;code&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; and save to reload.
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;
          &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"App-link"&lt;/span&gt;
          &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"https://reactjs.org"&lt;/span&gt;
          &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"_blank"&lt;/span&gt;
          &lt;span class="na"&gt;rel&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"noopener noreferrer"&lt;/span&gt;
        &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          Learn React
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;header&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Following React-Query's excellent documentation, we first modified that file by wrapping our app with the &lt;code&gt;QueryClientProvider&lt;/code&gt; that comes included in the library and created a new component &lt;code&gt;UserList&lt;/code&gt; where we will fetch our &lt;code&gt;Users&lt;/code&gt; from our fake API.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;QueryClientProvider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;QueryClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-query&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./App.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;UserList&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./UserList&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;queryClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;QueryClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;QueryClientProvider&lt;/span&gt; &lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;queryClient&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"App"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;header&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"App-header"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;React Query Demo&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;header&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;UserList&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;QueryClientProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's unpack our changes in that component. We first instantiated a new &lt;code&gt;queryClient&lt;/code&gt; instance with the &lt;code&gt;QueryClient&lt;/code&gt; constructor that React Query provides. We then passed that instance to the &lt;code&gt;QueryClientProvider&lt;/code&gt; with which we wrapped our whole app. This provides a context for our cached data and allows all components wrapped in it to use the querying and updating hooks that the library provides.&lt;/p&gt;

&lt;p&gt;We also cleaned up our component a bit, changed the title and added our newly created &lt;code&gt;UserList&lt;/code&gt; component, where things start to get real interesting. Let's take a look at it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useQuery&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-query&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;USERS_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;UserList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;isError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;error&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useQuery&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;USERS_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://jsonplaceholder.typicode.com/users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Network response failed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;}));&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Error: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"userRow"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Username: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A lot more going on here, but this is where the juice of React Query really shows. Let's unpack all of it.&lt;/p&gt;

&lt;p&gt;As we are using JSONPlaceholder's fake API to fetch a list of users, we first create the &lt;code&gt;User&lt;/code&gt; interface, a simplified version &lt;a href="https://jsonplaceholder.typicode.com/users" rel="noopener noreferrer"&gt;based on the schema provided&lt;/a&gt; by the site. In our case, we will fetch an array of Users and display it to the user.&lt;/p&gt;

&lt;p&gt;Within our component, we make use of the main tool that React-Query provides: the &lt;code&gt;useQuery&lt;/code&gt; hook. The hook takes two arguments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a &lt;strong&gt;unique query key&lt;/strong&gt; which is used internally by React Query for "refetching, caching and sharing queries across the application". The library will store the data under this key, in a similar way as data for different reducers are kept under a key name in Redux. In our case, we set it to the &lt;code&gt;USERS_KEY&lt;/code&gt; constant, which is simply a string of value  &lt;code&gt;"users"&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;a &lt;strong&gt;function that returns a promise&lt;/strong&gt; that resolves the data, or throws an error.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The second argument highlights one of library's great advantages: since React Query's fetching mechanisms are agnostically built on &lt;strong&gt;Promises&lt;/strong&gt;, it can be used with literally any asynchronous data fetching client, such as Axios, the native &lt;strong&gt;fetch&lt;/strong&gt; and even GraphQL! (we'll expand on how to do this in a subsequent post).&lt;/p&gt;

&lt;p&gt;For now, we are using &lt;strong&gt;fetch&lt;/strong&gt; to request a list of &lt;code&gt;User&lt;/code&gt;s from the &lt;a href="https://jsonplaceholder.typicode.com/users" rel="noopener noreferrer"&gt;&lt;code&gt;https://jsonplaceholder.typicode.com/users&lt;/code&gt;&lt;/a&gt; endpoint. Notice that, when using fetch, we must also manually check if the request is successful, and throw an error is if it not, as the second parameter expects the fetcher function to throw when an error occurs, and fetch does not automatically do this. This wouldn't be necessary if we were using Axios, for example.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note for TypeScript users:&lt;/strong&gt; React Query allows you to provide, via Generics, the result and error types of its hooks. This is especially useful when creating your own custom hooks, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useGetUsers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;useQuery&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fetchUsers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;useQuery&lt;/code&gt; hook returns an object, from where we have destructured three properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;isLoading:&lt;/strong&gt; a boolean that indicates that the query has no data and is currently fetching.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;data:&lt;/strong&gt; the property that contains the data that the Promise resolved to if the request was successful. In our case, it is an array of &lt;code&gt;User&lt;/code&gt;s, and we aliased it to the variable name &lt;code&gt;users&lt;/code&gt; just for clarity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;isError:&lt;/strong&gt; a boolean that indicated that the query encountered an error.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;error:&lt;/strong&gt; a property that contains the error thrown if the query is in an &lt;strong&gt;isError&lt;/strong&gt; state.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can use these properties to decide what the component should render, depending on the state of the query. We first check if it is in an &lt;code&gt;isLoading&lt;/code&gt; state, and render a message accordingly. We then check if it an error occured via the &lt;code&gt;isError&lt;/code&gt; boolean, and display the error under &lt;code&gt;error.message&lt;/code&gt; . Finally, we can safely assume that query is in &lt;code&gt;isSuccess&lt;/code&gt; state and render our list of users.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Updating our server-side state&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So far so good, but what about when we need to create, update or delete our remotely stored data? React Query solves this issue with the concept of &lt;strong&gt;Mutations&lt;/strong&gt; and the &lt;code&gt;useMutation&lt;/code&gt; hook.&lt;/p&gt;

&lt;p&gt;Let's create another component &lt;code&gt;CreateUser&lt;/code&gt; that renders a button which POSTs a new user to the API when clicking on it, and add it to our &lt;code&gt;App&lt;/code&gt; .&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;[...]&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;QueryClientProvider&lt;/span&gt; &lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;queryClient&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"App"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;header&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"App-header"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;React Query Demo&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;header&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;UserList&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CreateUser&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;QueryClientProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This time, we'll use Axios as our HTTP client to highlight React Query's versatility. Let's install it first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add axios
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And let's write the code for our new component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useMutation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useQueryClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-query&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;USERS_KEY&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./UserList&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;exampleUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John Doe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;johndoe@gmail.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;johndoe1990&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;postUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://jsonplaceholder.typicode.com/users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CreateUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;queryClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useQueryClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mutate&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMutation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;postUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;onSuccess&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;queryClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invalidateQueries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;USERS_KEY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onButtonClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;mutate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;exampleUser&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Creating User...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onButtonClick&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Click to post a new user&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's go over what's going on here.&lt;/p&gt;

&lt;p&gt;Firstly, we create a hard-coded &lt;code&gt;exampleUser&lt;/code&gt; to POST into the fake API when the user clicks on the button. We also create our required &lt;strong&gt;mutation function&lt;/strong&gt;, &lt;code&gt;postUser&lt;/code&gt; &lt;strong&gt;,&lt;/strong&gt; which returns a Promise of an Axios Response of a POST call to our &lt;code&gt;/users&lt;/code&gt; endpoint, passing in as data the argument of our mutation function.&lt;/p&gt;

&lt;p&gt;Inside our component, we'll first initialize an instance of &lt;code&gt;queryClient&lt;/code&gt; with the &lt;code&gt;useQueryClient&lt;/code&gt; hook, also provided by React Query. This is the same instance created in &lt;code&gt;App.tsx&lt;/code&gt; and provided by our &lt;code&gt;QueryClientProvider&lt;/code&gt;. We'll make use of it in a second.&lt;/p&gt;

&lt;p&gt;And now we make use of the &lt;code&gt;useMutation&lt;/code&gt; hook, also provided by React Query, which takes two arguments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a required &lt;strong&gt;mutation function&lt;/strong&gt; that performs an asynchronous task and returns a Promise. In our case, we pass in the already defined &lt;code&gt;postUser&lt;/code&gt; function.&lt;/li&gt;
&lt;li&gt;an object with multiple properties:

&lt;ul&gt;
&lt;li&gt;an optional &lt;strong&gt;mutation key&lt;/strong&gt;, in a similar way as we defined a &lt;strong&gt;query key&lt;/strong&gt;, to be used internally. We don't need to set one for this example.&lt;/li&gt;
&lt;li&gt;an optional &lt;strong&gt;onSuccess&lt;/strong&gt; callback, that fires when the mutation is successful and is passed the mutation result.&lt;/li&gt;
&lt;li&gt;an optional &lt;strong&gt;onError&lt;/strong&gt; callback that will fires if the mutation fails, and will get the error passed.&lt;/li&gt;
&lt;li&gt;an optional &lt;strong&gt;onMutate&lt;/strong&gt; callback, that fires before the mutation function is fired and is passed the same variables the mutation function would receive. This allows us to do optimistic updates: that is, we can early update a resource (and our UI) in the hope that the mutation succeeds and give our application a "synchronous feel". The value returned from this function will be passed to the &lt;strong&gt;onError&lt;/strong&gt; and the &lt;strong&gt;onSettled&lt;/strong&gt; callbacks, so that we can rollback our optimistic update in case the mutations fails.&lt;/li&gt;
&lt;li&gt;more config properties can be found &lt;a href="https://react-query.tanstack.com/reference/useMutation" rel="noopener noreferrer"&gt;in the docs.&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;In our example, we are only setting up an &lt;code&gt;onSuccess&lt;/code&gt; callback whose job is to invalidate our &lt;code&gt;"users"&lt;/code&gt; query, by calling the &lt;code&gt;invalidateQueries&lt;/code&gt; utility provided by our &lt;code&gt;queryClient&lt;/code&gt; and passing our &lt;code&gt;USERS_KEY&lt;/code&gt; as argument to it. By invalidating this query key in our cache after the mutation is successful, we indicate React Query that the data under that key is outdated and it should refetch it. Thus, the library will automatically re-query our &lt;code&gt;/users&lt;/code&gt; endpoint, and will bring back our updated &lt;code&gt;Users&lt;/code&gt; list.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;useMutation&lt;/code&gt; hook returns an object from where we destructure two properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;mutate:&lt;/strong&gt; a function that can be called passing variables to it as parameters and will trigger the mutation defined in the &lt;strong&gt;mutation function&lt;/strong&gt; defined in the hook.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;isLoading:&lt;/strong&gt; a boolean that indicates that the mutation is still pending.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our &lt;code&gt;CreateUser&lt;/code&gt; component will use &lt;strong&gt;mutate&lt;/strong&gt; when clicking on a button, so we create an &lt;code&gt;onButtonClick&lt;/code&gt; function that fires &lt;code&gt;mutate&lt;/code&gt; passing it our hardcoded &lt;code&gt;exampleUser&lt;/code&gt; as an argument. We then use our &lt;code&gt;isLoading&lt;/code&gt; flag to show an appropriate message to the user when the mutation is pending, or display the button with a call-to-action otherwise.&lt;/p&gt;

&lt;p&gt;And that's it! Try playing around with it in the app. One note though, if you check the Network tab on the DevTools, you'll see that, because we are using a fake API, the &lt;strong&gt;POST&lt;/strong&gt; call to add a user will indeed succeed with status code &lt;code&gt;201&lt;/code&gt; . However, when React Query refetches the data, (the subsequent &lt;strong&gt;GET&lt;/strong&gt; call that gets fired after we invalidate our query key) the new user won't be in the returned data there as &lt;strong&gt;JSONPlaceholder&lt;/strong&gt; will simply ignore any new data added to it. However, on a real API you would see the &lt;code&gt;User&lt;/code&gt; you just posted.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wrapping it up&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We've seen how React Query can handle the fetching of the data, cacheing and updating (via refetching) and provides us with a user-friendly hook to handle the returned data and rendering. Through the use of its &lt;strong&gt;query keys&lt;/strong&gt;, and its simple API, the library can replace a fully fledged state management solution, taking out of your hands the responsibility of writing hundred of lines of boilerplate code, and adding great functionality that you'd otherwise have to write from scratch.&lt;/p&gt;

&lt;p&gt;Check out &lt;a href="https://react-query-demo-zeta.vercel.app/" rel="noopener noreferrer"&gt;the finished demo app&lt;/a&gt; and &lt;a href="https://github.com/jpdjere/react-query-demo" rel="noopener noreferrer"&gt;clone the repo&lt;/a&gt; to play around with the code. And don't forget to give &lt;a href="https://react-query.tanstack.com/overview" rel="noopener noreferrer"&gt;the official documentation&lt;/a&gt; a read.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>react</category>
      <category>redux</category>
    </item>
  </channel>
</rss>
