Creating Optimistic Updates in UI with React.js’s new useOptimistic Hook and Next.js 13.4 Server Action

dickinsontiwari - Oct 14 '23 - - Dev Community

Optimistic updates are a powerful technique in modern web development, especially when it comes to improving the user experience. By updating the user interface optimistically, you can make the app feel more responsive and smooth, even when there’s a slight delay in the server response. In this article, we’ll explore how to implement optimistic updates using React.js’s new useOptimistic hook in combination with Next.js 13.4's server action. We'll build a "Like" button functionality for tweets as an example to demonstrate this technique.

Prerequisites

Before we begin, make sure you have the following installed:

  • Node.js (with npm or yarn) and a code editor of your choice.
  • React.js and Next.js installed in your project.

Setting Up the Project

Assuming you already have a Next.js project set up with the necessary files, let’s proceed to implement the optimistic “Like” functionality.

Step 1: Server Action for Like

First, we need to implement the server action to handle the like functionality. In this example, we’ll use a simple database (db) with two schema tables: tweets and likes. The likes table will store the username and tweet_id for the likes. Below is the code for the server action located in ../actions/tweetLike.ts:

// ../actions/tweetLike.ts  

import { db } from "../db";  
import { likes, tweets } from "../db/schema";  
import { revalidatePath } from "next/cache";  
import { eq } from "drizzle-orm";  
import { currentUser } from "@clerk/nextjs";  

export default async function tweetLike(tweet_id: string, Clikes: number) {  
  const user = await currentUser();  
  const tweetPost = await db  
    .update(tweets)  
    .set({ likes: Clikes + 1 })  
    .where(eq(tweets.id, BigInt(tweet_id)));  
  const liked = await db  
    .insert(likes)  
    .values({ tweet_id: BigInt(tweet_id), username: user?.username });  
  revalidatePath("/app");  
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Creating the Optimistic “Like” Button

Now, let’s create the “Like” button component using React.js’s useOptimistic hook. We'll name this component LikeButton and place it in ../components/LikeButton.tsx:

// ../components/LikeButton.tsx  

import { experimental_useOptimistic as useOptimistic } from "react";  
import tweetLike from "../actions/tweetLike";  

export default function LikeButton({  
  likes,  
  tweet_id,  
}: {  
  likes: number | null;  
  tweet_id: any;  
}) {  
  const [optimisticLikes, addOptimisticLikes] = useOptimistic(  
    likes || 0, // Default to 0 likes if null  
    (state, l) => state + 1  
  );  

  return (  
    <div className="flex items-end space-x-3">  
      <svg  
        viewBox="0 0 24 24"  
        aria-hidden="true"  
        fill="#f43f5e"  
        onClick={async () => {  
          addOptimisticLikes(1); // Optimistically increment the like count  
          await tweetLike(tweet_id, optimisticLikes); // Call the server action  
        }}  
        className="r-1gfgf0w r-4qtqp9 r-yyyyoo r-z80fyv r-dnmrzs r-bnwqim r-1plcrui r-lrvibr r-19wmn03 text-blue-500 fill-blue-500 w-6 h-6 cursor-pointer"  
      >  
        {/* SVG code for Like button */}  
      </svg>  
      <span className="text-sm opacity-60">{Number(optimisticLikes)}</span>  
    </div>  
  );  
}
Enter fullscreen mode Exit fullscreen mode

In the LikeButton component, we use the useOptimistic hook to create the optimisticLikes state variable, which holds the optimistic number of likes. The hook takes an initial value (likes prop or 0) and an updater function that increments the state by 1.

When the user clicks the “Like” button, we call the addOptimisticLikes function to optimistically increase the like count. Next, we call the tweetLike server action, passing the tweet_id and the optimistic like count. The server action will handle the actual like process, and in the response, we'll get the updated like count.

Conclusion

In this article, we explored how to create optimistic updates in the UI using React.js’s new useOptimistic hook and Next.js 13.4's server action. By implementing optimistic updates, we can enhance the user experience by making the app feel more responsive and smooth. In the example of a "Like" button for tweets, we showed how to increment the like count optimistically and update it on the server using the provided server action.

Optimistic updates can be used in various scenarios to provide a better user experience and reduce perceived latency in web applications. However, keep in mind that it’s essential to handle potential discrepancies between the optimistic UI and the server’s actual state. In some cases, you may need to handle errors or roll back optimistic updates if the server response indicates a failure.

By combining React.js’s new useOptimistic hook with Next.js's server action, you can take advantage of these powerful features to create a seamless and responsive user interface in your web applications.

. . . . .
Terabox Video Player