はじめに
1画面に複数コンテンツがあり、タブをクリックすると選択中のタブと配下のコンテンツが切り替わる機能を実装していきます。
(前提条件)
・Next.jsのプロジェクトを作成済みであること
実装
ディレクトリ構成
(プロジェクトのルート)
┣━ app
┃ ┗━ page
┃ ┗━ page.tsx (表示ページ)
┣━ components
┃ ┗━ tab
┃ ┣━ wrapper
┃ ┃ ┗━ Menu.tsx (タブ)
┃ ┃ ┗━ Contents.tsx (コンテンツを表示するエリア)
┃ ┗━ contents
┃ ┣━ Content1.tsx (コンテンツ)
┃ ┣━ Content2.tsx (〃)
┃ ┗━ Content3.tsx (〃)
┗━ styles
┗━ tabstyle.css (css)
プログラム
page.tsx
'use client';
import Contents from '@/components/tab/wrapper/Contents';
import Menu from '@/components/tab/wrapper/Menu';
import { createContext, useState } from 'react';
export const TabContext = createContext(
{} as {
tabIndex: number;
setTabIndex: React.Dispatch<React.SetStateAction<number>>;
},
);
export default function Page() {
const [tabIndex, setTabIndex] = useState(0);
return (
<>
<TabContext.Provider value={{ tabIndex, setTabIndex }}>
<Contents />
</TabContext.Provider>
</>
);
}
Menu.tsx
import { useContext } from "react"
import "@/styles/tabstyle.css"
import { TabContext } from "@/app/page/page"
export default function () {
const {tabIndex, setTabIndex } = useContext(TabContext)
return (
<>
<div style={{display: "flex"}}>
<div onClick={() =>setTabIndex(0)} className={`tab ${tabIndex === 0 && "selected"}`}>tab1</div>
<div onClick={() =>setTabIndex(1)} className={`tab ${tabIndex === 1 && "selected"}`}>tab2</div>
<div onClick={() =>setTabIndex(2)} className={`tab ${tabIndex === 2 && "selected"}`}>tab3</div>
</div>
</>
)
}
Contents.tsx
import { useContext } from 'react';
import Menu from './Menu';
import { TabContext } from '@/app/page/page';
import Content1 from '../contents/Content1';
import Content2 from '../contents/Content2';
import Content3 from '../contents/Content3';
export default function () {
const { tabIndex, setTabIndex } = useContext(TabContext);
return (
<>
<Menu />
{tabIndex === 0 && <Content1 />}
{tabIndex === 1 && <Content2 />}
{tabIndex === 2 && <Content3 />}
</>
);
}
※Contents2, Content3は数値部分を変えるのみなので省略
Content1.tsx
export default function Content1() {
return <>content1</>;
}
tabstyle.css
.tab {
padding: 0px 10px
}
.tab.selected {
background-color: lightblue;
text-decoration:underline;
}
画面イメージ
最後に
選択中のタブを状態管理するuseState
を親要素にて定義し、子にprops
でstate
をセットする関数を渡す方法もあります。
拡張性も考えると孫要素でもprops
のバケツリレーをせずにstate
を使用できるこちらの方が優れているためuseContext
を採用しました。
ご指摘、コメントあれば是非よろしくおねがいします m(_ _)m