使用 react-infinite-scroll 和 react hooks 时如何删除可重复的 API 结果
How to remove repeatable API results when using react-infinite-scroll and react hooks
我正在使用 react-infinite-scroll-component
库和 randomuser.me api。我可以获取数据并且无限滚动工作得很好,但我遇到的问题是,由于组件在每次滚动时都会发出请求,所以我得到了可重复的结果。
我找到了一个解决方法,可以删除相同的数组,但它不能与无限滚动包一起正常工作。
这是我的代码:
function App() {
const [people, setPeople] = useState([]);
const fetchPeopleImages = () => {
axios.get(`https://randomuser.me/api/?results=30&nat=br`).then((res) => {
const result = res.data.results;
setPeople([...people, ...result]);
});
// if (people.length > 30) {
// const removedDuplicatedPeople = people.filter(
// (ele, ind) =>
// ind ===
// people.findIndex(
// (elem) => elem.picture.medium === ele.picture.medium,
// ),
// );
// setPeople([...people, removedDuplicatedPeople]);
// }
};
useEffect(() => {
fetchPeopleImages();
// commented below because ESLINT was asking me to use useCallback
// inside fetchPeopleImage func. idk why
// eslint-disable-next-line
}, []);
return (
<div className="App">
<InfiniteScroll
dataLength={people.length}
next={() => fetchPeopleImages()}
hasMore={true}
loader={<h4>Carregando...</h4>}
endMessage={
<p style={{ textAlign: 'center' }}>
<b>Yay! You have seen it all</b>
</p>
}
>
{people.length > 1 &&
people.map((people, i) => (
<div>
<img src={people.picture.medium} alt="Imagem de uma pessoa" />
</div>
))}
</InfiniteScroll>
</div>
);
}
export default App;
评论的是我发现的删除具有相同图像的数组的解决方法 link。
代码沙盒:https://codesandbox.io/s/gracious-wildflower-opjx5?file=/src/App.js
最好不要专门做频繁抓取(如滚动)的过滤业务。如果你保持状态说 page
并将其传递给你的 api 并且 api 应该 return 数据会更好。
您遇到的不一致问题是由于 randomuser.me api 的限制造成的。 api只有有限的图片可以提供,所以它会把名字、年龄、图片等混在一起,尽量提供唯一的记录。因此,您经常会看到重复的图像。您可以通过渲染名称和图像来检查,您会看到 2 个相同的图像具有不同的名称。
解决您的问题的一些建议:
- 为 results
查询参数提供一个低值,比如 10
- 使用 seed
选项到 api
- 在每次滚动时递增 page
并将其传递给 api 查询参数
参见 updated demo here - 它在一定程度上有效
注意 - 您仍然不能保证看到呈现的独特图像。但是,您可以使用更新后的代码,当您将它与真正的 api.
一起使用时它会起作用
更新的代码片段
function App() {
const [people, setPeople] = useState([]);
const [page, setPage] = useState(0);
const fetchPeopleImages = () => {
axios
.get(`https://randomuser.me/api/?results=10&nat=br&page=${page}&seed=abc`)
.then(res => {
const result = res.data.results;
setPeople([...people, ...result]);
setPage(prev => prev + 1);
});
console.log("page", page);
};
useEffect(() => {
fetchPeopleImages();
// commented below because ESLINT was asking me to use useCallback inside
// fetchPeopleImage func. idk why
// eslint-disable-next-line
}, []);
return (
<div className="App">
<InfiniteScroll
dataLength={people.length}
next={() => fetchPeopleImages()}
hasMore={true}
loader={<h4>Loading.....</h4>}
endMessage={
<p style={{ textAlign: "center" }}>
<b>Yay! You have seen it all</b>
</p>
}
>
{people.length > 1 &&
people.map((people, i) => (
<div key={i}>
<img src={people.picture.medium} alt="Person" />
<p>{people.name.first}</p>
</div>
))}
</InfiniteScroll>
</div>
);
}
我正在使用 react-infinite-scroll-component
库和 randomuser.me api。我可以获取数据并且无限滚动工作得很好,但我遇到的问题是,由于组件在每次滚动时都会发出请求,所以我得到了可重复的结果。
我找到了一个解决方法,可以删除相同的数组,但它不能与无限滚动包一起正常工作。
这是我的代码:
function App() {
const [people, setPeople] = useState([]);
const fetchPeopleImages = () => {
axios.get(`https://randomuser.me/api/?results=30&nat=br`).then((res) => {
const result = res.data.results;
setPeople([...people, ...result]);
});
// if (people.length > 30) {
// const removedDuplicatedPeople = people.filter(
// (ele, ind) =>
// ind ===
// people.findIndex(
// (elem) => elem.picture.medium === ele.picture.medium,
// ),
// );
// setPeople([...people, removedDuplicatedPeople]);
// }
};
useEffect(() => {
fetchPeopleImages();
// commented below because ESLINT was asking me to use useCallback
// inside fetchPeopleImage func. idk why
// eslint-disable-next-line
}, []);
return (
<div className="App">
<InfiniteScroll
dataLength={people.length}
next={() => fetchPeopleImages()}
hasMore={true}
loader={<h4>Carregando...</h4>}
endMessage={
<p style={{ textAlign: 'center' }}>
<b>Yay! You have seen it all</b>
</p>
}
>
{people.length > 1 &&
people.map((people, i) => (
<div>
<img src={people.picture.medium} alt="Imagem de uma pessoa" />
</div>
))}
</InfiniteScroll>
</div>
);
}
export default App;
评论的是我发现的删除具有相同图像的数组的解决方法 link。 代码沙盒:https://codesandbox.io/s/gracious-wildflower-opjx5?file=/src/App.js
最好不要专门做频繁抓取(如滚动)的过滤业务。如果你保持状态说 page
并将其传递给你的 api 并且 api 应该 return 数据会更好。
您遇到的不一致问题是由于 randomuser.me api 的限制造成的。 api只有有限的图片可以提供,所以它会把名字、年龄、图片等混在一起,尽量提供唯一的记录。因此,您经常会看到重复的图像。您可以通过渲染名称和图像来检查,您会看到 2 个相同的图像具有不同的名称。
解决您的问题的一些建议:
- 为 results
查询参数提供一个低值,比如 10
- 使用 seed
选项到 api
- 在每次滚动时递增 page
并将其传递给 api 查询参数
参见 updated demo here - 它在一定程度上有效
注意 - 您仍然不能保证看到呈现的独特图像。但是,您可以使用更新后的代码,当您将它与真正的 api.
一起使用时它会起作用更新的代码片段
function App() {
const [people, setPeople] = useState([]);
const [page, setPage] = useState(0);
const fetchPeopleImages = () => {
axios
.get(`https://randomuser.me/api/?results=10&nat=br&page=${page}&seed=abc`)
.then(res => {
const result = res.data.results;
setPeople([...people, ...result]);
setPage(prev => prev + 1);
});
console.log("page", page);
};
useEffect(() => {
fetchPeopleImages();
// commented below because ESLINT was asking me to use useCallback inside
// fetchPeopleImage func. idk why
// eslint-disable-next-line
}, []);
return (
<div className="App">
<InfiniteScroll
dataLength={people.length}
next={() => fetchPeopleImages()}
hasMore={true}
loader={<h4>Loading.....</h4>}
endMessage={
<p style={{ textAlign: "center" }}>
<b>Yay! You have seen it all</b>
</p>
}
>
{people.length > 1 &&
people.map((people, i) => (
<div key={i}>
<img src={people.picture.medium} alt="Person" />
<p>{people.name.first}</p>
</div>
))}
</InfiniteScroll>
</div>
);
}