在我的 React 项目中,当用户滚动到页面底部时,我使用 React-infinite-scroller 从 API 获取数据。页面加载时,第一个 fetch 调用按预期工作,但一旦我向下滚动,就会进行 50 多个 API 调用,并且出现
Maximum update depth exceeded
错误。关于我可能做错了什么有什么想法吗?
当 page=2 时,response.data.next
是 null
,但从我看来,hasMore
始终是 true
。
{"count":6,"next":null,...}
尝试使用
useRef
代替 useState
来代替 hasMore
,但结果是相同的。
我正在遵循一个如下所示的基本示例:
import React, { useState, useEffect } from 'react';
import InfiniteScroll from 'react-infinite-scroller';
import Box from '@mui/material/Box';
import axiosInstance from '../axios';
const Test = () => {
const [data, setData] = useState([]);
const [hasMore, setHasMore] = useState(true);
const [page, setPage] = useState(1);
const fetchData = async (pageNumber) => {
try {
const response = await axiosInstance.get("/search/?page=" + (page))
const newData = response.data.results;
setData(prevData => [...prevData, ...newData]);
setHasMore(response.data.next !== null);
} catch (error) {
console.error('Error fetching data:', error);
}
};
useEffect(() => {
fetchData(page);
}, [page]);
const loadMore = () => {
setPage(prevPage => prevPage + 1);
};
return (
<>
<Box sx={{height: '800px'}}>
</Box>
<InfiniteScroll
pageStart={0}
loadMore={loadMore}
hasMore={hasMore}
loader={<div key={0}>Loading...</div>}
>
{data.map(item => (
<div key={item.id}>
{/* Render your data here */}
</div>
))}
</InfiniteScroll>
</>
);
};
export default Test;
问题出在您处理页面的方式上。 Infinity Scroll 首先调用
loadMore
,当您通过设置页面更改状态时,react 会触发重新渲染,当它重新渲染时,Infinity Scroll 再次调用 loadMore
,从而导致无限的重新渲染循环。可能有更多方法可以解决这个问题,但是使用 Ref 而不是 State 处理页面可以修复它:
import React, { useState } from 'react';
import InfiniteScroll from 'react-infinite-scroller';
import Box from '@mui/material/Box';
import axiosInstance from '../axios';
const Test = () => {
const [data, setData] = useState([]);
const [hasMore, setHasMore] = useState(true);
const page = useRef(1);
const fetchData = async (pageNumber) => {
try {
const response = await axiosInstance.get("/search/?page=" + pageNumber);
const newData = response.data.results;
setData(prevData => [...prevData, ...newData]);
setHasMore(response.data.next !== null);
} catch (error) {
console.error('Error fetching data:', error);
}
};
const loadMore = () => {
fetchData(page.current++);
};
return (
<>
<Box sx={{height: '800px'}}>
</Box>
<InfiniteScroll
pageStart={0}
loadMore={loadMore}
hasMore={hasMore}
loader={<div key={0}>Loading...</div>}
>
{data.map(item => (
<div key={item.id}>
{/* Render your data here */}
</div>
))}
</InfiniteScroll>
</>
);
};
export default Test;