react-tableで表の特定列・行を固定する方法

React

cover image from Unsplash

Photo by Mika Baumeister on Unsplash

本記事の内容

react-table を使う際に、

方法を紹介する。

なお、列の固定には、react-table-sticky というライブラリを使用する方法もあるが、今回はライブラリを使用しない方法を紹介する。

実装環境

react-table 7.8.0

ソースコード

コードは、react-table 公式ドキュメントにある Exaples/Basic をそのまま使用した。 ソースコードと CodeSandbox は、以下リンクからどうぞ。

CodeSandbox で確認してみると、こんな感じ。 Image from Gyazo元のコード。(https://codesandbox.io/s/laughing-glade-hw5vwm?file=/src/App.js より。)

コード追記後

Image from Gyazo追記後。

  import React from "react";
  import styled from "styled-components";
  import { useTable } from "react-table";
 
  import makeData from "./makeData";
 
  const Styles = styled.div`
    padding: 1rem;
+   font-size: 200%; /* 表を画面いっぱいに表示させてスクロールさせるため。ここは参考にしなくて大丈夫です */
 
  table {
    border-spacing: 0;
    border: 1px solid black;
 
+     /* スクロールしつつ、表のヘッダー部分のみ固定する */
+     thead {
+       background-color: white;
+       position: sticky;
+       top: 0;
+       z-index: 2;
+     }
 
      tr {
        :last-child {
          td {
            border-bottom: 0;
          }
        }
      }
 
      th,
      td {
        margin: 0;
        padding: 0.5rem;
        border-bottom: 1px solid black;
        border-right: 1px solid black;
 
        :last-child {
          border-right: 0;
        }
      }
 
+     /* スクロールしつつ、表の左一列のみ固定する */
+     td {
+       :first-child {
+         background-color: white;
+         position: sticky;
+         left: 0;
+         z-index: 1;
+       }
+     }
    }
  `;
 
  function Table({ columns, data }) {
    // Use the state and functions returned from useTable to build your UI
    const {
      getTableProps,
      getTableBodyProps,
      headerGroups,
      rows,
      prepareRow
    } = useTable({
      columns,
      data
    });
 
    // Render the UI for your table
    return (
      <table {...getTableProps()}>
        <thead>
          {headerGroups.map((headerGroup) => (
            <tr {...headerGroup.getHeaderGroupProps()}>
              {headerGroup.headers.map((column) => (
                <th {...column.getHeaderProps()}>{column.render("Header")}</th>
              ))}
            </tr>
          ))}
        </thead>
        <tbody {...getTableBodyProps()}>
          {rows.map((row, i) => {
            prepareRow(row);
            return (
              <tr {...row.getRowProps()}>
                {row.cells.map((cell) => {
                  return <td {...cell.getCellProps()}>{cell.render("Cell")}</td>;
                })}
              </tr>
            );
          })}
        </tbody>
      </table>
    );
  }
 
  function App() {
    const columns = React.useMemo(
      () => [
        {
          Header: "Name",
          columns: [
            {
              Header: "First Name",
              accessor: "firstName"
            },
            {
              Header: "Last Name",
              accessor: "lastName"
            }
          ]
        },
        {
          Header: "Info",
          columns: [
            {
              Header: "Age",
              accessor: "age"
            },
            {
              Header: "Visits",
              accessor: "visits"
            },
            {
              Header: "Status",
              accessor: "status"
            },
            {
              Header: "Profile Progress",
              accessor: "progress"
            }
          ]
        }
      ],
      []
    );
 
    const data = React.useMemo(() => makeData(20), []);
 
    return (
      <Styles>
        <Table columns={columns} data={data} />
      </Styles>
    );
  }
 
  export default App;

また、表の左二列をまとめて固定したいときは、以下のようになる。

      td {
        /* 左一列目 */
        :first-child {
          background-color: white;
          position: sticky;
          left: 0;
          z-index: 1;
        }
 
+       /* 表の左二列目も固定する */
+       :nth-child(2) {
+         background-color: white;
+         position: sticky;
+         left: /* 一列目のwidth */;
+         z-index: 1;
+       }
+     }

参考