【React】react-window Fixed Size Grid レスポンシブ

Fixed Size Grid をレスポンシブで作成します。

前回は Fixed Size Grid に任意のデータを表示しました。前回は以下を参照して下さい。

やりたいこと

jsonデータからサムネイルパス一覧を取得して、サムネイルを表示します。

リファクタリング

前回は Appコンポーネントのみで作成していましたが、今回は新たにPhotoGalleryコンポーネントを作成しました。

実装

imgPathList.json (インプットデータ)

{
    "imgPathList" : [
        [
            "https://dennie.tokyo/norway/img/photos/square/P1014659.jpg",
            "https://dennie.tokyo/norway/img/photos/square/P1014660.jpg",
            "https://dennie.tokyo/norway/img/photos/square/P1014661.jpg",
            "https://dennie.tokyo/norway/img/photos/square/P1014662.jpg",
            "https://dennie.tokyo/norway/img/photos/square/P1014662.jpg"
        ],
        [
            "https://dennie.tokyo/norway/img/photos/square/P1014663.jpg",
            "https://dennie.tokyo/norway/img/photos/square/P1014664.jpg",
            "https://dennie.tokyo/norway/img/photos/square/P1014665.jpg",
            "https://dennie.tokyo/norway/img/photos/square/P1014666.jpg",
            "https://dennie.tokyo/norway/img/photos/square/P1014666.jpg"
        ],
        [
            "https://dennie.tokyo/norway/img/photos/square/P1014667.jpg",
            "https://dennie.tokyo/norway/img/photos/square/P1014668.jpg",
            "https://dennie.tokyo/norway/img/photos/square/P1014669.jpg",
            "https://dennie.tokyo/norway/img/photos/square/P1014670.jpg",
            "https://dennie.tokyo/norway/img/photos/square/P1014670.jpg"
        ],
        [
            "https://dennie.tokyo/norway/img/photos/square/P1014671.jpg",
            "https://dennie.tokyo/norway/img/photos/square/P1014672.jpg",
            "https://dennie.tokyo/norway/img/photos/square/P1014673.jpg",
            "https://dennie.tokyo/norway/img/photos/square/P1014674.jpg",
            "https://dennie.tokyo/norway/img/photos/square/P1014674.jpg"
        ],
        [
            "https://dennie.tokyo/norway/img/photos/square/P1014675.jpg",
            "https://dennie.tokyo/norway/img/photos/square/P1014676.jpg",
            "https://dennie.tokyo/norway/img/photos/square/P1014677.jpg",
            "https://dennie.tokyo/norway/img/photos/square/P1014678.jpg",
            "https://dennie.tokyo/norway/img/photos/square/P1014678.jpg"
        ],
        [
            "https://dennie.tokyo/norway/img/photos/square/P1014681.jpg",
            "https://dennie.tokyo/norway/img/photos/square/P1014684.jpg",
            "https://dennie.tokyo/norway/img/photos/square/P1014685.jpg",
            "https://dennie.tokyo/norway/img/photos/square/P1014686.jpg"
        ],
        [
            "https://dennie.tokyo/norway/img/photos/square/P1014681.jpg",
            "https://dennie.tokyo/norway/img/photos/square/P1014684.jpg",
            "https://dennie.tokyo/norway/img/photos/square/P1014685.jpg",
            "https://dennie.tokyo/norway/img/photos/square/P1014686.jpg"
        ]
    ]
}

Appコンポーネント

import './App.css';
// import './dennie.css';
import React from 'react';
import PhotoGallery from './PhotoGallery';
import imagePathList from './imgPathList.json';

function App() {

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

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

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

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

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

export default App;

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

.dennie_container {
    border: 4px solid red;
}

PhotoGalleryコンポーネント

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', // クラス名(オプション)
}) {

  // テーブルの高さ、幅を保持する。
  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);

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

export default PhotoGallery;

PhotoGallery.css

.container_center {
    margin: 0 auto;
}

最後に

サムネイルパス一覧が固定なので、次回は動的にパス一覧を更新するような処理を実装します。

コメントを残す

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

© DeNnie.Lab All Rights Reserved.