The*_*ner 6 javascript infinite-scroll reactjs next.js
在我的 NextJS 应用程序中,我有一个如下所示的PostList.jsx组件:
import { useQuery } from '@apollo/react-hooks';
import Typography from '@material-ui/core/Typography';
import { NetworkStatus } from 'apollo-client';
import gql from 'graphql-tag';
import getPostsQuery from '../../apollo/schemas/getPostsQuery.graphql';
import Loading from './Loading';
import Grid from '@material-ui/core/Grid';
import PostPreview from './PostPreview';
import withStyles from '@material-ui/core/styles/withStyles';
import React, { useLayoutEffect } from 'react';
const styles = (theme) => ({
root: {
padding: theme.spacing(6, 2),
width: '100%',
},
});
export const GET_POSTS = gql`${getPostsQuery}`;
export const getPostsQueryVars = {
start: 0,
limit: 7,
};
const PostsList = (props) => {
const { classes } = props;
const {
loading,
error,
data,
fetchMore,
networkStatus,
} = useQuery(
GET_POSTS,
{
variables: getPostsQueryVars,
// Setting this value to true will make the component rerender when
// the "networkStatus" changes, so we'd know if it is fetching
// more data
notifyOnNetworkStatusChange: true,
},
);
const loadingMorePosts = networkStatus === NetworkStatus.fetchMore;
const loadMorePosts = () => {
fetchMore({
variables: {
skip: posts.length
},
updateQuery: (previousResult, { fetchMoreResult }) => {
if (!fetchMoreResult) {
return previousResult
}
return Object.assign({}, previousResult, {
// Append the new posts results to the old one
posts: [...previousResult.posts, ...fetchMoreResult.posts]
})
}
})
};
const scrollFunction = () => {
const postsContainer = document.getElementById('posts-container');
if (postsContainer.getBoundingClientRect().bottom <= window.innerHeight) {
console.log('container bottom reached');
}
};
useLayoutEffect(() => {
document.addEventListener('scroll', scrollFunction);
scrollFunction();
// returned function will be called on component unmount
return () => {
document.removeEventListener('scroll', scrollFunction);
};
}, []);
if (error) return <div>There was an error!</div>;
if (loading) return <Loading />;
const { posts, postsConnection } = data;
const areMorePosts = posts.length < postsConnection.aggregate.count;
return (
<Grid item className={classes.root}>
<Grid container spacing={2} direction="row" id="posts-container">
{posts.map((post) => {
return (
<Grid item xs={12} sm={6} md={4} lg={3} xl={2} className={`post-preview-container`}>
<PostPreview
title={post.title}
excerpt={post.excerpt}
thumbnail={`https://i.schandillia.com/d/${post.thumbnail.hash}${post.thumbnail.ext}`}
/>
</Grid>
);
})}
</Grid>
{areMorePosts && (
<button onClick={() => loadMorePosts()} disabled={loadingMorePosts}>
{loadingMorePosts ? 'Loading...' : 'Show More'}
</button>
)}
</Grid>
);
};
export default withStyles(styles)(PostsList);
Run Code Online (Sandbox Code Playgroud)
如您所见,该组件使用 Apollo Client 通过 GraphQL 查询从数据库中获取文档,并将它们分页显示。分页定义为getPostsQueryVars对象。在这里,如果您向下滚动到底部并且仍然有可用的帖子,您将看到一个按钮,单击该按钮将加载下一组帖子。
我在这里热衷于做的是实现某种无限滚动并完全取消按钮。到目前为止,我已经scroll使用 React 钩子向组件添加了一个事件函数,并且可以确认它按预期触发:
const scrollFunction = () => {
const postsContainer = document.getElementById('posts-container');
if (postsContainer.getBoundingClientRect().bottom <= window.innerHeight) {
console.log('container bottom reached');
}
};
useLayoutEffect(() => {
document.addEventListener('scroll', scrollFunction);
scrollFunction();
return () => {
document.removeEventListener('scroll', scrollFunction);
};
}, []);
Run Code Online (Sandbox Code Playgroud)
但是我该如何从这里开始呢?一旦container bottom is reachedANDareMorePosts是如何实现以下目标true:
<h4>Loading...</h4>在最后一个之前显示一个</Grid>?loadMorePosts()功能?<h4>Loading...</h4>一次loadMorePosts()完成执行?| 归档时间: |
|
| 查看次数: |
1247 次 |
| 最近记录: |