使用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获取数据。
以上! !)