
目的
我最近用Apollo客户端实现了无限滚动,我花了一些时间,我将与你分享,以避免浪费时间。此外,我想通过使用Apollo服务器创建自己的假数据,希望这也是有帮助的。
什么是Apollo客户端?
Apollo客户端是一个用于JS的综合状态管理库。在这篇文章中,我将用反应来解释。最重要的部分是缓存,可以避免从服务器端获取不必要的数据。这个库非常有用,因为它不仅可以通过缓存获取数据,更新数据,还可以作为一个状态管理库使用,比如Redux, Recoil, Zustand。
什么是Apollo服务器?
Apollo服务器是一个开源的库,可以连接所有你想连接的东西。
下面的图片来自官方文档,这个图片说明了什么是Apollo服务器。

图片来自www.apollographql.com/docs/apollo…
在这篇文章中,我将更多地关注例子。让我们深入了解一下这个例子。
注意。你可以选择基于偏移量的分页或基于光标的分页。这不是本文的主要焦点,但使用情况是不同的。就无限滚动而言,你可以使用两种方式,我使用基于偏移量的方式,因为它比其他方式更简单。
例子
前半部分。后台Apollo服务器
- 创建你的项目(项目名称由你决定)
mkdir apollo-inifinite-scroll-backend
cd apollo-inifinite-scroll-backend
2.用npm初始化node.js项目。如果你想推送github,你需要创建.gitignore文件并写入 "node_modules"(可选)。你的项目包含 "package.json "文件
npm init -y
3.安装一些依赖项并创建一个基础索引文件
npm install apollo-server graphql
touch index.js
4.定义你的graphql模式和解析器。为了更简单,我遵循简单的例子(书籍)。但你想改变你想使用的任何东西。你需要把offset和limit传给query类型,并通过使用resolver创建offset和limit的逻辑。最后,有必要通过使用这两个来创建一个服务器。
import { ApolloServer, gql } from "apollo-server";
import { bookBasic } from "./data/books.js";
const typeDefs = gql`
type Book {
title: String
author: String
}
type Query {
books(offset: Int, limit: Int): [Books!]
}
`;
const resolvers = {
Query: {
books: async (_parent, args, _context, _info) => {
if (args.limit) {
const start = args.offset;
const end = args.limit;
return [...booksBasic].slice(start, end);
} else {
return [...booksBasic];
}
},
},
};
new ApolloServer({
typeDefs,
resolvers,
})
.listen()
.then(({ url }) => {
console.log(`🚀 Server ready at ${url}`);
5.像下面这样创建你的数据。
export const booksBasic = [
{
title: "Book1",
author: "John",
},
{
title: "Book2",
author: "Mike",
},
{
title: "Book3",
author: "John",
},
... same structure, I omitted it(but I have 36 books data)
6.在你的终端上使用下面的命令运行服务器,你会看到下面的句子。
node index.js
🚀 Server ready at http://localhost:4000/
7.访问 "localhost:4000",你可以看到如下图所示的屏幕

8.点击上面屏幕上的 "查询你的服务器 "按钮,你就可以使用graphql的沙盒了!!这次我们有书的标题和作者,所以你可以写一个如下图的查询。

9.你可以通过使用offset和limit来设置范围。基本上offset意味着 "开始",limit意味着 "结束"。因此,如果你想从10到20的图片中挑选,你可以设置偏移量10,限制量10,如下图所示。

好了,我们已经完成了后台的工作。所以我将创建一个前台。
下半部分。前端Apollo客户端
- 使用create react app来设置你的环境(项目名称是可选的)。
npx create-react-app apollo-inifinite-scroll-frontend
cd apollo-inifinite-scroll-frontend
2.2.安装一些依赖项。我使用react-insersection-observer来检查和重新获取浏览器屏幕是否在底部,但你也可以使用另一个(例如,你可以自己写处理滚动,或使用react-infinite-scroller-component)。
npm install @apollo/client graphql react-intersection-observer
3.在index.js中设置你的apollo客户端,如下所示。你需要通过使用 "offsetLimitPagination "将缓存类型策略设置为使用基于偏移量的分页。然后创建一个新的客户端,并设置Uri和缓存。注意,这个URI是 "apollo server uri",我们在前半部分创建了Apollo服务器。最后,你需要用新的客户端将你的应用程序与apollo提供者包装起来。
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { ApolloProvider, ApolloClient, InMemoryCache } from "@apollo/client";
import { offsetLimitPagination } from "@apollo/client/utilities";
const cache = new InMemoryCache({
typePolicies: {
Query: {
fields: {
books: offsetLimitPagination(),
},
},
},
});
const client = new ApolloClient({
uri: "http://localhost:4000/",
cache,
});
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<ApolloProvider client={client}>
<App />
</ApolloProvider>
4.创建你的查询,从后端获取数据。由于我们在Apollo服务器上创建了书籍、标题和作者查询。你可以像下面这样创建查询。
import { gql } from "@apollo/client";
export const GET_BOOKS = gql`
query getBooks($offset: Int, $limit: Int) {
books(offset: $offset, limit: $limit) {
title
author
}
}
`;
5.创建app.js来显示查询。我将解释Card部分,所以不用担心。你需要导入你在第4步中创建的查询,并用useQuery来使用它。你可以得到一些值,如data,fetchmore。在这种情况下,data和fetch more是必须的,加载和错误是可选的。你还需要设置变量和偏移量、限制。正如我已经解释过的,offset是开始,limit是结束,所以在这段代码中每次加载8张卡片。你可以把你的数据映射到卡片上,并使用inview来观察浏览器是否有底气去获取更多的书籍卡片。在这种情况下,我扩展了一个限制,每次取更多。
import { useQuery } from "@apollo/client";
import { Card } from "./components/Card";
import { GET_BOOKS } from "./graphql/queries/books";
import { InView } from "react-intersection-observer";
export default function App() {
const { loading, error, fetchMore, data } = useQuery(GET_BOOKS, {
variables: { offset: 0, limit: 8 },
});
if (loading) {
return <p>Loading</p>;
}
if (error) {
console.log(error);
}
if (data) {
console.log(data.books.length);
}
return (
<div>
{data &&
data.books.map(({ title, author }, index) => (
<Card key={index} title={title} author={author} />
))}
{data && (
<InView
onChange={async (inView) => {
const currentLength = data.books.length || 0;
if (inView) {
await fetchMore({
variables: {
offset: currentLength,
limit: currentLength * 2,
},
});
}
}}
/>
)}
</div>
)
6.创建一个卡片。这一部分完全由你决定,你可以创建卡片,图片,...等等。你也可以设计它。在我的案例中,我使用了模块css和scss。然而,这完全是可选的。
import React from "react";
import style from "./style.module.scss";
export const Card = React.memo(function (props) {
const {
title,
author,
} = props;
return (
<div className={style.container}>
<p>{title}</p>
<p>{author}</p>
</div>
);
})
7.完成了!你可以看到下面这样的屏幕。很难找到工作,所以我设置了console.log关于数据长度。你可能会注意到,长度的数量每8个增加,这意味着工作完美!!!。很好!!!。

总结
在这篇文章中,我分享了如何使用fetch more的知识,以及如何通过使用自己创建的真正的端点来实现无限滚动。事实上,fetch more功能并不古老,所以我很难找到合适的信息。我花了很多时间去搜索和尝试,所以我希望这篇文章能帮助你,避免浪费时间。
参考资料
官方文档(阿波罗服务器):https://www.apollographql.com/docs/apollo-server/
官方文档(阿波罗客户端):https://www.apollographql.com/docs/react/
Apollo客户端的分页和无限滚动:www.apollographql.com/blog/apollo…
如何用GraphQL和React实现无限滚动:sysgears.com/articles/ho…
React + GraphQL + Apolloで無限のスクロール(Offset-based):qiita.com/sinno999/it…
GraphQLのページネーション機能を実装する方法:Apollo client + express-graphql:sterfield.co.jp/programmer/…
谢谢您的阅读!!