如何在你的React应用程序中设置GraphQL
在这篇文章中,我们将讨论如何在Apollo的帮助下在我们的React应用程序中实现GraphQL。有很多方法可以将GraphQL集成到我们的React应用程序中,但我确实更喜欢Apollo,而不是其他任何替代方案。
如果你还不熟悉GraphQL,你可以看看这篇文章,它应该让你从根本上了解为什么它很重要,以及什么时候你可能想使用它。
如果你已经熟悉了,你可能还想看看这篇文章,在那里我们深入了解了如何用Node.js和Express.js建立GraphQL服务器。
包含本文中所有代码的仓库可以在这里找到。
请务必查看GraphQL服务器资源库,我们将在这里与之互动。
项目设置
1.设置React项目
首先,我们将从创建一个新的React项目开始。这可以通过npm或yarn完成。我个人更喜欢yarn,但你也可以使用npm,这没有什么问题。
2.安装所需的依赖项
因为我们只做一些比较基本的工作,所以你只需要安装两个库来安装Apollo:
- @apollo/client,它包含了几乎所有你可能需要的东西,以便设置Apollo客户端。
- graphql,它提供了处理GraphQL查询的逻辑。
3.设置Apollo客户端
现在我们已经安装了这两个必要的依赖项,我们可以继续设置Apollo客户端。
首先,让我们从@apollo/client添加必要的导入:
import { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client';
- ApolloClient是一个主类,一旦实例化,将创建一个新的Apollo客户端实例(我们可以有多个)。
- InMemoryCache是一个我们将使用的类,以便让Apollo客户端处理其请求的缓存过程。
- ApolloProvider是一个组件,它接收客户端作为道具,这将允许我们将Apollo客户端注入到我们的应用程序。
现在让我们开始创建我们的第一个Apollo客户端:
const apolloClient = new ApolloClient({
uri: 'http://localhost:8080/graphql',
cache: new InMemoryCache(),
});
在这里你可以看到我们传递了两个属性给ApolloClient的结构体。这些属性用于指定后端GraphQL服务器的端点,以及Apollo将使用的缓存机制(我们传递了我们已经导入的默认机制 -InMemoryCache)。
这就是我们设置客户端所需的全部内容。
4.挂上Apollo客户端
设置过程的最后一步是将Apollo客户端连接到我们的React应用程序。我们可以通过在**组件中包装我们的**组件来做到这一点:
root.render(
<React.StrictMode>
<ApolloProvider client={apolloClient}>
<App />
</ApolloProvider>
</React.StrictMode>
);
我们的App.js现在看起来应该是这样的:
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client';
const apolloClient = new ApolloClient({
uri: 'http://localhost:8080/graphql',
cache: new InMemoryCache(),
});
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<ApolloProvider client={apolloClient}>
<App />
</ApolloProvider>
</React.StrictMode>
);
使用 useQuery 获取数据
现在我们已经完成了Apollo客户端的设置,我们可以开始使用**@apollo/client库提供的一些工具,以及graphql**库。
对于这篇文章,应该还有一个资源库,它展示了一个使用Node.js和Express构建的基本GraphQL服务器,它允许我们访问一些作者和一些书籍。
一个作者可以有多本书,但一本书只能有一个作者,所以背后的模式看起来是这样的。
作者GraphQL模式
书籍GraphQL模式
让我们深入研究一些简单的用例,如检索作者和他们写的书。首先,我们必须创建一个GraphQL查询,这可以这样做。
const GET_AUTHORS_WITH_BOOKS_QUERY = gql`
query {
authors {
id
firstName
lastName
books {
id
title
}
}
}
`;
其次,我们必须使用useQuery钩子来查询我们的数据。
const { data, loading, error } = useQuery(GET_AUTHORS_WITH_BOOKS_QUERY);
正如你所看到的,我们将可以访问3个重要的属性。
- 数据表示我们所查询的数据(根据我们之前定义的gql查询)。
- 装载, 给我们提供请求的状态,特别是它是否已经完成加载
- 错误, 在请求失败的情况下,它将向我们表明遇到了什么问题(验证、服务器停机等)。
而现在我们可以利用这些属性来处理我们的数据。
return (
<div className="App">
<div className="authors-container">
{loading ? (
<p>Loading Authors...</p>
) : error ? (
<p>There was an issue loading the data...</p>
) : (
data?.authors.map((author) => (
<div className="user-record" key={author.id}>
<p>Author: {author.firstName + " " + author.lastName}</p>
<div className="author-books-container">
{author?.books?.length && <h3>Books Written:</h3>}
{author?.books?.map((book) => (
<div className="author-book-record">
<p>Book Title: {book.title}</p>
</div>
))}
</div>
</div>
))
)}
</div>
</div>
);
在这里,你可以看到,我们将检索我们所存储的所有作者,我们将在屏幕上显示他们的名字和他们所写的书的标题。
所有事先定义的属性都是反应式的,这意味着我们唯一要做的就是使用它们,一切都会很好地与我们的React应用程序挂钩;这意味着一旦加载过程完成,例如,加载变量的值将改变为falsy,然后我们就知道我们可以访问数据属性,或错误属性。
用useMutation更新/创建数据
更新或变异数据的过程与查询数据的过程相当类似,唯一的区别是我们使用的关键字(查询vs 突变),以及我们从调用钩子得到的东西,那就是一个数组,它为我们提供了一个触发变异的函数,以及我们从useQuery钩子得到的其他属性(数据, 装载, 错误).
在创建一个新的作者时,突变查询将看起来像这样。
const ADD_AUTHOR_MUTATION = gql`
mutation CreateAuthor($firstName: String!, $lastName: String!) {
createAuthor(
firstName: $firstName
lastName: $lastName
) {
id
}
}
`;
该 useMutation钩子的调用会是这样的。
const [addAuthor] = useMutation(ADD_AUTHOR_MUTATION);
我们将不使用 数据, 载入,和 错误属性,因为我们只需启动并忘记变异函数。
至于JSX和React代码的其余部分,我们将创建一个新的表单来输入作者的名字和姓氏,提交后我们将触发addAuthor函数调用来创建新的作者记录。
最后的App.js文件看起来会是这样的。
import { useState } from "react";
import { useQuery, useMutation, gql } from "@apollo/client";
import "./App.css";
function App() {
const [authorFirstName, setAuthorFirstName] = useState("");
const [authorLastName, setAuthorLastName] = useState("");
const GET_AUTHORS_WITH_BOOKS_QUERY = gql`
query {
authors {
id
firstName
lastName
books {
id
title
}
}
}
`;
const ADD_AUTHOR_MUTATION = gql`
mutation CreateAuthor($firstName: String!, $lastName: String!) {
createAuthor(
firstName: $firstName
lastName: $lastName
) {
id
}
}
`;
const { data, loading, error, refetch } = useQuery(GET_AUTHORS_WITH_BOOKS_QUERY);
const [addAuthor] = useMutation(ADD_AUTHOR_MUTATION);
const handleSubmitForm = (e) => {
e.preventDefault(); // Avoid refreshing the page
addAuthor({
variables: {
firstName: authorFirstName,
lastName: authorLastName,
},
});
refetch();
};
return (
<div className="App">
<div className="authors-container">
{loading ? (
<p>Loading Authors...</p>
) : error ? (
<p>There was an issue loading the data...</p>
) : (
data?.authors.map((author) => (
<div className="user-record" key={author.id}>
<p>Author: {author.firstName + " " + author.lastName}</p>
<div className="author-books-container">
{author?.books?.length && <h3>Books Written:</h3>}
{author?.books?.map((book) => (
<div className="author-book-record">
<p>Book Title: {book.title}</p>
</div>
))}
</div>
</div>
))
)}
</div>
<div className="add-author-container">
<form onSubmit={(e) => handleSubmitForm(e)}>
<input
type="text"
value={authorFirstName}
onChange={(e) => setAuthorFirstName(e.target.value)}
/>
<input
type="text"
value={authorLastName}
onChange={(e) => setAuthorLastName(e.target.value)}
/>
<button type="submit">Add Author</button>
</form>
</div>
</div>
);
}
export default App;
所以,你有了它。你应该有一个基本的Apollo集成,现在你可以随着你的应用程序的复杂性的增加而建立。
随着你的应用程序的增长,你可能想开始考虑将查询和突变分离到独立的全局、功能或视图特定目录中。你可能还想考虑创建钩子来处理常见的查询或突变,这样你就可以提高代码的可重用性,以及消除多余的重复。
我希望你喜欢读这篇文章,它帮助你了解在Apollo的帮助下在你的React应用程序中设置GraphQL的基本原理。如果你觉得我错过了什么,请在下面的评论中告诉我。
直到下一次。干杯!
转载自:https://juejin.cn/post/7176274176607518779