An Interest In:
Web News this Week
- March 21, 2024
- March 20, 2024
- March 19, 2024
- March 18, 2024
- March 17, 2024
- March 16, 2024
- March 15, 2024
SWR - An awesome react hooks for data fetching
Data fetching is an integral part of every application we build. In modern web development we deal with a lot of data-fetching mechanisms to fetch data from a web server. We generally store this data in a state of our application.
The question would arise: what happens when we refresh the page? The data should be repeatedly retrieved or persisted if it is not then we would definitely get a blank page. This is usually handled in our application with the API calls inside our useEffect() hook, componentDidMount() or write custom fetch Hook instead.
In this article we will learn about useSWR hook which is a library we can use that handles all heavy lifting tasks for us not just data fetching but even data revalidation, caching, data pagination, page focus, data refresh, realtime, handling errors and lot more.
What is SWR?
SWR is a React Hooks, a fast and lightweight library built by Vercel, the name comes from the term stale-while-revalidate. A HTTP cache invalidation strategy popularized by HTTP RFC 5861. SWR is a strategy to first return the data from cache (stale), then send the fetch request (revalidate), and finally come with the up-to-date data.
SWRs useSWR(key, fetcher, options) is a Hook that retrieves data asynchronously from a URL with the aid of a fetcher function, both passed as arguments to the Hook. The key argument here is the URL in string format, and the fetcher is either a function declared in the global configuration, a predefined custom function, or a function defined as the useSWR() argument.
By default, useSWR() returns the data received, a validation request state, a manual revalidate argument, and an error, if there are any. This can be easily done by setting the Hook to a destructurable object variable:
const { data, isValidating, revalidate, error } = useSWR(key, fetcher)
We will definitely take a look into the arguments it takes in our demo application here. In this tutorial we will only focus on stale-while revalidate feature useSWR provides us. We will see the difference in normal fetch/axios API calls and implementation of useSWR hook.
Project Installation
Lets create a simple next project and give it a name of useswr-demo.
npx create-next-app useswr-demo
After project creation we will spin up a local server by connecting a database with MongoDB cloud and create a fresh cluster there. We will grab the connection string from the MongoDB and paste it inside of our .env.local file. You can also check the .env.example file for reference.
Lets install vercel/node and mongodb with the command below.
npm i mongodb @vercel/node
We will now head into our api directory and create a new folder called lib. Inside there we will create a database.js file where we will add some function to connect with our mongoDB.
const MongoClient = require("mongodb").MongoClient;let cachedDb = null;export const connectToDatabase = async () => { if (cachedDb) { console.log("Using existing DB connection"); return Promise.resolve(cachedDb); } return MongoClient.connect(process.env.MONGODB_URI, { native_parser: true, useUnifiedTopology: true, }) .then((client) => { let db = client.db("truskin-storage"); console.log("New DB Connection"); cachedDb = db; return cachedDb; }) .catch((error) => { console.log("Mongo connect Error"); console.log(error); });};
We have now created a connection function we can readily use inside of our application. Lets create a new file and call it todo.js inside of api folder. Inside there we will import our connectTODatabase function we exported before. For the demo purpose we will just add two endpoints to achieve this GET and POST just to add simplicity
// Import Dependenciesimport { connectToDatabase } from '../lib/database';module.exports = async (req, res) => { const db = await connectToDatabase(); if (req.method === 'GET') { const collection = await db.collection('todos'); const todos = await collection.find({}).toArray(); res.status(200).json({ todos }); } else if (req.method === 'POST') { const newtodo = req.body; const collection = await db.collection('todos'); const todos = await collection.insertOne(newtodo); res.status(200).json({ todos, status: 'API called sucessfully' }); } else { res.status(404).json({ status: 'Error route not found' }); }};
Lastly before we can use our endpoints we created we will need to create a vercel.json file to make it work smooth
{ "env": { "MONGODB_URI": "@mongodb-ur" }, "headers": [ { "source": "/(.*)", "headers": [ { "key": "Access-Control-Allow-Origin", "value": "*" } ] } ] }
Now if we visit our route http://localhost:3000/api/todos
You must see an empty array returned to you. Currently we do not have any todos added.
Lets compare the use of useSWR react hook and without the use of useSWR hook and see how our application behaves.
Without useSWR
We will start off by making the use of index.js file inside of our api folder. Lets first install axios for making our API calls.
npm i axios
We can import the Axios library and make a normal API call inside of our application.
import Head from 'next/head';import Image from 'next/image';import axios from 'axios';import styles from '../styles/Home.module.css';export default function Index(props) { const todoList = props.data; return ( <div className={styles.container}> <Head> ... </Head> <main className={styles.main}> <ul> {todoList.map((todo, index) => ( <li key={index}> <a>{todo.task}</a> </li> ))} </ul> </main> <footer className={styles.footer}> ... </footer> </div> );}export const getStaticProps = async () => { const res = await axios.get('http://localhost:3000/api/todos'); return { props: { data: res.data.todos }, };};
This is a simple way to make a call to our API. For demo purpose I will bring in Postman and send a POST request to our endpoint
http://localhost:3000/api/todos
We will get a success status and we can see the reflection inside of our MongoDB collection. Lets simulate the changes in the database by manually deleting a document. If we come back to our application
http://localhost:3000
We won't see any changes unless we refresh the page. Well this is the main concept we are trying to look into: how can we revalidate the stale data and update our UI. Lets solve this problem by implementing the useSWR hook.
With useSWR
Lets first install our library with the following command. We will make the use of both useSWR and axios to see this in action. But you can simply achieve this with just useSWR only.
npm install swr
We will create a new file todo.js inside of pages and do the same we did before but with useSWR library which looks something like this.
import axios from 'axios';import useSWR from 'swr';import styles from '../styles/Home.module.css';export default function Users() { const address = 'http://localhost:3000/api/todos'; const fetcher = async (url) => await axios.get(url).then((res) => res.data.todos); const { data, error } = useSWR(address, fetcher, { revalidateOnFocus: false, // auto revalidate when the window gets focused }); if (error) <p>Loading failed...</p>; if (!data) <h1>Loading...</h1>; return ( <div> <main className={styles.main}> <div className="container"> {data && ( <ul> {data.map((todo, index) => ( <li key={index}> <a>{todo.task}</a> </li> ))} </ul> )} </div> </main> </div> );}
For demo purpose I will bring in Postman and test a POST request to our endpoint
http://localhost:3000/api/todos
We will get a success status and we can see the reflection inside of our MongoDB collection. Lets simulate the changes in the database by manually deleting a document. If we come back to our application
http://localhost:3000/todos
We can now see our UI has been updated with fresh data. We did not have to refresh the page to re-fetch the new data. And, weve done it! There we have a very barebones example of using SWR with Axios to update our stale data inside of our UI.
Note: You still can use the mutate function to refresh local state data so for example 2 we are sending data to the server but the local state data is not updated. The mutate function refreshes local state data based on the initial endpoint . For more information you can refer to the document here(https://swr.vercel.app/docs/mutation).
Conclusion
In conclusion, useSWR Hook can be a great choice for data fetching in React. I hope this article has provided you some insight into fetching data in Next.js applications with useSWR. We just scratched the surface. We still have a lot more features this library offers us with. Its caching, pagination and auto refetching can enhance user experience. Moreover, it's lightweight and backend agnostic, which allows fetching data from any kind of API or database quickly and easily.
Thank you for reading. Please find the Github repo in the link here.
Please refer to the official documentation for more details.
Happy coding!
Original Link: https://dev.to/ishanme/swr-supercool-react-hooks-for-data-fetching-4l4b
Dev To
An online community for sharing and discovering great ideas, having debates, and making friendsMore About this Source Visit Dev To