Using SWR React Hooks With Next.js’ Incremental Static Regeneration (ISR)

If you’ve ever used Incremental Static Regeneration (ISR) with Next.js, you may have found yourself sending stale data to the client. This occurs when you are revalidating the page on the server. For some websites this works, but for others (such as Hack Club’s Scrapbook, a site built by @lachlanjc that I help maintain), the user expects the data to be kept up to date.

The first solution that comes to mind may be to simply server side render the pages, ensuring that the client is always sent the most up to date data. However, fetching large chunks of data before rendering can slow down the initial page load. The solution used in Scrapbook was to use the SWR library of React hooks to update the cached page from the server with client side data fetching. This approach ensures that users still have a good experience, that the site is fast and that the data is kept up to date.

Meet SWR

SWR is a React Hooks library built by Vercel, the name comes from the term stale-while-revalidate. As the name suggests, your client will be served stale/old data whilst the most up to date data is being fetched (revalidating) through SWR on the client side. SWR does not just revalidate the data once, however, you can configure SWR to revalidate the data on an interval, when the tab regains focus, when a client reconnects to the Internet or programmatically.

When paired with ISR and Next.js’ API routes, SWR can be used to create a responsive user experience. The client is first served the cached statically generated page (generated with getStaticProps()), in the background the server also begins the process of revalidating that page (read more here). This process feels fast for the client and they can now see the set of data, however it may be a touch out of date. Once the page is loaded, a fetch request is made to an Next.js API route of your’s which returns the same data as what was generated with getStaticProps(). When this request is completed (assuming it was successful), SWR will update the page with this new data.

Let’s now look back at Scrapbook and how this helped solve the problem of having stale data on the page. The obvious thing is that now, the client gets an updated version. The more interesting thing, however, is the impact on the speed of our side. When we measure speed through Lighthouse, we get a speed index of 1.5 seconds for the ISR + SWR variant of the site and 5.8 seconds for the Server Side Rendering variant (plus a warning regarding initial server response time). That’s a pretty stark contrast between the two (and it was noticeable when loading the pages up as well). But there is also a tradeoff, on the Server Side Rendered page the user didn’t have the layout of the site change after a couple of seconds with new data coming in. Whilst I believe Scrapbook handles this update well, it’s an important consideration when designing your user’s experience.

Where To Use SWR (And Where Not To)

SWR can be put in place in a variety of places, here are a couple of site categories where SWR would make a great fit:

  • Sites with live data that require updating at a rapid pace.
    Examples of such sites would be sports score sites and flight tracking. When building these sites, you’d look to use the revalidate on interval option with a low interval setting (one to five seconds).
  • Sites with a feed style of updates or posts that update in realtime.
    The classic example of this would be the news sites which have live blogs of events such as elections. Another example would be the aforementioned Scrapbook as well. In this case, you’d also likely want to use the revalidate on interval option but with a higher interval setting (thirty to sixty seconds) to save on data usage and prevent unnecessary API calls.
  • Sites with more passive data updates, that people keep open in the background a lot.
    Examples of these sites would be weather pages or in the 2020s COVID-19 case number pages. These pages don’t update as frequently and therefore don’t need the constant revalidation of the previous two examples. However, it would still enhance the user experience for the data to update. In these cases, I would recommend revalidating the date when the tab regains focus and when a client reconnects to the internet, that’ll mean if a person anxiously returns to the tap hoping there has only been a small increase in COVID cases they’ll get that data quickly.
  • Sites with small pieces of data that users can interact with.
    Think the Youtube Subscribe Button, when you click subscribe you want to see that count change and feel like you’ve made a difference. In these cases, you can revalidate the data programmatically using SWR to fetch the new count and update the displayed amount.

One thing to note, is that these can all be applied with or without ISR.

There are of course some places where you won’t want to use SWR or to use SWR without ISR. SWR isn’t much use if your data isn’t changing or changes very rarely and instead can clog up your network requests and use up mobile user’s data. SWR can work with pages requiring authentication, however you will want to use Server Side Rendering in these cases and not Incremental Static Regeneration.

Using SWR With Next.js And Incremental Static Regeneration

Now we’ve explored the theory of this strategy, let’s explore how we put it into practise. For this we’re going to build a website that shows how many taxis are available in Singapore (where I live!) using this API provided by the government.

Project Structure

Our project will work by having three files:

  • lib/helpers.js
  • pages/index.js (our frontend file)
  • pages/api/index.js (our API file)

