1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

React(Typescript), Laravel APIでPagination

Last updated at Posted at 2023-12-11

タイトルのとおりですが、最近LaravelとReactでPaginationを作成したので、そのときのメモという形で記事を書きたいと思います。

Laravelでpagination付きのAPIを作成し、ReactではMaterialUIのPaginationを使用して実装してます。
https://mui.com/material-ui/react-pagination/

今回はReact側について記事を書きたい思うので、Laravelに関してはふれておりません…あしからず。

一覧を受け取るカスタムフック

Laravelから受け取るデータの型を定義します。
一覧で表示させたいデータの中身はWordで、Paginationも含めたものがWordResponseAPIとなります。

type/word.ts
export type Word = {
  id: number;
  user_id: number;
  word_en: string;
  word_ja: string;
  part_of_speech: number;
  memory: number;
  memo: string;
  created_at: string;
  updated_at: string;
  deleted_at: string | null;
};

export type WordResponseApi = {
  current_page: number;
  data: Word[];
  last_page: number;
  total: number;
}

axiosで受け取ります。
上記で宣言した型をimportします。

hooks/useAllWords.ts
import axios from "axios";
import { useState } from "react";
import { WordResponseApi } from "../types/word";

export const useAllWords = () => {
	const [wordsData, setWordsData] = useState<WordResponseApi>({
		current_page: 1,
		data: [],
		last_page: 1,
		total: 0,
	});

	const fetchPost = async (currentPage: number) => {
		try {
			const response = await axios.get<WordResponseApi>(`/words?page=${currentPage}`);
			setWordsData(response.data);
		} catch (error) {
			console.log(error);
		}
	};
	return { fetchPost, wordsData };
};

一覧を表示させる

先ほど作成したカスタムフックを使用して、一覧を表示させます。

Main.tsx
import React, { useEffect, useState } from "react";
import { useAllWords } from "../hooks/useAllWords";

export const Main = () => {
	const getPageNumberFromSession = (): number => {
		const pageNumber = sessionStorage.getItem("currentPage");
		return pageNumber ? parseInt(pageNumber, 10) : 1;
	};
 
	const { fetchPost, wordsData } = useAllWords();

 	const [page, setPage] = useState(getPageNumberFromSession());

  	const handleChangePage = (
		event: React.ChangeEvent<unknown>,
		newPage: number
	) => {
		setPage(newPage);
		fetchPost(newPage);
	};

 	useEffect(() => {
		sessionStorage.setItem("currentPage", page.toString());
		fetchPost(page);
	}, [page]);

 	return (
		<main>
            <div className="p-6 bg-white border-b border-gray-200">
                <div className="text-gray-600 body-font">    
                    <div className="container mx-auto">
                        <ul className="flex flex-wrap -m-2">
                            {wordsData.data.map(
                                ({
                                    id,
                                    word_en,
                                    word_ja,
                                    part_of_speech,
                                    memory,
                                    memo,
                                    created_at,
                                }) => (
                                    <Word
                                        key={id}
                                        word_id={id}
                                        word_en={word_en}
                                        word_ja={word_ja}
                                        part_of_speech={part_of_speech}
                                        memory={memory}
                                        memo={memo}
                                        created_at={created_at}
                                        onDelete={handleDelete}
                                        onUpdateSuccess={onUpdateSuccess}
                                    />
                                )
                            )}
                        </ul>
                    </div>
                </div>
                <div className="mt-4 flex justify-center">
                    <Pagination
                        count={wordsData.last_page}
                        page={page}
                        onChange={handleChangePage}
                    />
                </div>
            </div>
  		</main>
	);
};

useStateの初期値にwordsData.currentPageとしてもよかったのですが、
例えば2ページ目以降でリロードしたときに1ページ目に戻ってしまうという問題があったので、
セッションストレージを使用しました。

useEffectでセッションストレージにつっこみ、getPageNumberFromSessionで取り出すといったイメージです。

以上!

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?