[英]Infinite Scroll using Algolia on React
我正在尝试在我的反应应用程序上实现无限滚动,以获取来自 Algolia 的搜索命中。
我在他们的文档中遇到了一个 class 组件。 我使用 React Hooks 所以试图让它在 React Hooks 上工作。 我得到的只是这么多的渲染,当这个组件安装时我的应用程序被挂断了。
这是我的代码:
import React, { useEffect, useRef } from 'react';
import Card from '@material-ui/core/Card';
import CardActionArea from '@material-ui/core/CardActionArea';
import CardActions from '@material-ui/core/CardActions';
import CardContent from '@material-ui/core/CardContent';
import CardMedia from '@material-ui/core/CardMedia';
import Button from '@material-ui/core/Button';
import IconButton from '@material-ui/core/IconButton';
import Typography from '@material-ui/core/Typography';
import Container from '@material-ui/core/Container';
import Grid from '@material-ui/core/Grid';
import { connectHits, connectInfiniteHits } from 'react-instantsearch-dom';
import noItemImage from './../../assets/img/noItemImage.png'
import { Link } from 'react-router-dom'
import ShareIcon from '@material-ui/icons/Share';
import PropTypes from 'prop-types';
function AlgoliaHits(props) {
const { hits } = props
console.log(hits)
var sentinel = useRef(null)
useEffect(() => {
function onSentinelIntersection (entries){
const { hasMore, refine } = props
entries.forEach(entry => {
if (entry.isIntersecting && hasMore) {
refine()
}
})
}
var observer = new IntersectionObserver(onSentinelIntersection, {})
observer.observe(sentinel.current)
return () => {
observer.disconnect()
}
}, [props])
return (
<Container maxWidth="md" style={{ marginBottom: 100 }}>
<Grid container spacing={2}>
{
hits.map(hit => (
<Grid item xs={12} sm={6} md={4} lg={4} xl={3}>
<Link to={`/item/${hit.item_id}`} style={{ textDecoration: 'none' }}>
<Card maxWidth={210} key={hit.item_id} elevation={0}>
<CardActionArea>
<CardMedia
component="img"
alt="Contemplative Reptile"
height="140"
image={
hit.item_images_url ?
hit.item_images_url.length === 0 ?
noItemImage
:
hit.item_images_url[0]
:
noItemImage
}
title={hit.item_name}
/>
<CardContent>
<Typography gutterBottom variant="h5" component="h2"
style={{ whiteSpace: 'nowrap', width: 250, overflow: 'hidden', textOverflow: 'ellipsis' }}>
{hit.item_name}
</Typography>
<Typography variant="body2" color="textSecondary" component="p"
style={{ whiteSpace: 'nowrap', width: 200, overflow: 'hidden', textOverflow: 'ellipsis' }}>
{hit.item_description}
</Typography>
</CardContent>
</CardActionArea>
<CardActions>
<Button size="small" color="primary" component={Link} to={`/item/${hit.item_id}`}>
View
</Button>
<IconButton size="small" color="secondary">
<ShareIcon style={{ padding: 4 }}/>
</IconButton>
</CardActions>
</Card>
</Link>
</Grid>
))
}
</Grid>
<div id="sentinel" ref={sentinel} />
</Container>
);
}
AlgoliaHits.propTypes = {
hits: PropTypes.arrayOf(PropTypes.object).isRequired,
hasMore: PropTypes.bool.isRequired,
refine: PropTypes.func.isRequired,
}
const AlgoliaInfiniteScroll = connectHits(AlgoliaHits)
const ItemCard = connectInfiniteHits(AlgoliaInfiniteScroll)
export default ItemCard
这里是我使用参考的地方。 我在做什么错? 以及如何解决?
TIA
我的第一个想法是问题可能出在useEffect
依赖数组中。
只要其中一个依赖项发生更改, useEffect
挂钩就会触发。 在您的情况下,您已将依赖项数组指定为[props]
,这意味着每次道具更改时,它都会再次触发。 由于props
可能经常变化,对于props.hits
等对象,我敢打赌这是将您的代码投入您提到的无限循环中。
我相信在原始示例中, onSentinelIntersection
功能仅在组件安装时发生一次。
我将从一个空的依赖数组开始: []
在你的 useEffect 的末尾。 这是替换componentDidMount
并且仅在组件第一次渲染时运行一次(尽管有点 hacky)的方法。
如果这有帮助,那么您可能已经成功了。 但是,我还建议将onSentinelIntersection
function 从useEffect
中移出(如果可能的话,甚至完全从组件中移出。)-因为最好将尽可能多的代码保留在 useEffect 之外(因为它将是每次执行时评估)。
所以像:
function AlgoliaHits(props) {
const { hits } = props
console.log(hits)
var sentinel = useRef(null)
function onSentinelIntersection (entries){
const { hasMore, refine } = props
entries.forEach(entry => {
if (entry.isIntersecting && hasMore) {
refine()
}
})
}
useEffect(() => {
var observer = new IntersectionObserver(onSentinelIntersection, {})
observer.observe(sentinel.current)
return () => observer.disconnect()
}, [])
....
可能是一个好的开始。 您也可以安全地将[IntersectionObserver, onSentinelIntersection]
添加到useEffect
依赖项中,因为它们在技术上是 useEffect 到 function 所必需的,并且在这种情况下不应导致任何进一步的useEffect
触发器。
React useEffect 文档的Dependencies & Performance部分在这里很有帮助——以及整个页面本身。
对于额外的资源,我真的从 Dan Abramov 的The Complete Guide To useEffect中获得了很多收获——读了很久,但我认为值得(当你有时间的时候,就是这样!)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.