Our helpers file will export a function (getTaxiData) that will fetch the data from the external API, and then return it in an appropriate format for our use. Our API file will import that function and will set it’s default export to a handler function that will call the getTaxiData function and then return it, this will mean sending a GET request to /api will return our data.

We’ll need this ability for SWR to do client-side data fetching. Lastly, in our frontend file we’ll import getTaxiData and use it in getStaticProps, it’s data will be passed to the default export function of our frontend file which will render our React page. We do this all to prevent code duplication and ensure consistency in our data. What a mouthful, let’s get started on the programming now.

The Helpers File

We’ll begin by creating the getTaxiData function in lib/helpers.js:

export async function getTaxiData(){
    let data = await fetch("https://api.data.gov.sg/v1/transport/taxi-availability").then(r => r.json())
    return {taxis: data.features.properties[0].taxi_count, updatedAt: data.features.properties[0].timestamp}
}

The API File

We’ll then build the handler function in api/index.js as well as importing the getTaxiData function:

import { getTaxiData } from '../../lib/helpers'
export default async function handler(req, res){
    res.status(200).json(await getTaxiData())
}

There isn’t anything here unique to SWR or ISR, besides the aforementioned project structure. That stuff starts now in index.js!

The Front-End File

The first thing we want to do is create our getStaticProps function! This function will import our getTaxiData function, use it and then return the data with some additional configuration.

export async function getStaticProps(){
    const { getTaxiData } = require("../lib/helpers")
    return { props: (await getTaxiData()), revalidate: 1 }
}

I’d like to focus on the revalidate key in our returned object. This key practically enables Incremental Static Regeneration. It tells your host that every one second regenerating the static page is an available option, that option is then triggered in the background when a client visits your page. You can read more about Incremental Static Regeneration (ISR) here.

It’s now time to use SWR! Let’s import it first:

import  useSWR from 'swr'

We’re going to be using SWR in our React-rendering function, so let’s create that function:

export default function App(props){
}

We’re receiving the props from getStaticProps. Now we’re ready to set up SWR:

const fetcher = (...args) => fetch(...args).then(res => res.json())
const { data } = useSWR("/api", fetcher, {initialData: props, refreshInterval: 30000})

Let’s break this down. Firstly, we define the fetcher. This is required by SWR as an argument so that it knows how to fetch your data given that different frameworks etc. can have different set ups. In this case, I’m using the function provided on the SWR docs page. Then we call the useSWR hook, with three arguments: the path to fetch data from, the fetcher function and then an options object.

In that options object, we’ve specified two things:

  • the initial data
  • the interval at which SWR should revalidate the data

The initial data option is where we provide the data fetched from getStaticProps which ensures that data is visible from the start. Lastly, we use object destructuring to extract the data from the hook.

To finish up, we’ll render that data with some very basic JSX:

return <div>As of {data.updatedAt}, there are {data.taxis} taxis available in Singapore!</div>

And, we’ve done it! There we have a very barebones example of using SWR with Incremental Static Regeneration. (The source of our example is available here.)

If you ever run into stale data with ISR, you know who to call: SWR.

Further Reading on SmashingMag

How To Run Ads On Twitch

One of my client ask me to run ads on Twitch as he is broadcusting content on Twitch. I don't have any idea how can I do this. Anyone here can help. Thanks in advance.

10 Robust Enterprise-Grade ELT Tools To Collect Loads of Data

Enterprises in 2021 deal with a massive amount of data on a regular basis. The Global Data Fabric market analysis says, "businesses that use insights from data extraction will earn $1.8 Trillion by the end of 2021". With such great amounts of data, it is becoming increasingly hard to maintain and categorize the collected data. Moreover, manually processing the data only became more time-consuming and monotonous. With rapid technological advancements, companies are finding ways to find even the slightest advantages to be the best in the market.  Hence, adopting the right ELT tools/platform can greatly contribute to enterprise productivity. ELT tools can collect data, segregate the data based on common characteristics and provide clear-cut insights about the collected data. 

Below is a list of the 10 enterprise-grade ELT tools that I rate above 4 (out of 5).  These can provide great advantages to enterprises that adopt them.

How do I choose a router for my home?

The web interface of a router automatically sets the language for your device according to the Time zone a user sets. English is the common default language chosen for most countries. You can also change the language of your router through the Basic homepage of the routerlogin.net interface. When you are done changing the language, click on the Confirm button, refresh the current page and the page refreshes with the language you selected.
https://19216811netgear.net/

How do I setup my tp-link router for the first time?

