0
0

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】シンプルなタブ切り替えの実装

Posted at

はじめに

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;
}

画面イメージ

タブを押すと選択中のタブとコンテンツが切り替わります。
image.png

最後に

選択中のタブを状態管理するuseStateを親要素にて定義し、子にpropsstateをセットする関数を渡す方法もあります。

拡張性も考えると孫要素でもpropsのバケツリレーをせずにstateを使用できるこちらの方が優れているためuseContextを採用しました。

ご指摘、コメントあれば是非よろしくおねがいします m(_ _)m

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?