【React】react-window を使用した動的テーブル

前回は固定数のデータ(jsonから読み込んがサムネイルパス一覧)をテーブルに表示させていました。

前回は以下を参照して下さい。

今回は、テーブルをスクロールしてスクロールがボトムまで行きそうになったら、サムネイルパス一覧を更新し、表示できるサムネイルの数を動的に増やします。

実装

Appコンポーネント

サムネイルパス一覧が jsonデータからではなく ImgPathList フックの返却値の第一引数 imagePathList から取得できます。第二引数は、サムネイルパス一覧を更新する関数(next)になります。next関数をPhotoGalleryコンポーネントのupDateListプロパティへ渡しています。PhotoGalleryコンポーネントでスクロールの判定を行い、upDateListプロパティで受け取ったサムネイルパス一覧を更新する関数(next)を実行する為です。

import './App.css';
// import './dennie.css';
import React from 'react';
import PhotoGallery from './PhotoGallery';
import ImgPathList from './ImgPathList';

function App() {

  // 列の数(1列に表示する写真の数)
  const columnCount = 4;

  // テーブルの幅(0〜1で設定する。ex)0.8 は幅80%)
  const tableWidth = 0.8;

  // クラス名(オプション)
  // const className = "dennie_container";

  // 第一引数がサムネイルパス一覧。第二引数はサムネイルパス一覧を更新する関数。
  const [imagePathList, next] = ImgPathList(columnCount);

  // 写真(サムネイル)の表示
  const RenderItem = ({columnIndex, rowIndex, style, data}) => {
    return (
      <div style={{...style}}>
         <img src={data[rowIndex][columnIndex]} width={"100%"}/>
      </div>
    );
  }

  return (
    <>
    <PhotoGallery 
      imgPathList = {imagePathList}
      renderItem = {RenderItem} 
      columnCount = {columnCount}
      tableWidth = {tableWidth}
      upDateList = {next}
      // className = {className}
      />
    </>
  );
}

export default App;

dennie.css (任意なくてもOK)

前回と同じです。

.dennie_container {
    border: 4px solid red;
}

PhotoGalleryコンポーネント

サムネイルパス一覧を更新する関数を受け取ります。FixedSizeGrid に onScroll プロパティを指定することで、スクロールすると実行されるイベントを登録できます。

import './PhotoGallery.css';
import React, { useLayoutEffect , useState} from 'react';
import {FixedSizeGrid} from 'react-window';

function PhotoGallery({
  imgPathList = [],   // サムネイルパス一覧
  renderItem,         // カラム表示
  columnCount,        // カラム数
  tableWidth = 1,       // テーブルの幅(1で横幅マックス)(オプション)
  orgItemSizeWith = 1,  // サムネイルの横の長さ(オプション)
  orgItemSizeHigt = 1,  // サムネイルの縦の長さ(オプション)
  className = 'container_center', // クラス名(オプション)
  upDateList = f => f,     // サムネイルパス一覧更新関数(オプション)
}) {

  // テーブルの高さ、幅を保持する。
  const [width, setWidth] = useState(0);
  const [height, setHeight] = useState(0);
  
  // テーブルの高さ、幅をリサイズする。
  const resize = () => {
    setWidth(window.innerWidth);
    setHeight(window.innerHeight);
  }

  useLayoutEffect(() => {
    window.addEventListener("resize", resize);
    resize();
  },[])

  // 列の幅
  let colWidth = (width * tableWidth) / columnCount;

  // 列の高さ(行の高さ) 列の幅 * 縦横比率
  let colHeight = colWidth * (orgItemSizeHigt / orgItemSizeWith);

  // データリストの高さ
  let listHeight = colHeight * imgPathList.length;

  // スクロールイベント。スクロール位置とデータリストの高さを判定して、ボトムになりそうな場合、サムネイルパス一覧を更新する。
  const onScroll = ({
    scrollTop,
  }) => {
    if(scrollTop > listHeight - 1000){
      upDateList();
    }
  }

  return (
    <FixedSizeGrid
      className = {className}
      columnCount = {columnCount}
      columnWidth = {colWidth}
      height = {height}
      width = {width * tableWidth}
      rowCount = {imgPathList.length}
      rowHeight = {colHeight}
      itemData = {imgPathList}
      onScroll = {onScroll}
    >
      {renderItem}
    </FixedSizeGrid>
  );
}

export default PhotoGallery;

PhotoGallery.css

前回と同じです。

.container_center {
    margin: 0 auto;
}

ImgPathList フック

今回新しく追加しました。imagePathList はサムネイルパス一覧になります。next はサムネイルパス一覧を更新する関数になります。

import {useState} from 'react';

function ImgPathList(columnCount = 5, parListCount = 10) {

    // 現在のパス名のカウント
    const [currentNumber, setCurrentNumber] = useState(1014659);

    // サムネイルパス一覧
    const [imagePathList, setImagePathList] = useState([]);

    const next = () => {

        // 新たにサムネイルパス一覧を生成する。
        let cnt = 0;
        let imgPathList = [...Array(parListCount)].map(element => {
            return [...Array(columnCount)].map(elem => {
                const strCurrentNumber = String(currentNumber + cnt);
                const imagePath = `https://dennie.tokyo/norway/img/photos/square/P${strCurrentNumber}.jpg`;
                cnt++;
                return imagePath;
            });
        });

        // 現在のパス名のカウントを増えた分更新する。
        setCurrentNumber(currentNumber + cnt - 1);
        
        // サムネイルパス一覧を更新する。
        setImagePathList(imagePathList.concat(imgPathList));
    }
    
    return [imagePathList, next];
}

export default ImgPathList;

最後に

最後に写真ギャラリーとして完成させます。

コメントを残す

メールアドレスが公開されることはありません。

© DeNnie.Lab All Rights Reserved.