我正尝试通过无限滚动通过滚动的graphql连接我的页面以填充更多项目。目前,我遇到的问题是每次滚动时刷新页面,然后在到达hasMore max时出错。如果有人对如何使它起作用有任何想法,那将是巨大的帮助。我正在使用nextjs,typescript,graphql和reactjs无限滚动
import React, { useState } from 'react';
import gql from 'graphql-tag';
import InfiniteScroll from 'react-infinite-scroller';
import { useQuery } from '@apollo/react-hooks';
import { useRouter } from 'next/router';
import { withApollo } from '../../lib/apollo';
import { ErrorIndicator, LoadingIndicator, SubHeading } from '../../components/Atoms/';
import { Card, SubNav } from '../../components/Molecules/';
import { ArticleList, SixCards } from '../../components/Organisms/';
import { BREAKPOINT } from '../../constants/';
import { countryData } from '../../data/countryData';
export const queryCreator = (categories, count): any => gql`
{
articles(lang: "en", categories: ["${categories}"], count: ${count}){
id
slug
title
content
featuredImage
creator {
name
id
}
categories {
name
id
}
}
}
`;
export const News: React.FC = () => {
const [articleListState, updateArticleList] = useState({
count: 8,
articleList: []
});
const { count, articleList } = articleListState;
const router = useRouter();
const { categories } = router.query;
const categoriesToQuery = categories ? categories.toString() : '';
const formattedQuery = queryCreator(categoriesToQuery, count);
const { loading, error, data } = useQuery(formattedQuery);
if (error) {
return <ErrorIndicator />;
}
if (loading) {
return <LoadingIndicator />;
}
const { articles } = data;
// updateArticleList({ count: 8, articleList: articles });
const hasMore = () => count <= 13;
const loadMore = () => {
if (hasMore) {
const addOne = count + 1;
updateArticleList({ count: addOne, articleList: articles });
}
};
const items = [];
articleList.map((article) =>
items.push(
article && (
<div className="article" key={article.id}>
<Card key={article.id} article={article} size="short" />
<style jsx>{`
.article {
padding: 6px 0;
margin: 0 auto;
}
`}</style>
</div>
)
)
);
console.log(items, count);
return (
<main className="articles-container">
<SubNav />
<SixCards articles={articles} />
<div className="article-list">
<InfiniteScroll
pageStart={0}
loadMore={loadMore}
hasMore={hasMore()}
loader={
<div key={0}>
<SubHeading title="Loading . . ." Tag="h5" />
</div>
}
>
{items}
{/* <ArticleList articles={articleList} /> */}
</InfiniteScroll>
</div>
<style jsx>{`
main.articles-container {
min-height: 80vh;
display: flex;
flex-direction: column;
width: 80%;
margin: 0 auto;
}
.article-list {
display: flex;
flex-direction: column;
justify-content: center;
// width: 100%;
max-width: 1020px;
margin: 10px auto;
align-self: center;
}
@media only screen and (max-width: ${BREAKPOINT}px) {
main.articles-container {
width: 90%;
}
}
`}</style>
</main>
);
};
export default withApollo(News);
答案 0 :(得分:0)
我的查询使用 React、Typescript、GraphQL、apollo/client 和 graphql-tag。
在此示例中,我们将创建 RepoList 组件。此组件将使用 Github 的 GraphQl 使用 searchTerm 获取存储库列表。
import React from 'react';
import { useDebounce } from 'use-debounce';
import gql from 'graphql-tag';
import { useQuery } from '@apollo/client';
import InfiniteScroll from 'react-infinite-scroll-component';
import RepositoryItem, { SkeletonRepositoryCard } from './RepositoryItem';
export const SEARCH_FOR_REPOS = gql`
query($search_term: String!, $cursor: String) {
search(query: $search_term, type: REPOSITORY, first: 15, after: $cursor) {
repositoryCount
edges {
node {
... on Repository {
id
name
description
owner {
login
avatarUrl
}
stargazers {
totalCount
}
}
}
cursor
}
pageInfo {
endCursor
hasNextPage
}
}
}
`;
export interface RepoDetails {
node: {
id: string;
name: string;
description: string | null;
owner: {
login: string;
avatarUrl: string;
};
stargazers: {
totalCount: number;
};
};
}
interface SearchRepoData {
search: {
repositoryCount: string;
edges: RepoDetails[];
pageInfo: {
endCursor: string;
hasNextPage: boolean;
};
};
}
interface SearchRepoVars {
search_term: string;
}
const RepositoryList: React.FC<{ searchTerm: string }> = ({ searchTerm }) => {
const classes = useStyles();
const [expandedRepo, setExpandedRepo] = React.useState<number | null>(null);
const [nextCursor, setNextCursor] = React.useState<string | null>(null);
const [deboucedSearchKey] = useDebounce(searchTerm, 500);
const { data, loading, error, fetchMore } = useQuery<
SearchRepoData,
SearchRepoVars
>(SEARCH_FOR_REPOS, { variables: { search_term: deboucedSearchKey } });
// Reset every time the data change
// We make sure the repos shrink when we make a new search
React.useEffect(() => {
setExpandedRepo(null);
}, [data]);
const handleFetchMore = () => {
console.log('next');
if (data)
fetchMore({
variables: {
cursor: data.search.pageInfo.endCursor,
search_term: searchTerm,
},
});
};
if (loading && searchTerm.length > 1)
return (
< ... render loader ... >
);
if (error)
return (
< ... render error ... >
);
if (!loading && searchTerm.length && data && !data.search.repositoryCount)
return (
< ... Render No Repo ... >
);
if (data && data.search.repositoryCount)
return (
<InfiniteScroll
dataLength={data.search.edges.length}
next={handleFetchMore}
hasMore={data.search.pageInfo.hasNextPage}
loader={<h4>Loading...</h4>}
endMessage={
<p style={{ textAlign: 'center' }}>
<b>Yay! You have seen it all</b>
</p>
}
>
{data &&
data.search.edges.map((repo, i) => (
< ... render repo card ... >
))}
</InfiniteScroll>
);
return <div>Please search for repos</div>;
};
export default RepositoryList;