Chakra UIのTabsをnext.jsでURL同期させる

1 min read読了の目安(約1600字

Chakra UIのTabsを利用した際、このタブ切り替えとURLを同期したくなったので、next.jsとの組み合わせでまとめる

ファイル名は/tabs/[[...path]].tsxとして、パスをすべて拾うようにする。[1]

/* /tabs/[[...path]].tsx */

import { Box, Tab, TabList, TabPanel, TabPanels, Tabs } from "@chakra-ui/react"
import React, { FC } from "react"
import { useRouter } from "next/router"
import { GetServerSideProps } from "next"
const tabMap = [
  "dog", "cat"
]
const Page: FC<{ path: string }> = ({ path }) => {
  const initialTab = Math.max(tabMap.indexOf(path), 0) // path値から初期タブを決定
  const router = useRouter()

  return <Box>
    <Tabs
      onChange={(idx) => {
        // タブが変更されたらrouterへpush。
        router.push({
          pathname: router.pathname,
          query: {
            path: [tabMap[idx]]
          }
        }, undefined, { shallow: true }) // shallowすることでrouterを再度呼び出さない
      }}
      defaultIndex={initialTab}
    >
      <TabList>
        <Tab>
          {tabMap[0]}
        </Tab>
        <Tab>
          {tabMap[1]}
        </Tab>
      </TabList>
      <TabPanels>
        <TabPanel>
          🐶
        </TabPanel>
        <TabPanel>
          🐱
        </TabPanel>
      </TabPanels>
    </Tabs>
  </Box>
}

export const getServerSideProps: GetServerSideProps = async (req) => {
  const path = req.query.path?.[0] ?? null
  return {
    props: { path }
  }
}

export default Page
  • useRouterからpathを取得するなどでも良かったが、getServerSidePropsからパスを取得するようにした。
  • onChangeで変更があった際にshallowでpushする
  • nextjs以外なら、history.pushstateを使うことになるだろう
脚注
  1. [[...path]]については この記事にまとめたので参照のこと ↩︎