{"id":7508,"date":"2025-07-02T23:32:42","date_gmt":"2025-07-02T23:32:42","guid":{"rendered":"https:\/\/namastedev.com\/blog\/?p=7508"},"modified":"2025-07-02T23:32:42","modified_gmt":"2025-07-02T23:32:42","slug":"data-fetching-with-swr-and-react-query-5","status":"publish","type":"post","link":"https:\/\/namastedev.com\/blog\/data-fetching-with-swr-and-react-query-5\/","title":{"rendered":"Data Fetching with SWR and React Query"},"content":{"rendered":"<h1>Data Fetching with SWR and React Query: A Comprehensive Guide<\/h1>\n<p>Data fetching is a crucial part of modern web development, especially when building applications that require real-time data updates. With numerous libraries available, developers often find themselves debating between SWR (stale-while-revalidate) and React Query. In this article, we&#8217;ll delve deep into both libraries, exploring their features, use cases, and how you can effectively implement them in your React applications.<\/p>\n<h2>What is SWR?<\/h2>\n<p>SWR is a React Hooks library created by Vercel, designed for data fetching and caching. The name SWR stands for &#8220;Stale-While-Revalidate,&#8221; which is a cache invalidation strategy that serves stale data while revalidating the data in the background.<\/p>\n<h3>Key Features of SWR<\/h3>\n<ul>\n<li><strong>Automatic Caching:<\/strong> SWR caches the response data, reducing redundant network requests.<\/li>\n<li><strong>Real-time Updates:<\/strong> It provides real-time updates through its revalidation mechanism.<\/li>\n<li><strong>Built-in support for Suspense:<\/strong> SWR works seamlessly with React&#8217;s Suspense, making data loading intuitive.<\/li>\n<li><strong>TypeScript Support:<\/strong> SWR is fully compatible with TypeScript, enhancing developer experience with type safety.<\/li>\n<\/ul>\n<h2>What is React Query?<\/h2>\n<p>React Query is another powerful library for fetching, caching, and synchronizing server state in React applications. It excels in managing server-side data, making it easy to build complex data fetching layers.<\/p>\n<h3>Key Features of React Query<\/h3>\n<ul>\n<li><strong>Powerful Query Management:<\/strong> Manage query state, automatic caching, and background fetching.<\/li>\n<li><strong>Pagination and Infinite Querying:<\/strong> Built-in support for pagination and infinite scrolling.<\/li>\n<li><strong>Query Invalidations:<\/strong> Fine-grained invalidation and refetching control, allowing for optimal data freshness.<\/li>\n<li><strong>DevTools:<\/strong> React Query DevTools helps with debug and optimize your queries.<\/li>\n<\/ul>\n<h2>When to Use SWR vs. React Query<\/h2>\n<p>Choosing between SWR and React Query can depend on several factors:<\/p>\n<ul>\n<li><strong>Simplicity:<\/strong> If your application has straightforward data-fetching needs, SWR\u2019s minimalistic approach is a great option.<\/li>\n<li><strong>Complex State Management:<\/strong> For applications requiring complex server state interactions such as pagination, caching strategies, and query invalidation, React Query shines.<\/li>\n<li><strong>Real-time Data:<\/strong> Both libraries offer real-time capabilities, but SWR\u2019s focus on revalidation makes it particularly suited for real-time applications.<\/li>\n<\/ul>\n<h2>Getting Started with SWR<\/h2>\n<p>Let\u2019s see how to fetch data using SWR in a simple React component.<\/p>\n<h3>Installation<\/h3>\n<pre><code>npm install swr<\/code><\/pre>\n<h3>Basic Usage<\/h3>\n<p>Here\u2019s an example of how to use SWR to fetch a list of users from an API:<\/p>\n<pre><code>import useSWR from 'swr';\n\nconst fetcher = (url) =&gt; fetch(url).then((res) =&gt; res.json());\n\nfunction UserList() {\n    const { data, error } = useSWR('https:\/\/jsonplaceholder.typicode.com\/users', fetcher);\n\n    if (error) return &lt;p&gt;Failed to load&lt;\/p&gt;;\n    if (!data) return &lt;p&gt;Loading...&lt;\/p&gt;;\n\n    return (\n        &lt;ul&gt;\n            {data.map(user =&gt; &lt;li key={user.id}&gt;{user.name}&lt;\/li&gt;)}\n        &lt;\/ul&gt;\n    );\n}<\/code><\/pre>\n<h2>Getting Started with React Query<\/h2>\n<h3>Installation<\/h3>\n<pre><code>npm install react-query<\/code><\/pre>\n<h3>Basic Usage<\/h3>\n<p>Here\u2019s how to fetch the same list of users using React Query:<\/p>\n<pre><code>import { useQuery } from 'react-query';\n\nconst fetchUsers = async () =&gt; {\n    const response = await fetch('https:\/\/jsonplaceholder.typicode.com\/users');\n    if (!response.ok) {\n        throw new Error('Network response was not ok');\n    }\n    return response.json();\n};\n\nfunction UserList() {\n    const { data, error, isLoading } = useQuery('users', fetchUsers);\n\n    if (isLoading) return &lt;p&gt;Loading...&lt;\/p&gt;;\n    if (error) return &lt;p&gt;Error: {error.message}&lt;\/p&gt;;\n\n    return (\n        &lt;ul&gt;\n            {data.map(user =&gt; &lt;li key={user.id}&gt;{user.name}&lt;\/li&gt;)}\n        &lt;\/ul&gt;\n    );\n}<\/code><\/pre>\n<h2>Comparing SWR and React Query: A Side-by-Side Example<\/h2>\n<p>Let\u2019s compare both libraries in a more detailed example where we implement data fetching, error handling, and loading states.<\/p>\n<h3>Example: Fetching Posts<\/h3>\n<h4>Using SWR<\/h4>\n<pre><code>import useSWR from 'swr';\n\nconst fetcher = (url) =&gt; fetch(url).then((res) =&gt; res.json());\n\nfunction Posts() {\n    const { data, error, isLoading } = useSWR('https:\/\/jsonplaceholder.typicode.com\/posts', fetcher);\n\n    if (error) return &lt;p&gt;Error loading posts&lt;\/p&gt;;\n    if (!data &amp;&amp; isLoading) return &lt;p&gt;Loading posts...&lt;\/p&gt;;\n\n    return (\n        &lt;div&gt;\n            &lt;h2&gt;Posts&lt;\/h2&gt;\n            &lt;ul&gt;\n                {data.map(post =&gt; (\n                    &lt;li key={post.id}&gt;{post.title}&lt;\/li&gt;\n                ))}&lt;\/ul&gt;\n        &lt;\/div&gt;\n    );\n}<\/code><\/pre>\n<h4>Using React Query<\/h4>\n<pre><code>import { useQuery } from 'react-query';\n\nconst fetchPosts = async () =&gt; {\n    const response = await fetch('https:\/\/jsonplaceholder.typicode.com\/posts');\n    if (!response.ok) {\n        throw new Error('Network response was not ok');\n    }\n    return response.json();\n};\n\nfunction Posts() {\n    const { data, error, isLoading } = useQuery('posts', fetchPosts);\n\n    if (isLoading) return &lt;p&gt;Loading posts...&lt;\/p&gt;;\n    if (error) return &lt;p&gt;Error loading posts: {error.message}&lt;\/p&gt;;\n\n    return (\n        &lt;div&gt;\n            &lt;h2&gt;Posts&lt;\/h2&gt;\n            &lt;ul&gt;\n                {data.map(post =&gt; (\n                    &lt;li key={post.id}&gt;{post.title}&lt;\/li&gt;\n                ))}&lt;\/ul&gt;\n        &lt;\/div&gt;\n    );\n}<\/code><\/pre>\n<h2>Handling Mutations<\/h2>\n<p>Both libraries provide convenient ways to handle data mutations such as creating, updating, and deleting records.<\/p>\n<h3>Mutations with SWR<\/h3>\n<pre><code>import useSWR, { mutate } from 'swr';\n\nconst postFetcher = (url, data) =&gt; fetch(url, {\n    method: 'POST',\n    headers: {\n        'Content-Type': 'application\/json',\n    },\n    body: JSON.stringify(data),\n}).then((res) =&gt; res.json());\n\nfunction CreatePost() {\n    const handleSubmit = async (e) =&gt; {\n        e.preventDefault();\n        const data = { title: e.target.title.value };\n        \/\/ update local data and refetch\n        const newPost = await postFetcher('https:\/\/jsonplaceholder.typicode.com\/posts', data);\n        mutate('https:\/\/jsonplaceholder.typicode.com\/posts', (posts) =&gt; [...posts, newPost], false);\n    };\n\n    return (\n        &lt;form onSubmit={handleSubmit}&gt;\n            &lt;input name=\"title\" required \/&gt;\n            &lt;button type=\"submit\"&gt;Create Post&lt;\/button&gt;\n        &lt;\/form&gt;\n    );\n}<\/code><\/pre>\n<h3>Mutations with React Query<\/h3>\n<pre><code>import { useMutation, useQueryClient } from 'react-query';\n\nfunction CreatePost() {\n    const queryClient = useQueryClient();\n\n    const mutation = useMutation(newPost =&gt; {\n        return fetch('https:\/\/jsonplaceholder.typicode.com\/posts', {\n            method: 'POST',\n            body: JSON.stringify(newPost),\n            headers: {\n                'Content-Type': 'application\/json',\n            },\n        }).then((res) =&gt; res.json());\n    }, {\n        onSuccess: () =&gt; {\n            queryClient.invalidateQueries('posts');\n        }\n    });\n\n    const handleSubmit = async (e) =&gt; {\n        e.preventDefault();\n        const data = { title: e.target.title.value };\n        mutation.mutate(data);\n    };\n\n    return (\n        &lt;form onSubmit={handleSubmit}&gt;\n            &lt;input name=\"title\" required \/&gt;\n            &lt;button type=\"submit\"&gt;Create Post&lt;\/button&gt;\n        &lt;\/form&gt;\n    );\n}<\/code><\/pre>\n<h2>Conclusion<\/h2>\n<p>In summary, both SWR and React Query have their unique strengths and cater to different needs in the world of data fetching. SWR excels in simplicity and real-time capabilities, while React Query shines in complex state management and query optimization. By understanding your application&#8217;s requirements, you can confidently choose the right data-fetching library for your next React project.<\/p>\n<h3>Further Reading and Resources<\/h3>\n<ul>\n<li><a href=\"https:\/\/swr.vercel.app\/\">SWR Documentation<\/a><\/li>\n<li><a href=\"https:\/\/react-query.tanstack.com\/\">React Query Documentation<\/a><\/li>\n<li><a href=\"https:\/\/reactjs.org\/docs\/hooks-intro.html\">React Hooks Documentation<\/a><\/li>\n<\/ul>\n<p>Happy coding!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Data Fetching with SWR and React Query: A Comprehensive Guide Data fetching is a crucial part of modern web development, especially when building applications that require real-time data updates. With numerous libraries available, developers often find themselves debating between SWR (stale-while-revalidate) and React Query. In this article, we&#8217;ll delve deep into both libraries, exploring their<\/p>\n","protected":false},"author":78,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[398],"tags":[224],"class_list":{"0":"post-7508","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-react","7":"tag-react"},"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/posts\/7508","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/users\/78"}],"replies":[{"embeddable":true,"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/comments?post=7508"}],"version-history":[{"count":1,"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/posts\/7508\/revisions"}],"predecessor-version":[{"id":7509,"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/posts\/7508\/revisions\/7509"}],"wp:attachment":[{"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/media?parent=7508"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/categories?post=7508"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/tags?post=7508"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}