使用React(Typescript)和Laravel API进行分页

最近我在Laravel和React中创建了分页功能,因此我想以此来记录并写一篇文章。

我正在使用Laravel创建带有分页功能的API,并在React中使用MaterialUI的Pagination进行实现。链接:https://mui.com/material-ui/react-pagination/

由于本次我想写有关React方面的文章,所以没有提及Laravel…请理解。

接收清单的自定义钩子

在Laravel中定义接收数据的类型。
想要在列表中显示的数据是Word,并且包括分页,而这些数据的响应API名称为WordResponseAPI。

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 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 };
};

展示清单

使用之前创建的自定义钩子,来显示列表。

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页的问题,我选择使用了会话存储(session storage)。

可以使用useEffect将数据存入会话存储,然后通过getPageNumberFromSession获取数据。

以上! !)

广告
将在 10 秒后关闭
bannerAds