Creating Optimistic Updates in UI with React.js’s new useOptimistic Hook and Next.js 13.4 Server Action
Tags: react, nextjs, tailwindcss, twitter
Published: 2023-10-14 11:48:56

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`:
```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");  
}
```
## 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`:
```ts
// ../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>  
  );  
}
```
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.

{% embed http://www.youtube.com/watch?v=Fs_UqcxB68M %}

## 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.