website-logomedcode

Next.js 15 :How to add a like button to Next.js use server-action

Adding a like button to your website can significantly improve user engagement by allowing visitors to interact with your content. In Next.js 15,
alejandro coutinho| November 24, 2024
next.js
Next.js 15 :How to add a like button to Next.js use server-action

#SERVAER-action next.js15 Like-button webdev

Adding a like button in your website encourages user participation and may even increase its level of engagement. The new features of the framework such as server actions in Next.js 15 also facilitate the implementation of one of the main features that is creating a like button. The said article will discuss how such functionality can be achieved with the help of Next.js server actions in a seamless manner for the developers as well as for users.

Understanding Server Actions in Next.js 15

Before diving into the implementation, it’s crucial to understand the concept of server actions in Next.js 15. Server actions allow developers to handle backend operations within the framework itself, providing a simplified way to work with databases, APIs, and server-side functionality.

In Next.js 15, server actions are integrated into the app directory, offering several benefits over traditional methods. These actions provide a seamless approach to tasks like handling form submissions, modifying database entries, and performing other backend tasks without the need for extensive configuration.

Step 1: Install Next.js

npx create-next-app@latest like-button-app

Step 2: Setting Up the Database

To implement a like button, we need a backend to store the like counts. For simplicity, we will use MongoDB as the database. You can install the necessary MongoDB package with the following:

npm install mongoose

Create a model to store the like counts. In the /models directory, create a file named Likes.js:

importmongoosefrom"mongoose";
const { Schema } =mongoose;
constlikesSchema=newSchema(
  {
    blogId: {
      type:String,
      required:true,
    },
    numberOfLikes: {
      type:Number,
      required:true,
    },
  },
  { timestamps:true }
);
constLikes=mongoose.models.likes||mongoose.model("likes", likesSchema);
exportdefaultLikes;

Step 3: Setting Up Server Actions in Next.js 15

1.create action.js file for function on server


import { revalidatePath } from "next/cache";
import Likes from "../module/Likes";

// get Likes

exportconstgetLikes=async (_id) => {
  try {
    connectDb();
    constlikesPost=awaitLikes.findOne({ blogId:_id });
    returnlikesPost;
  } catch (error) {
    console.log(error.message);
    thrownewError("Failed to fetch likes!");
  }
};


exportconstincrementLike=async (_id) => {
  try {
    connectDb();
    constlikesPost=awaitLikes.findOne({ blogId:_id });
    if (likesPost) {
      awaitLikes.updateOne(
        { blogId:_id }, // Filter query
        { $inc: { numberOfLikes:1 } },
        { new:true } // Update operation
      );
      constupdatedDoc=awaitLikes.findOne(
        { blogId:_id }, // Filter query to find the blog by _id
        { numberOfLikes:1, _id:0 } // Projection: only return numberOfLikes
      );
      returnupdatedDoc.numberOfLikes; // Return the updated numberOfLikes value
    } else {
      connectDb();
      constnewLikes=newLikes({ blogId:_id, numberOfLikes:1 });
      awaitnewLikes.save();
      returnnewLikes.numberOfLikes;
    }
  } catch (error) {
    console.log(error);
  }
  revalidatePath("/blogs");
};

Step 4: Setting Up Ui page

create blogPage.jsx for example ui blog page.

note 1: getPostsBySlug() is server function to get Data from database.

import { getPostsBySlug, getLikes } from "@/app/utils/action";
const BlogPage = async ({ params }) => { const { slug } = await params; const blog = await getPostsBySlug((await params).slug); const likesPost = await getLikes(blog._id); return ( <section className="p-16 py-40 w-full grid grid-cols-7 gap-10 xl:gap-8 lg:flex lg:flex-col sm:p-3 sm:py-28 dark:bg-dark"> <div className="myRightSide col-span-5 flex flex-col justify-around dark:bg-dark"> <div className="w-full px-4 mb-1 sm:text-sm sm:mb-2 dark:text-light dark:bg-dark"> <h1 className="hello text-4xl font-bold py-6 pt-6 sm:text-2xl text-mainColor dark:text-light xs:py-1"> {blog.title} </h1> <span className="text-xl text-gray-600 py-3 sm:text-sm xs:text-sm xs:py-1 dark:text-light"> {blog.description} </span> <div className="mt-6"> <div className="flex justify-start py-1"> <div className="flex justify-start items-center dark:bg-dark"> <Link href={`/dashboard/users/${blog.userId}`} className="text-blue-600 text-sm uppercase dark:text-light xs:text-xs" > {blog?.username} </Link> <span className="ml-2 text-sm text-gray-800 font-semibold dark:text-light xs:text-xs"> | {blog?.createdAt} </span> </div> <Link href={`/category/${blog.category}`} className="uppercase text-xs text-gray-800 font-semibold rounded-sm px-2 py-1 ml-2 bg-yellow-400 hover:bg-yellow-300" > {blog.category} </Link> </div> <Image src={blog.image ? blog.image : imageBlog} alt={blog.title} className="w-[1280px] h-auto sm:h-auto object-cover rounded mt-2" width={800} height={400} priority={true} quality={100} /> </div> <h2 className="flex underline font-bold justify-start items-start py-6 xs:py-2 ml-2 mt-1 font-bolder"> {blog.tags} </h2> <div className="py-4 w-full xs:min-w-full" dangerouslySetInnerHTML={{ __html: blog.content}} /> <ReactionBlog totalLikes={totalLikes} BlogId={BlogId} /> </div> </div> </section> ); }; export default BlogPage;

2.create "use client" component ReactionBlog.jsx 

"use client";
import React, { useState } from "react";
import { AiOutlineLike } from "react-icons/ai";
import { BiDislike } from "react-icons/bi";
import ShareButtons from "./ShareButtons";
import { incrementLike } from "../utils/action";

const ReactionBlog = ({totalLikes, BlogId }) => {
  const numberOfLikes = totalLikes?.numberOfLikes;
  const [likes, setLikes] = useState(numberOfLikes ? numberOfLikes : 1);
  const [isClicked, setIsClicked] = useState(false);
  
  return (
<div className="flex flex-col justify-start items-center p-2 border mb-1 rounded-md"> <div className="flex"> <button onClick={async () => { if (!isClicked) { const updatedLikes = await incrementLike(BlogId); setLikes(updatedLikes); setIsClicked(true); } }} className={`${ isClicked ? "bg-mainColor" : "bg-transparent" }py-2 px-10 hover:text-mainColor hover:scale-105 hover:shadow text-center border border-gray-300 rounded-md h-8 text-sm flex items-center gap-1 lg:gap-2`} > <AiOutlineLike className={`w-5 h-5 ${isClicked ? "fill-mainColor" : ""}`} /> <span>{likes}</span> </button> </div> </div> )}; export default ReactionBlog;

## Conclusion:

adding a Like button to your Next.js website using Server Actions is a great way to enhance user interaction and engagement. By following the steps outlined in this blog post, you can easily implement this feature and provide a seamless user experience. Happy coding!


Explore the latest insights, articles,free components, and expert advice on programming and software development

© Copyright 2024 MED DAKIR. All rights reserved./privacy policyTerms & Conditions