はじめに
ブログサイトを作る過程で学んだことを、備忘録目的で投稿しています。
自身は駆け出しエンジニアであり、React自体がほぼ初学者のため、誤った認識・理解をしている可能性があります。
万が一参考にする場合は、上記の点を考慮した上でご一読ください。
また、スタイリングについては割愛しています。
この記事は、過去に投稿したNext.js × microCMSでブログサイト作成した際に学んだことを書き留めるのプロジェクトを元に説明しています。
目的
記事詳細ページにて、Qiitaのような目次を実装する。
作業環境
Windows10 Pro x64
Node.js: 20.14.0
npm: 10.3.0
Next.js: 14.2.3(App Router使用)
手順
実装にあたりTocbot
というライブラリを使用します。
まずはインストールします。
npm install --save tocbot
Tocbot
を呼び出すファイルと、それを使用するTocBox
コンポーネントを作成します。
useEffect
を使用するためサーバーレンダリングではなく、クライアントレンダリングにする必要があります。("use client"
)
下記だと、.toc
の子要素に<nav className="toc"></nav>
が追加されます。
"use client";
import { useEffect } from "react";
import tocbot from "tocbot";
export const Toc = () => {
useEffect(() => {
tocbot.init({
tocSelector: ".toc", // 目次を追加する class 名
contentSelector: ".target-toc", // 目次を取得するコンテンツの class 名
headingSelector: "h2, h3, h4", // 目次として取得する見出しタグ
headingsOffset: 100, // 見出しのオフセット
scrollSmoothOffset: -40, //スムーススクロールのオフセット
});
// 不要となったtocbotインスタンスを削除
return () => tocbot.destroy();
}, []);
return <nav className="toc" />;
};
import styles from "./index.module.scss";
import { Toc } from "@/libs/tocbot";
export const TocBox = () => {
return (
<>
<p className={styles.title}>目次</p>
<Toc />
</>
);
};
作成したTocBox
コンポーネントを詳細ページで呼び出します。
import Image from "next/image";
import parse from "html-react-parser";
import styles from "./page.module.scss";
import { getArticlesDetail } from "@/libs/microcms";
import { TocBox } from "@/components/TocBox"; // 追加
export default async function Page({ params }) {
const article = await getArticlesDetail(params.slug);
return (
<main className={styles.main}>
<div className={styles.container}>
<div className={styles.article}>
<p className={styles.thumbnail}>
<Image
src={article.thumbnail.url}
alt={article.title}
height={article.thumbnail.height}
width={article.thumbnail.width}
priority
/>
</p>
<h1 className={styles.title}>{article.title}</h1>
<p className={styles.category}>{article.category.name}</p>
<div className={`${styles.body} target-toc`}>
{parse(article.body)}
</div>
</div>
{/* 追加 */}
<div className={styles.toc}>
<TocBox />
</div>
</div>
</main>
);
}
目次が設置できました。
要素を検証すると、見出しレベル毎にクラス名が割り振られていたり(例:node-name--H2
)、アクティブの見出しにもクラス名が付与されていたりなど(例:is-active-link)、スタイル調整がしやすくなっています。
また、目次内のリンクをクリックすると、該当箇所までスムーススクロールしてくれます。
さいごに
理想は目次もSSGに対応させたかったのですが、今の自分の力量では実現できず断念しました。
Tocbot
はオプションも充実しているのでとても使いやすかったです、ぜひ使用してみてください、
参考