ページサイズの動的調整
定数の定義
src/frontend/src/constants/styles.ts
/**
* スタイル関連の定数
*/
export const STYLES = {
...(略)...
// 映画リスト関連
...(略)...
LIST_MOVIE_PER_PAGE_DEFAULT: 5,
// ↓追加
LIST_MOVIE_CARD_WIDTH: 128,
LIST_MOVIE_CARD_GAP: 8,
// ↑追加
...(略)...
} as const;
コンポーネントの作成
映画リストコンポーネント
src/frontend/src/app/components/list/ListMovie.tsx
"use client";
import { useEffect, useState, useCallback, useRef } from "react"; // <- useRefを追加
...(略)...
/**
* 映画リストコンポーネント
*/
const ListMovie = (props: Props) => {
const [movies, setMovies] = useState<Movie[]>(props.movies);
const [perPage, setPerPage] = useState<number>(STYLES.LIST_MOVIE_PER_PAGE_DEFAULT);
const [currentMovies, setCurrentMovies] = useState<Movie[]>([]);
const [currentPage, setCurrentPage] = useState(0);
const observerRef = useRef<ResizeObserver | null>(null); // <- 追加
...(略)...
/**
* ページ変更ハンドラ
* @param page - 移動先のページ番号
*/
const handlePageChange = useCallback(
...(略)...
);
// ↓追加
const containerRef = useCallback((el: HTMLDivElement | null) => {
if (observerRef.current) {
observerRef.current.disconnect();
observerRef.current = null;
}
if (!el) return;
const observer = new ResizeObserver(([entry]) => {
const width = entry.contentRect.width;
const count = Math.max(
1,
Math.floor(
(width + STYLES.LIST_MOVIE_CARD_GAP) /
(STYLES.LIST_MOVIE_CARD_WIDTH + STYLES.LIST_MOVIE_CARD_GAP)
)
);
setPerPage(count);
});
observer.observe(el);
observerRef.current = observer;
}, []);
// ↑追加
// 空の状態の表示
if (movies.length === 0) {
return <></>;
}
return (
<>
<div className={`${STYLES.LIST_MOVIE_LABEL_PHRASE}`}>{props.phrase}</div>
<div className={`${STYLES.LIST_MOVIE}`}>
...(略)...
<div className={`${STYLES.LIST_MOVIE_INSIDE}`} ref={containerRef}> {/* <- refを追加 */}
...(略)...
</div>
</div>
</>
);
};
export default ListMovie;
ブラウザで下記 URL にアクセスしてください。
サインインすると、映画リストが表示されます。また、ウィンドウサイズを変更すると、ページ内の映画件数が動的に調整されます。