Sometimes, the IP address of the router automatically changes. The default IP address of the Tp-link router is 192.168.1.1 with which a user can access the web interface of the tplinkwifi.net window. If for some reason the IP address has changed or your network manager has changed it, you can assign a new IP address to the router using the web management window. Sometimes, a user fails to interact with the web interface of the router through the tplinkwifi.net link, he can also type 192.168.1.1 as an alternative to access its web interface.
https://tplinkroutersetup.net/

How do I log into my Roku account?

Adding the channels from the Roku Channel store is one of the significant processes that every user must know to utilize his Roku Streaming Device to its utmost level. A user can simply add or remove channels with the help of the Roku Remote. You need to search for the required channel in the Streaming Channels option then have to type the name of it and have to wait until the results of the search channel doesnt appear on the screen. You can do it directly through the Roku remote without going through the Roku login screen.
https://rokulogin.com/

Why You Must Experience Orbi Login At Least Once In Your Lifetime?

To create a separate network from the main router, a user has to activate the Guest network using the orbilogin.com interface. You can use the Guest network to allow visitors to access the Internet connection. At the same time, you can deny them from accessing the files and documents within the network. Make sure you assign different SSID names to each frequency band in the network before the configuration process of the Guest network.
https://orbillogin.net/

The Millionaire Guide On Dlinkrouter.local To Help You Get Rich?

A user can change the Routers IP address using the web interface of the Dlink router. Go to the Router Settings tab of the Advanced option and assign a new IP address through the IP address field. The IP address that a user will configure using the IP address option will be used to access the default web interface of the dlinkrouter.local window. You may also have to adjust the network settings of your computer to access the network of the router.
https://dlink-router-local.com/

What I Wish Everyone Knew About Router.asus.com.

A user can register an ASUS device either using a mobile number or using a valid Gmail id. If you want to choose the Gmail option choose the Register with email option from the Sign-in page and if you want to register through a phone number, choose the Register with mobile number option. When a user is done filling up information on the required fields, a verification link will be sent to your registered mail. You need to click the verification link sent to your mail id to activate your router.asus.com account.
https://wwwrouterasus.com/

Learn From These Mistakes Before You Learn Re.rockspace.local.

Sometimes when the memory of a browser gets piled up with the browsing and download history, it may deny a user from interacting with the re.rockspace.local interface. A user is recommended to always clean up the cache memory or history of the browser through the settings option to avoid the web management issue. You also need to make sure that you are entering the correct login credentials on the login window.
https://rerockspace-local.net/

The Biggest Contribution Of Tplinkwifi.net To Humanity.

A user having a wireless connection issue on a Tp-link router has to ensure that the Internet is not dropping from the network connection side. Keep your Tp-link router away from the ovens, refrigerators, Bluetooth devices, and other electronic devices that may cause an interruption in the tplinkwifi.net network. Try Switching to the Wired connection if the issue is not resolving. Connect the router to the computer via Ethernet cable.
https://tp-tplinkwifinet.com/

How do I setup my Amped Wireless Extender?

Only users with the correct Wireless settings can connect to your routers network. Until or unless a network is open, no user can connect to a routers network if he doesnt have the correct wireless credentials. Wireless credentials of a network consisting of the SSID name and Wi-fi password used by a user to connect to the routers network. You can also hide the network name from the Wi-fi list using the Hide SSID option from the Wireless settings of the setup.ampedwireless.com interface.
http://setupampedwireless.info

5 Common Mistakes Everyone Makes In Myrouter.local.

Guest Network is a smart way to allow guests in your home to use the Internet connection without allowing them to access personal documents, files, and information within the network. If your friends come to your home, they can access the routers network but cannot access the shared files in your network. A user doesnt have to type the Wi-fi password to connect to your network using the Guest Network. It is similar to the Wi-fi connection that is used in cafes and hotels. The Guest network is automatically enabled during the myrouter.local setup process.
https://myrouterlocalcom.net/

Limit Communication Between Microservices With Kubernetes Network Policies

Security is an important concern for microservices applications. Although security is a broad topic, I want to zoom into a critical aspect: limiting communication between microservices. By default, microservices platforms such as Kubernetes allow unconstrained communication between services. However, to prevent a few compromised services from affecting all the services on the platform, a microservices platform needs to limit the interactions between services. This constraint is enforced by creating network policies in Kubernetes. Network policies allow you to specify which services can communicate with each other and which services can't. For example, you can specify that a service can only communicate with other services in the same namespace with a network policy.

A Kubernetes cluster needs a network controller to enforce the network policies. The network controller is a special pod that runs on every node in the cluster (a.k.a., DaemonSet). It monitors the network traffic between services and enforces the network policies.