1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Next.jsでのカルーセル機能の実装

Last updated at Posted at 2024-10-09

はじめに

カルーセルとは、まるでページをめくるように、複数のコンテンツをスライド形式で楽しむことができる機能のことです。
← 1/20 → みたいなやつです
ページネーションとも言います。

今回は、Next.jsを用いて、そんなカルーセル形式でブログ記事を表示する機能を実装してみました。

データの準備

まずは、展示するブログの記事データを用意します。タイトルやURL、日付、そして説明文を含むオブジェクトの配列を作成しました。これらのデータは、まるで個々のストーリーが集まった小さな宇宙のように、カルーセルの中で輝きます。

export const blogs = [
  {
    title: "ブログタイトル1",
    url: "https://example.com/blog1",
    date: "2024-01-01",
    description: "ブログ1の説明文",
  },
  // 他のブログデータ...
];

Blogコンポーネントの実装

次に、実際にカルーセル機能を持ったBlogコンポーネントを作成します。

"use client";
import React, { useState } from "react";
import { AiFillBook } from "react-icons/ai";
import BlogCard from "./BlogCard"; // ブログカードを表示するコンポーネント
import { blogs } from "../constants/blogs"; // ブログデータ
import { AnimatePresence } from "framer-motion";
import { AiOutlineLeft, AiOutlineRight } from "react-icons/ai"; // 矢印アイコン

function Blog() {
  const blogsPerPage = 4; // 1ページに表示するブログの数
  const [currentPage, setCurrentPage] = useState(1); // 現在のページ番号

  const totalPages = Math.ceil(blogs.length / blogsPerPage); // 全ページ数

  // 現在のページに表示するブログを取得
  const startIndex = (currentPage - 1) * blogsPerPage;
  const currentBlogs = blogs.slice(startIndex, startIndex + blogsPerPage);

  // ページ変更のハンドラー
  const handleNextPage = () => {
    if (currentPage < totalPages) {
      setCurrentPage(currentPage + 1);
    }
  };

  const handlePrevPage = () => {
    if (currentPage > 1) {
      setCurrentPage(currentPage - 1);
    }
  };

  return (
    <section className="w-full h-fit px-[40px] py-10 max-xs:px[20px] relative bg-white" id="blog">
      <div className="max-w-7xl mx-auto">
        <div className="inline-block pb-4 pt-4">
          <p className="bg-hotpink text-white text-sm font-medium py-3 px-5 rounded-full flex items-center gap-2">
            <span><AiFillBook className="w-4 h-4" /></span>
            ブログ
          </p>
        </div>

        <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 max-w-[1200px] mx-auto">
          <AnimatePresence>
            {currentBlogs.map((blog, index) => (
              <BlogCard
                key={index}
                title={blog.title}
                url={blog.url}
                date={blog.date}
                description={blog.description}
              />
            ))}
          </AnimatePresence>
        </div>

        <div className="flex justify-between items-center mt-4">
          <button
            onClick={handlePrevPage}
            disabled={currentPage === 1}
            className={`${currentPage === 1 ? "opacity-50 cursor-not-allowed" : ""} bg-gray-300 text-gray-700 px-3 py-1 rounded-md`}
          >
            <AiOutlineLeft />
          </button>

          <div className="text-center">
            <p className="text-sm">Page {currentPage} of {totalPages}</p>
          </div>

          <button
            onClick={handleNextPage}
            disabled={currentPage === totalPages}
            className={`${currentPage === totalPages ? "opacity-50 cursor-not-allowed" : ""} bg-gray-300 text-gray-700 px-3 py-1 rounded-md`}
          >
            <AiOutlineRight />
          </button>
        </div>
      </div>
    </section>
  );
}

export default Blog;

このコードでは、1ページあたり4つのブログ記事を表示し、ページネーションを通じてユーザーが簡単に次の記事にアクセスできるようにしています。

まとめ

今回は、Next.jsを用いてブログ記事をカルーセル形式で表示する機能を実装しました。これにより、ユーザーはスムーズに情報を探し出し、新たなインスピレーションを受け取ることができます。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?