React-Redux-Toolkit中分页localStorage刷新不持久化问题求助
修复React分页状态localStorage持久化问题
你的代码存在几个关键问题,导致分页状态无法正确持久化,以下是问题分析和修复方案:
核心问题点
- useState初始化逻辑错误:在useState的初始化回调中调用
setPageNumber是无效的,初始化回调应直接返回初始值,而非调用状态更新函数。 - ReactPaginate页码索引不匹配:ReactPaginate的
selected参数是0起始索引,但你的API分页是1起始,直接赋值会导致页码偏移。 - pageCount计算错误:
pagination.last_visible_page已经是API返回的总页数,无需再除以每页条数(24),否则会导致分页组件显示错误的页码数量。 - localStorage取值未处理null:当localStorage中无
page键时,JSON.parse会返回null,需要处理这种边界情况。
修复后的完整代码
import { useEffect, useState } from "react"; import { Link } from "react-router-dom"; import AnimeList from "../components/AnimeList"; import { useGetAnimeListQuery } from "../features/AnimeApi"; import ReactPaginate from "react-paginate"; const Home = () => { // 修复useState初始化:直接返回初始值,处理localStorage不存在的情况 const [pageNumber, setPageNumber] = useState(() => { const savedPage = localStorage.getItem('page'); // 解析失败或无存储值时返回默认页码1,确保为数字类型 return savedPage ? parseInt(savedPage, 10) : 1; }); // 持久化页码到localStorage useEffect(() => { localStorage.setItem("page", pageNumber.toString()); }, [pageNumber]); const { data: anime = {}, isLoading, error, } = useGetAnimeListQuery(pageNumber); const { data, pagination } = anime; if (isLoading) { return ( <div role="status" className="h-screen flex flex-col justify-center items-center bg-gradient-to-r from-[#005C97] to-[#363795]" > <svg className="inline mr-2 w-8 h-8 text-gray-200 animate-spin dark:text-gray-600 fill-blue-600" viewBox="0 0 100 101" fill="none" xmlns="http://www.w3.org/2000/svg" > <path d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z" fill="currentColor" /> <path d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z" fill="currentFill" /> </svg> <span className="sr-only">Loading...</span> </div> ); } if (error) { console.error(error.message); } // 直接使用API返回的总页数,避免计算错误 const pageCount = pagination?.last_visible_page || 1; // 修复页码转换:ReactPaginate的selected是0起始,转成1起始传给API const changePage = ({ selected }) => { setPageNumber(selected + 1); }; return ( <> <div className="bg-gradient-to-r from-[#005C97] to-[#363795]"> <section className="container pt-4 pb-4"> <main className="grid grid-cols-4 gap-3 px-20"> {data?.map((film) => ( <Link to={`/anime/${film.mal_id}`} key={film.mal_id}> <AnimeList {...film} pagination={pagination} /> </Link> ))} <ReactPaginate containerClassName={"paginationBttns"} previousLabel={"Previous"} previousLinkClassName={"previousBttn"} nextLabel={"Next"} nextLinkClassName={"nextBttn"} disabledClassName={"paginationDisabled"} breakLabel={"..."} pageRangeDisplayed={3} marginPagesDisplayed={3} pageCount={pageCount} // 初始选中项转成0起始,与ReactPaginate匹配 initialPage={pageNumber - 1} onPageChange={changePage} activeClassName={"paginationActive"} /> </main> </section> </div> </> ); }; export default Home;
关键修复说明
- useState初始化逻辑:
- 直接从localStorage读取值,解析失败或无存储值时返回默认页码1,确保返回值为数字类型。
- 页码索引转换:
- ReactPaginate的
selected是0起始索引,转换为1起始后传给API,保证请求页码正确。 - 设置
initialPage为pageNumber -1,确保页面刷新后分页组件高亮正确的页码。
- ReactPaginate的
- pageCount修正:
- 直接使用API返回的
pagination.last_visible_page作为总页数,避免多余计算导致的错误。
- 直接使用API返回的
- localStorage持久化:
- 存储时直接存数字的字符串形式,简化逻辑同时避免JSON序列化的冗余。
内容的提问来源于stack exchange,提问作者Haroon Islam
相关产品推荐
相关产品推荐

