テーブルの行リンクは意外と面倒くさい
はじめに
Next.js にて下記のようなテーブルを作成する際に、テーブルの各行をリンク化させつつ特定のセルをクリッカブル(例だと編集モードにして編集作業を行うイメージ)にするのが面倒くさかったので愚痴っていきたいと思います。
結論
テーブルにて行リンクが本当に必要か再検討すべし。
どうしても必要なら
- 色々と制約ついてしまうけど行リンクをやめてプログラムによる画面遷移にする
- div タグを用いて行リンクを実現させつつ(CSS グリッドを用いる)、テーブルを構築する
のどちらかで実装するのが良さそう
'use client'
import { useRouter } from 'next/navigation'
const Table = () => {
...
const router = useRouter()
const handleRowClick = (row) => {
router.push(`/use-cases/${row.original.id}`);
}
return (
...
<tr onClick={()=> handleRowClick(row)}>
...
</tr>
...
);
}
import Link from "next/link"
const Table = () => {
...
return (
...
<Link
key={row.id}
className="relative grid w-full cursor-pointer grid-cols-5 place-items-center space-x-2 border-b-2 border-gray-200 hover:bg-slate-600"
href={`/use-cases/${row.original.id}`}
>
...
</Link>
...
)
}
検証用に使ったリポジトリ
そもそも table タグ を使うと行リンクがむずかしい
まず前提として(いろいろなところで言われていますが)table タグ を使うと行リンクは難しいです
table を使わないなら行全体の div をnext/link
などで囲めばいいだけですが、table になると tr タグを a タグで囲んだり、tr タグの中に a タグを入れるのは不正な構造となってしまいます。
これを解決するためには、たとえば 「各セルに空の a タグを追加しその a タグが全体を覆うように CSS で調整する」 といったハック的な方法がありますが、あまり一般的ではありません。
(詳細は下記を参考にしてください)
next/link では stopProgation が効かない
next/link
を用いる場合は stopProgation
が効かないことも地味に注意すべき点です。
preventDefault
を用いて伝搬を防がないといけないのもつい忘れがちです。
行でいろんなアクションを行うことがある
行でいろんなアクションを行いたい、みたいな要件は割とあります。
例えばサンプルコードに載せてるような編集可能なテーブルというのはその一部です。他にも、行削除や行追加などビジネス要件に応じてさまざまなことが求められます。
以下は Material UI と TanStack Table をベースにした「Material React Table」というライブラリのサンプル集ですが、ライブラリひとつとってもかなり多くのことが実現可能なことがわかるでしょう。
こういったことをしつつ、行をリンクとして扱おうとすると面倒くさいです。
で、結局なにが言いたいん?
要するにテーブルの行リンク化はどうしても必要なとき以外はしなくてもいいんじゃないかなと思いました。
GitHub のプルリクエスト一覧なんかがいい例ですね。
プルリクエストの一覧テーブルの行全体をクリックできるようにはしていません。詳細ページに移動するには、各行のプルリクエストのタイトルをクリックする必要があります。シンプルでわかりやすいですね。
また下記テーブルの設計リストにも書いてある通り、特定のセルをクリックするとクイックビューやモーダルが開くという形でも充分代替可能だと思います。
最後に
行リンクは面倒くさい。
参考資料
ポップアップストアや催事イベント向けの商業スペースを簡単に予約できる「SHOPCOUNTER」と商業施設向けリーシングDXシステム「SHOPCOUNTER Enterprise」を運営しています。エンジニア採用強化中ですので、興味ある方はお気軽にご連絡ください! counterworks.co.jp/
Discussion