Apollo GraphQL:如何使用 React 和 Node.js 构建全栈应用程序
Apollo Client 是一个功能齐全的 JavaScript 应用状态管理库。它功能强大,既可用于后端也可用于前端。
在本教程中,我们将首先使用 Node.js 构建一个 Apollo GraphQL 服务器,然后使用 React.js 在客户端使用数据,从而实现 Apollo Client 在后端和前端的应用。
如果你是 GraphQL 新手,本教程或许对你有所帮助。否则,让我们开始吧。
原文发布于我的博客
使用 Apollo、Node 和 GraphQL 构建服务器
在本指南中,我将使用 GitHub API 来获取要显示的数据,该操作将由使用 Apollo 和 Node.js 构建的 GraphQL 服务器完成。
为此,我们需要在终端上运行以下命令来设置一个新的 Node.js 项目。
yarn init
设置完成后,我们现在可以通过运行此命令来安装所需的软件包。
yarn add apollo-server graphql axios
太好了,我们现在有了构建服务器所需的一切,让我们首先app.js在根目录创建一个新文件,这将是我们服务器的入口点。
接下来,我们需要定义一个 Graphql schema,以反映我们数据应该呈现的方式。
GraphQL模式
模式描述了数据图的结构。它定义了一组类型,这些类型及其字段的数据来自后端数据存储。现在,让我们在文件中添加一个新的模式app.js。
app.js
const { ApolloServer, gql } = require("apollo-server")
const axios = require("axios")
const typeDefs = gql`
type User {
id: ID
login: String
avatar_url: String
}
type Query {
users: [User]
}
`
如您所见,我们并未使用 GitHub API 提供的所有数据。我们只需要用于 React 应用的引用键的 ID、登录信息和头像 URL。此外,我们还有一个查询,users用于返回用户数组。
现在我们有了 GraphQL schema,接下来需要构建相应的解析器来完成查询操作。
GraphQL解析器
解析器是一组函数的集合,用于帮助生成 GraphQL 查询的响应。所以,让我们在app.js文件中添加一个新的解析器。
app.js
const resolvers = {
Query: {
users: async () => {
try {
const users = await axios.get("https://api.github.com/users")
return users.data.map(({ id, login, avatar_url }) => ({
id,
login,
avatar_url,
}))
} catch (error) {
throw error
}
},
},
}
解析器必须按名称匹配相应的模式。因此,这里users指的是users我们模式中定义的查询。它是一个函数,借助 API 获取数据,并按axios预期返回 ID、登录名和头像 URL。
由于此操作可能需要一些时间才能完成,因此这里使用了 async/await 来逐步处理。
这样,我们就可以在下一节中创建 Apollo 服务器了。
创建 Apollo 服务器
如果你还记得的话,在我们从包中app.js导入的文件中,有一个构造函数,它接收一个对象作为参数。这个对象必须包含模式和解析器才能创建服务器。ApolloServerapollo-server
所以,我们app.js稍微调整一下ApolloServer。
app.js
const server = new ApolloServer({
typeDefs,
resolvers,
})
// typeDefs: typeDefs,
// resolvers: resolvers
server.listen().then(({ url }) => console.log(`Server ready at ${url}`))
这里,我们传递一个包含模式和解析器的对象作为参数,以ApolloServer创建服务器并监听它。这样一来,我们就拥有了一个可以正常工作的服务器。
您现在就可以开始体验 GraphQL Playground 并发送查询了,只需运行以下命令:
yarn start
您现在可以预览它http://localhost:400
- 完整
app.js文件
const { ApolloServer, gql } = require("apollo-server")
const axios = require("axios")
const typeDefs = gql`
type User {
id: ID
login: String
avatar_url: String
}
type Query {
users: [User]
}
`
const resolvers = {
Query: {
users: async () => {
try {
const users = await axios.get("https://api.github.com/users")
return users.data.map(({ id, login, avatar_url }) => ({
id,
login,
avatar_url,
}))
} catch (error) {
throw error
}
},
},
}
const server = new ApolloServer({
typeDefs,
resolvers,
})
server.listen().then(({ url }) => console.log(`Server ready at ${url}`))
单独一个服务器做不了什么,我们需要在package.json文件中添加一个启动脚本来启动服务器,正如你所猜测的那样。
package.json
// first add nodemon: yarn add nodemon --dev
"scripts": {
"start": "nodemon src/index.js"
}
至此,我们已经有了可以从 Github API 获取数据的服务器,现在是时候转移到客户端并使用这些数据了。
我们开始做吧
使用 React 构建客户端
我们首先需要做的就是创建一个新的 React 应用,方法是在终端中运行以下命令。
npx create-react-app client-react-apollo
接下来,我们需要安装 Apollo 和 GraphQl 软件包。
yarn add apollo-boost @apollo/react-hooks graphql
现在,我们可以通过更新index.js文件将 Apollo 与我们的 React 应用连接起来。
将 React 连接到 Apollo
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import ApolloClient from 'apollo-boost'
import { ApolloProvider } from '@apollo/react-hooks';
import App from './App';
import './index.css';
import * as serviceWorker from './serviceWorker';
const client = new ApolloClient({
uri: 'https://7sgx4.sse.codesandbox.io'
})
ReactDOM.render(
<React.StrictMode>
<ApolloProvider client={client}>
<App />
</ApolloProvider>
</React.StrictMode>,
document.getElementById('root')
);
serviceWorker.unregister();
如您所见,我们首先导入 `Apollo.json`ApolloClient和 `Apollo.json` ApolloProvider。前者用于告知 Apollo 获取数据时要使用的 URL。如果未uri向 `Apollo.json` 传递`URL` ApolloClient,它将使用当前域名加上 `<your_url>` /graphql。
后者是 `Provider`,它期望接收客户端对象,以便将 Apollo 连接到 React。
也就是说,我们现在可以创建一个显示数据的组件。
获取数据
App.js
import React from "react"
import { useQuery } from "@apollo/react-hooks"
import gql from "graphql-tag"
import "./App.css"
const GET_USERS = gql`
{
users {
id
login
avatar_url
}
}
`
这里,我们有一个简单的 GraphQL 查询,用于获取数据。稍后会将该查询传递useQuery给 Apollo,以告知其要获取哪些数据。
App.js
const User = ({ user: { login, avatar_url } }) => (
<div className="Card">
<div>
<img alt="avatar" className="Card--avatar" src={avatar_url} />
<h1 className="Card--name">{login}</h1>
</div>
<a href={`https://github.com/${login}`} className="Card--link">
See profile
</a>
</div>
)
此展示组件将用于显示用户。它从应用程序组件接收数据并将其显示出来。
显示数据
App.js
function App() {
const { loading, error, data } = useQuery(GET_USERS)
if (error) return <h1>Something went wrong!</h1>
if (loading) return <h1>Loading...</h1>
return (
<main className="App">
<h1>Github | Users</h1>
{data.users.map(user => (
<User key={user.id} user={user} />
))}
</main>
)
}
export default App
Apollo 提供的钩子useQuery函数接收 GraphQL 查询并返回三种状态:加载中、错误和数据。
如果数据获取成功,则将其传递给 User 组件;否则,抛出错误。
- 完整
App.js文件
import React from "react"
import { useQuery } from "@apollo/react-hooks"
import gql from "graphql-tag"
import "./App.css"
const GET_USERS = gql`
{
users {
id
login
avatar_url
}
}
`
const User = ({ user: { login, avatar_url } }) => (
<div className="Card">
<div>
<img alt="avatar" className="Card--avatar" src={avatar_url} />
<h1 className="Card--name">{login}</h1>
</div>
<a href={`https://github.com/${login}`} className="Card--link">
See profile
</a>
</div>
)
function App() {
const { loading, error, data } = useQuery(GET_USERS)
if (error) return <h1>Something went wrong!</h1>
if (loading) return <h1>Loading...</h1>
return (
<main className="App">
<h1>Github | Users</h1>
{data.users.map(user => (
<User key={user.id} user={user} />
))}
</main>
)
}
export default App
太棒了!至此,我们已经使用 React 和 Node JS 构建了一个全栈 Apollo GraphQL 应用。
在此处预览 Apollo GraphQL 服务器
在这里预览 React 应用
在这里找到源代码
感谢阅读