我正在使用React Infinite Scroller来呈现帖子列表。
我的加载更多结果函数被调用了3次,因此结果被更新了3次(可以通过console.log查看)
我通过以下方式呈现帖子
{results.map((result) => (
<Widget data={result} key={result.id} />
))}
这将前两次更新结果,但是当状态第三次更改时,它将不再呈现任何结果。
我的完整代码:
import React, { useState } from "react";
import InfiniteScroll from "react-infinite-scroller";
import LoadingIndicator from "./loading";
import { request } from "../communication";
const InfiniteResults = ({ endpoint, widget }) => {
let [results, setResults] = useState([]);
let [hasMoreResults, setHasMoreResults] = useState(true);
const Widget = widget;
function loadMoreResults(page) {
// prevent from making more requests while waiting for the other one to complete
setHasMoreResults(false);
request
.get(endpoint, {
offset: page * 10,
})
.then(function gotResults(response) {
const data = response.data;
const resultsCopy = results;
data.results.forEach(function saveResultToState(result) {
resultsCopy.push(result);
});
setResults(resultsCopy);
console.log(resultsCopy);
console.log(results);
if (!data.next) {
setHasMoreResults(false);
} else {
setHasMoreResults(true);
}
});
}
return (
<InfiniteScroll
pageStart={-1}
loadMore={loadMoreResults}
hasMore={hasMoreResults}
loader={<p key={0}>Loading...</p>}
>
{results.map((result) => {
console.log("rerender");
return <Widget data={result} key={result.id} />;
})}
</InfiniteScroll>
);
};
export default InfiniteResults;
答案 0 :(得分:2)
您的问题在于您的状态更新:
const resultsCopy = results;
data.results.forEach(function saveResultToState(result) {
resultsCopy.push(result);
);
setResults(resultsCopy);
当您执行const resultsCopy = results;
时,您实际上并没有在复制数组;您只是通过另一个名称引用相同的数组。这意味着,当您开始向其中添加元素时,就是将它们直接添加到由React的useState
钩子控制的元素中。所有状态更新都应通过setState
返回的setResults
(在您的情况下为useState
)函数中完成。
要对先前状态进行更新,最好的方法是使用函数作为参数调用setResults
函数,该函数将先前状态作为自己的参数。这样可以确保状态更新是连续的(每次更新在上一个更新完成之后进行)。
setResults(prevState => prevState.concat(data.results));
// or
setResults(function (prevState) {
return prevState.concat(data.results);
});
在这里,我还使用了concat
函数,该函数将两个数组合并为一个数组并返回结果。这样,您就不会使用push
调用来更新以前的状态。