本文共 10350 字,大约阅读时间需要 34 分钟。
This is a second part of a set articles exploring GraphQL technology. Refer to for the server setup which is necessary for this client side article.
这是探索GraphQL技术的系列文章的第二部分。 有关此客户端文章所必需的服务器设置,请参阅 。
In this section, we focus on how to implement GraphQL on a React client using Apollo. We begin by setting up a simple React Component. First we will have an app component which will be the parent component and another component to render the list of channels and a third component for creating new channels.
在本节中,我们重点介绍如何使用Apollo在React客户端上实现GraphQL。 我们首先建立一个简单的React Component。 首先,我们将有一个app组件,它将是父组件,另一个是呈现频道列表的组件,第三个是用于创建新频道的组件。
We begin by defining a simple directory structure for our react application.
我们首先为我们的react应用程序定义一个简单的目录结构。
app/├── src/ └── app/ ├── components/ ├── ChannelList/ └── ChannelList.jsx └── CreateChannel/ └── CreateChannel.jsx ├── app.jsx ├── public/ └── index.html ├── style/ └── style.scss ├── .eslintrc.js ├── webpack.config.js └── package.json
We create a simple functional component to show a list of channels from the server.
我们创建了一个简单的功能组件,以显示来自服务器的频道列表。
// src/app/components/ChannelList/ChannelList.jsximport React from 'react';const ChannelsList = () => { ... };
To hook up our component with our query, we require the Apollo client and some other helper packages from react-apollo.
要将我们的组件与查询连接起来,我们需要Apollo客户端和react-apollo的其他一些帮助程序包。
npm i -S react-apollo #yarn add react-apollo
react-apollo
allows you decorate your components with a higher order component called graphql
to get your GraphQL data into the component. React Apollo also comes with ApolloClient, which is the core of Apollo that handles all the data fetching, caching and optimistic updates. To setup the Apollo Client, we will need to import the required components.
react-apollo
允许您使用称为graphql
高阶组件来装饰组件,以将GraphQL数据放入组件中。 React Apollo还附带了ApolloClient,它是Apollo的核心,负责处理所有数据提取,缓存和乐观更新。 要设置Apollo客户端,我们需要导入所需的组件。
// src/app/components/ChannelList/ChannelList.jsx...import { gql, graphql} from 'react-apollo';...
Next, we decorate our component with a GraphQL higher-order component that takes the query and passes the data to the component:
接下来,我们用GraphQL高阶组件装饰组件,该组件接受查询并将数据传递给组件:
// src/app/components/ChannelList/ChannelList.jsx...const channelsListQuery = gql` query ChannelsListQuery { channels { id name } } `;const ChannelsListWithData = graphql(channelsListQuery)(ChannelsList);export default ChannelsListWithData;
The gql
template tag is what you use to define GraphQL queries in your Apollo Client apps. It parses your GraphQL query which may then be consumed by Apollo Client methods. Whenever Apollo Client is asking for a GraphQL query you will always want to wrap it in a gql template tag.
gql
模板标记是用于在Apollo Client应用程序中定义GraphQL查询的标记。 它解析您的GraphQL查询,然后Apollo Client方法可能会使用它。 每当Apollo Client请求GraphQL查询时,您总是希望将其包装在gql模板标签中。
When wrapped in the graphql HOC, our ChannelsList component will receive a prop called data
, which will contain channels when it’s available, or error when there is an error. Data also contains a loading property, which is true when Apollo Client is still waiting for data to be fetched; this reduces the amount of code which we would otherwise write to monitor the state of the request. We can utilize the data in out component to notify the user accordingly about the state of the API request. We can then render the channels if they are fetched successfully.
当包装在graphql HOC中时,我们的ChannelsList组件将接收一个名为data
的道具,该道具将在可用时包含通道,或者在出现错误时包含错误。 数据还包含加载属性,当Apollo Client仍在等待获取数据时,此属性为true; 这减少了我们将编写的用于监视请求状态的代码量。 我们可以利用数据输入输出组件来通知用户有关API请求状态的信息。 如果成功获取通道,我们便可以渲染它们。
// src/app/components/ChannelList/ChannelList.jsx...const ChannelsList = ({ data: { loading, error, channels }}) => { if (loading) { returnFetching Data...
; } if (error) { return{
error.message}; } return
We then set up the main app component that will render the ChannelList component.
然后,我们设置将呈现ChannelList组件的主应用程序组件。
The app component is responsible for setting up the Apollo client and a network interface which defines the a http connection of our API.
该应用程序组件负责设置Apollo客户端和一个网络接口,该接口定义了我们API的http连接。
// src/app/app.jsximport { ApolloClient, ApolloProvider, createNetworkInterface} from 'react-apollo’;import ChannelList from './components/ChannelList/ChannelList';const networkInterface = createNetworkInterface({ uri: 'http://localhost:7700/graphql',});const client = new ApolloClient({ networkInterface,});let app = document.querySelector('#app');render(, app) React , GraphQL , Apollo
The createNetworkInterface()
function creates a simple HTTP network interface using the provided configuration object which includes the URI Apollo will use to fetch data from. The ApolloProvider
HOC provides a client instance to a React component tree, similar to react-redux
Provider
component. It provides an ApolloClient instance to all of your GraphQL components that use the graphql
function. If you do not add this component to the root of your React tree then your components enhanced with Apollo capabilities will not be able to function.
createNetworkInterface()
函数使用提供的配置对象创建一个简单的HTTP网络接口,该配置对象包括Apollo将用于从中获取数据的URI。 ApolloProvider
HOC向React组件树提供客户端实例,类似于react-redux
Provider
组件。 它为使用graphql
函数的所有GraphQL组件提供ApolloClient实例。 如果您不将此组件添加到React树的根目录,那么使用Apollo功能增强的组件将无法运行。
A part from the client
prop, ApolloProvider
may also take an optional store which is an instance of Redux if we wish to include Redux in your project too. This ensures that we only use one HOC ApolloProvider
and not react-redux Provider
.
如果我们也希望将Redux包含在您的项目中,则ApolloProvider
可能是Redux实例的一部分,它是client
道具的一部分。 这确保了我们仅使用一个HOC ApolloProvider
而不使用react-redux Provider
。
When we navigate to and issue our query, we see the following results.
当我们导航到并发出查询时,我们看到以下结果。
Subsequently when we open our application at , we can confirm the expected results.
随后,当我们在打开应用程序时,我们可以确认预期结果。
Mutations are aimed at creating, updating or deleting of records. They basically perform the write operations equivalents in CRUD operations. In this section, we will create a mutation that creates a new channel. We will create a new component CreateChannel
that will be responsible for creating the new channels. It’s a simple component that provides an input field and an event handler for the input.
突变旨在创建,更新或删除记录。 它们基本上执行与CRUD操作等效的写操作。 在本节中,我们将创建一个创建新频道的变体。 我们将创建一个新组件CreateChannel
,它将负责创建新通道。 它是一个简单的组件,为输入提供输入字段和事件处理程序。
// src/app/components/CreateChannel/CreateChannel.jsx...const CreateChannel = ({ mutate}) => { const handleKeyUp = (evt) => { if (evt.keyCode === 13) { evt.persist(); mutate({ variables: { name: evt.target.value } }) .then( res => { evt.target.value = ''; }); } }; return ( );};const CreateChannelMutation = gql` mutation addChannel($name: String!) { addChannel(name: $name) { id name } }`;const CreateChannelWithMutation = graphql( CreateChannelMutation)(CreateChannel);export default CreateChannelWithMutation;
Using graphql with mutations makes it easy to bind actions to your components. Unlike queries, which provide a complicated object with lots of metadata and methods, mutations provide only a simple function to the wrapped component, in a prop called mutate. Most mutations will require arguments in the form of query variables.
使用带有突变的graphql可以轻松地将操作绑定到组件。 与为复杂对象提供大量元数据和方法的查询不同,在称为mutate的道具中,变异仅为包装的组件提供了简单的功能。 大多数变异将需要查询变量形式的参数。
...mutate({ variables: { name: evt.target.value }})...
In the above snippet, we pass a name
variable into mutate
which will be passed to the actual query and will send to the server. The addChannel
query below takes in the name
variable passed in as part of the variables in mutate
above.
在上面的代码片段中,我们将一个name
变量传递给mutate
,该变量将传递给实际查询并发送给服务器。 下面的addChannel
查询接受作为上面mutate
变量的一部分传入的name
变量。
...const CreateChannelMutation = gql` mutation addChannel($name: String!) { addChannel(name: $name) { id name } }`;...
We then wire it up in the main app component.
然后,我们将其连接到主应用程序组件中。
// src/app/app.jsx…import CreateChannel from './components/CreateChannel/CreateChannel’;… render(... , app)...
To make our input component call a GraphQL mutation, we have to wire it up with the GraphQL higher order component (HOC) from react-apollo. For mutations, the graphql HOC passes down a mutate prop, which we’ll call to execute the mutation. Inputting a new value and reloading the page shows the new channel.
为了使我们的输入组件称为GraphQL突变,我们必须将其与react-apollo中的GraphQL高阶组件(HOC)连接起来。 对于突变,graphql HOC传递了一个突变道具,我们将其称为执行突变。 输入新值并重新加载页面将显示新频道。
GraphQL is a pretty alternative to the conventional REST implementations. Looking at the above application and making a comparison with Redux, we can see that the amount of code used is reduced by a very large percentage. We can avoid the whole concept of writing actions and reducers and configuring stores.
GraphQL是传统REST实现的不错替代方案。 查看上面的应用程序并与Redux进行比较,我们可以看到使用的代码量减少了很大的百分比。 我们可以避免编写动作和缩减器以及配置商店的整个概念。
In the next and final part of this series, we will focus on how to update the UI in realtime; how to perform operations and have the browser automatically update in three different ways; refetching queries, manually updating the client state based on the mutation result and using GraphQL subscriptions to notify the client about the updates. Unlike conventinal REST updates, GraphQL provides a more real-time view using subscriptions; updating data in one browser will automatically show changes in the next browser like push notifications.
在本系列的下一个也是最后一部分,我们将重点介绍如何实时更新UI。 如何执行操作并使浏览器以三种不同方式自动更新; 重新获取查询,基于变异结果手动更新客户端状态,并使用GraphQL订阅将更新通知给客户端。 与常规的REST更新不同,GraphQL使用订阅提供了更实时的视图。 在一个浏览器中更新数据将自动在下一个浏览器中显示更改,例如推送通知。
翻译自:
转载地址:http://qsuwd.baihongyu.com/