Data fetching is a core aspect of dynamic and responsive applications in modern web development. Reactjs is a popular frontend library, which offers several ways to fetch and manage data.
Whether you’re building a simple app or a complex large app, It’s important to understand the various methods you can use to fetch data in react
While building a large and complex application, it is considered best practice to keep your files and folders clean and more organized way to avoid duplication and navigate easily and understandable. There are many ways but, I’m sharing with you the most popular way. Learn more about Setting up your Reactjs project structure by using atomic design pattern.
In this article, I’m going to share 5 different methods for fetching data from servers using RESTful API in reactjs:
- Fetch API
- Axios
- React Query
- SWR
- GraphQL (Apollo Client)
If you’re curious about native javascript ways, read this article on making API calls in javascript in 5 different ways.
1) Fetch API
The Fetch API is a modern & built-in javascript function for making asynchronous calls. It’s a native browser API that returns a promise. The Fetch API is built on top of javascript promises which makes handling requests much easier and cleaner to write.
Here is an example of fetching data in reactjs using Fetch API:
import React, { useEffect, useState } from "react"; export default function PostsListWrapper() { const [posts, setPosts] = useState([]); const [loading, setLoading] = useState(true); const getPosts = () => { return fetch("https://jsonplaceholder.typicode.com/posts") .then((response) => response.json()) .then((data) => { setPosts(data); setLoading(false); }) .catch((error) => console.error("Error: ", error)); }; useEffect(() => { getPosts(); }, []); if(loading) return <p>Loading...</p> return ( <section> <h3>Posts List</h3> <ul>{posts && posts?.map((item, idx) => <li key={item.id}>{item.title}</li>)}</ul> </section> ); }
JSXIn the above example, I have created a posts list wrapper component that fetches dummy data from public API https://jsonplaceholder.typicode.com/posts. One thing that we have to do manually is to convert our JSON result to a JavaScript object. The .then() the chaining method used after the fetch function, waits for the API to finish, and this is where we do our work like setting data in state.
2) Axios
Axios is the most popular third-party library for making asynchronous calls, based on javascript promises. Axios is simpler, faster, and much more powerful than native Fetch API, it provides control over our HTTP request.
Some of the best features I love that make it unique and powerful, such as,
- easy syntax
- creating different instances
- configure request
- playing with interceptors (middleware) to manipulate data in request and response
- retry or cancel the request
- handling errors
- and many others.
If you’re interested in learning more about these interesting features, go to this link to read official docs.
In order to use axios
in the react application, you need to install it as a dependency. Run the below command to install Axios:
npm i axios
ShellScriptLet’s see Axios in action:
import React, { useEffect, useState } from "react"; // import axios import axios from "axios"; // defining a base url const BASE_URL = "https://jsonplaceholder.typicode.com"; // creating an instance const publicInstance = axios.create({ baseURL: BASE_URL, }); export default function PostsListWrapper() { const [posts, setPosts] = useState([]); const [loading, setLoading] = useState(true); const getPosts = async () => { try { let posts = await publicInstance({ url: "/posts", method: "GET", }); setLoading(false); setPosts(posts?.data); } catch (error) { console.log("Error: ", error); } }; useEffect(() => { getPosts(); }, []); if (loading) return <p>Loading...</p>; return ( <section> <h3>Posts List</h3> <ul> {posts && posts?.map((item, idx) => <li key={item.id}>{item.title}</li>)} </ul> </section> ); }
JSXThe above example shows a different syntax than Fetch API. We can also use Axios as we did with fetch using chaining methods, but I just want to show you its features, customization, and control over HTTP requests.
You might feel it is complex, that we need to do more work than fetch. But remember, as I told you we can also use Axios like with did with fetch. But the way I have written code for you is how we use it to build large applications, by defining Once and using it anywhere we and can be easily maintained and work with different env.
Let me explain you each step by step:
- See Line 3, we have imported Axios as a dependency
- define a base URL to avoid repeating, and later on changing a single variable value change it everywhere. Let’s say you want to move your app from demo/development to production.
- Next, I created an instance named publicInstance, this instance acts separately, which from the name suggested only public API calls. In order to get private data we create a separate instance called privateInstance and set the Authorization header like we set the Base URL.
- In our
getPosts()
function by using try/catch to easily get errors without crashing our app, define our instance which accepts an object of URL (data fetching path) and a method. - The
getPosts()
method uses async/await to make API calls and set data in oursetPosts
state.
3) React Query
React Query is a powerful data-fetching and state management library that handles caching, automatic prefetching, providing request status (loading, success, fetching, error, and more), and many other useful features that we have to manage manually. React Query library is built by TenStack, they build multiple useful and powerful react libraries like these to make work easier and faster. If you’re interested, take a quick start guide of react-query by following this link.
You need to install the react-query as a third-party dependency to your react app to start using it. Use the below command to install react-query, and devtools to see requests in action.
npm i @tanstack/react-query @tanstack/react-query-devtools
ShellScriptHere is an example of how to use React Query:
import React from 'react'; import { useQuery } from 'react-query'; import axios from 'axios'; const fetchPosts = async () => { const { data } = await axios.get('https://jsonplaceholder.typicode.com/posts'); return data; }; export default function PostsListWrapper() { const { data, error, isLoading, isSuccess } = useQuery('posts', fetchPosts); if (isLoading) return <p>Loading...</p>; if (error) return <p>Error fetching data.</p>; return ( <div> <h1>Posts</h1> {data.map((post) => ( <div key={post.id}> <h2>{post.title}</h2> <p>{post.body}</p> </div> ))} </div> ); };
JSXThe above example shows how to request data, but this time we don’t use useEffect()
the hook to call our function at the component mount, instead react-query takes care of all that our us.
There are two main used functions in react-query
- useQuery(): used for getting data from the server.
- useMutate(): used for sending data to the server.
4) SWR
SWR (Stale While Revalidate) is a react hook-based library for making asynchronous calls. This library is created and maintained by Vercel (Company behind Nextjs) It focuses on cache management, revalidation, and minimal API requests.
SWR is a strategy to first return the data from the cache (stale), then send the fetch request (revalidate), and finally come up with the up-to-date data. [by, SWR]
Like react-query, it caches data, revalidates provides request status (loading, success, error). The reason it is recommended is because it is:
- lightweight
- easy syntax
- fast
- provides real-time experience
- and SSR / ISR / SSG ready
You can install SWR using the below command:
npm i swr
ShellScriptLet’s understand it with an example in action:
import React from 'react'; import useSWR from 'swr'; const fetcher = (url) => fetch(url).then((res) => res.json()); export default function PostsListWrapper() { const { data, error, isLoading } = useSWR('https://jsonplaceholder.typicode.com/posts', fetcher); if (isLoading) return <p>Loading...</p>; if (error) return <p>Error fetching data.</p>; return ( <div> <h1>Posts</h1> {data.map((post) => ( <div key={post.id}> <h2>{post.title}</h2> <p>{post.body}</p> </div> ))} </div> ); };
JSXIf you compare the above example with the react-query example you’ll find some matching in Syntex. But both libraries are different in providing solutions.
You can make SWR reusable by creating a custom hook, for example, the above example is taken from the official website just for demo purposes:
function useUser (id) { const { data, error, isLoading } = useSWR(`/api/user/${id}`, fetcher) return { user: data, isLoading, isError: error } } // use it in your component like this: function Avatar ({ id }) { const { user, isLoading, isError } = useUser(id) if (isLoading) return <Spinner /> if (isError) return <Error /> return <img src={user.avatar} /> }
JSXThis example is very helpful in understanding and using SWR in your project.
5) GraphQL with Apollo Client
GraphQL is becoming a new standard for making API calls. It provides efficient data handling and state management.
GraphQL on its own is a big topic, so I’ll try to keep it simple and short. GraphQL is like a query language for APIs, it means instead of RESTful API which provides all the field values and keys, GraphQL allows the frontend to request exactly the data they need in a single request. This reduces the over-fetching and unnecessary data.
Apollo Client on the other hand is a state management library that integrates with GraphQL. It is like a wrapper around GraphQL in our app which simplifies the process of fetching, caching, and managing data in client applications. It works with many different frameworks like React, Vue, Angular, and others. See the Full list of supported frameworks.
In order to use it in your react app, install the below command:
npm install @apollo/client graphql
ShellScriptSee Apollo GraphQL in action:
import React from 'react'; import { useQuery, gql } from '@apollo/client'; const GET_POSTS = gql` query GetPosts { posts { id title body } } `; export default function PostsListWrapper() { const { loading, error, data } = useQuery(GET_POSTS); if (loading) return <p>Loading...</p>; if (error) return <p>Error fetching data</p>; return ( <div> <h1>Posts</h1> {data.posts.map((post) => ( <div key={post.id}> <h2>{post.title}</h2> <p>{post.body}</p> </div> ))} </div> ); };
JSXIn the above example, you see a query is defined with the required field keys GET_POSTS variable. The useQuery()
hook from @apollo-client
takes that query and returns data, this object of useQuery() the function also includes data, error, request status, and more useful info.
Great article on the different ways to make API calls in ReactJS! Thanks for breaking it down into understandable methods. I’ve been using Axios quite a bit and agree that its syntax makes things a lot simpler. How would you compare Axios with SWR in terms of handling real-time data?
Thanks again for the helpful overview!
Thanks, i’m happy that this article is so helpful.
Honestly i did’nt dig deeper into SWR, but it’s another great way to make api call in reactjs using hook method.