Введение в Apollo Client с React на GraphQL
Russian (Pусский) translation by Anna k.Ivanova (you can also view the original English article)



Недавно GraphQL набрал популярность и, скорее всего, заменит Rest API. В этом уроке мы будем использовать Apollo Client для связи с API-интерфейсом GitHub. Мы объединим Apollo Client с ReactJS, но вы можете использовать его и с несколькими другими клиентскими платформами.
В этом руководстве не рассматривается процесс запуска проекта React, но вы можете использовать приложение create-response-app чтобы начать работать.
После того, как у нас появится готовое приложение react, необходимо установить необходимые модули.
Установка модулей
Следующая строка устанавливает все необходимые модули.
1 |
npm install apollo-client-preset react-apollo graphql-tag graphql --save |
Теперь мы можем предоставить наш компонент клиенту.
Предоставление клиенту компонента
Вы можете предоставить клиента в любой точке иерархии компонентов React. Тем не менее, всегда рекомендуется использовать компонент, обертывающий все ваше приложение, клиентом.
1 |
import React from 'react'; |
2 |
import ReactDOM from 'react-dom'; |
3 |
import App from './App'; |
4 |
|
5 |
import { ApolloProvider } from 'react-apollo'; |
6 |
import { ApolloClient } from 'apollo-client'; |
7 |
import { HttpLink } from 'apollo-link-http'; |
8 |
import { InMemoryCache } from 'apollo-cache-inmemory'; |
9 |
|
10 |
const token = "YOUR_TOKEN"; |
11 |
|
12 |
const httpLink = { |
13 |
uri: 'https://api.github.com/graphql', |
14 |
headers: { |
15 |
authorization: `Bearer ${token}` |
16 |
}
|
17 |
};
|
18 |
|
19 |
const client = new ApolloClient({ |
20 |
link: new HttpLink(httpLink), |
21 |
cache: new InMemoryCache() |
22 |
});
|
23 |
|
24 |
ReactDOM.render(<ApolloProvider client={client}><App/></ApolloProvider>, document.getElementById('root')); |
Выше мы видим, что мы определили uri для GitHub, а также использовали определенный токен для headers. Вы должны использовать свой собственный токен, созданный GitHub. Поэтому не забудьте заменить его YOUR_TOKEN.
В этом примере мы определили маркер API на стороне клиента. Однако вы не должны публиковать свой API токен. Поэтому всегда полезно хранить его на сервере, отделенном от клиентской стороны.
Обратите внимание, что мы завернули компонент <App/> с помощью ApolloProvider и использовали переменную client, созданную для свойства client.
Приложение GraphiQL
Прежде чем погрузиться в запросы, я хочу отметить, что есть очень удобный инструмент под названием GraphiQL для тестирования ваших запросов GraphQL. Прежде чем продолжить, убедитесь, что вы скачали его.
Как только вы откроете GraphiQL, вам нужно установить GraphQL Endpoint и HTTP Headers.
GraphQL Endpoint: https://api.github.com/graphql
Header Name: Authorization
Header Value: Bearer YOUR_TOKEN
Конечно, вам нужно заменить YOUR_TOKEN на свой токен. Не забудьте включить Bearer перед токеном при определении Header Value.
Если вы не хотите загружать приложение, вы также можете использовать онлайн-интерфейс GraphQL API Explorer для GitHub.
Запросы GraphQL
В отличие от REST API с несколькими API ендпоинтами, GraphQL имеет только один ендпоинт, и вы получаете только то, что определено вашим запросом.
Документация GigHub's GraphQL API даcт вам больше информации.
Кроме того, лучшая часть приложения GraphiQL заключается в том, что оно дает вам доступ к документации для запросов прямо внутри приложения. Вы можете увидеть боковую панель справа - Docs.
Начнем с простейшего запроса:
1 |
query{ |
2 |
viewer{ |
3 |
login
|
4 |
}
|
5 |
}
|
Этот запрос возвращает вам информацию для входа в программу просмотра. В этом случае зритель - это вы, поскольку вы использовали свой собственный токен API.
В этом уроке я не буду приводить подробную информацию о запросах. Вы всегда можете обратиться к документации и попробовать запросы в инструментах GraphQL, чтобы узнать, получаете ли вы правильные данные.
Давайте используем следующий запрос для остальной части учебника.
1 |
query($name: String!){ |
2 |
search(query: $name, last: 10, type: REPOSITORY) { |
3 |
edges { |
4 |
node { |
5 |
... on Repository { |
6 |
id
|
7 |
name
|
8 |
description
|
9 |
url
|
10 |
}
|
11 |
}
|
12 |
}
|
13 |
}
|
14 |
}
|
Этот запрос ищет последние 10 репозиториев, соответствующих определенной строке ввода, которые мы определим в нашем приложении.
Он возвращает id, name, description и url для каждого результата.
Использование запроса GraphQL в компоненте React
Нам нужно импортировать два модуля ниже в наш компонент React, чтобы иметь возможность определять запрос в компоненте, а затем передавать результаты компоненту в качестве props.
1 |
import gql from 'graphql-tag'; |
2 |
import { graphql } from 'react-apollo'; |
Здесь мы присвоили наш запрос константной переменной, но мы еще не определили параметр name.
1 |
const repoQuery = gql` |
2 |
query($name: String!){
|
3 |
search(query: $name, last: 10, type: REPOSITORY) {
|
4 |
edges {
|
5 |
node {
|
6 |
... on Repository {
|
7 |
id
|
8 |
name
|
9 |
description
|
10 |
url
|
11 |
}
|
12 |
}
|
13 |
}
|
14 |
}
|
15 |
}
|
16 |
`
|
Теперь мы завершаем наш компонент с graphql HOC (Higher Order Component), чтобы определить параметры запроса, выполнить запрос и затем передать результат в качестве props для нашего компонента.
1 |
const AppWithData = graphql( |
2 |
repoQuery, |
3 |
{
|
4 |
options: { |
5 |
variables: { |
6 |
name: "tuts" |
7 |
}
|
8 |
}
|
9 |
}
|
10 |
)(App) |
Ниже приведен финальный вариант нашего компонента.
1 |
import React, { Component } from 'react'; |
2 |
|
3 |
import gql from 'graphql-tag'; |
4 |
import { graphql } from 'react-apollo'; |
5 |
|
6 |
class App extends Component { |
7 |
render() { |
8 |
return ( |
9 |
<div> |
10 |
</div> |
11 |
);
|
12 |
}
|
13 |
}
|
14 |
|
15 |
const repoQuery = gql` |
16 |
query($name: String!){
|
17 |
search(query: $name, last: 10, type: REPOSITORY) {
|
18 |
edges {
|
19 |
node {
|
20 |
... on Repository {
|
21 |
id
|
22 |
name
|
23 |
description
|
24 |
url
|
25 |
}
|
26 |
}
|
27 |
}
|
28 |
}
|
29 |
}
|
30 |
`
|
31 |
|
32 |
const AppWithData = graphql( |
33 |
repoQuery, |
34 |
{
|
35 |
options: { |
36 |
variables: { |
37 |
name: "tuts" |
38 |
}
|
39 |
}
|
40 |
}
|
41 |
)(App) |
42 |
|
43 |
export default AppWithData; |
Обратите внимание, что мы экспортируем не фактический компонент App, а завернутый компонент, который является AppWithData.
Проверка данных в консоли
Давайте продолжим и добавим {console.log (this.props)} к методу render вашего компонента.
1 |
class App extends Component { |
2 |
render() { |
3 |
console.log(this.props) |
4 |
return ( |
5 |
<div> |
6 |
</div> |
7 |
);
|
8 |
}
|
9 |
}
|
Когда вы проверите консоль своего браузера, вы увидите два лога с объектами.
Внутри каждого объекта вы увидите свойство data. Это обеспечивается нашим компонентом через graphql HOC.
Обратите внимание, что первый журнал имеет свойство loading: true внутри data, а второй лог имеет loading: false и новый объект с именем search, который является именно теми данными, которые мы хотели получить.
Отображение данных
Давайте напишем JSX для отображения извлеченных данных.
Поскольку объект search изначально не существует, мы не можем напрямую попытаться его отобразить. Поэтому сначала нам нужно проверить, были ли получены данные, и объект search готов к использованию.
Для этого мы просто будем использовать информацию из loading, предоставленную внутри свойства data.
Если loading равно true, мы просто выводим текст «Loading», иначе сами данные.
1 |
class App extends Component {
|
2 |
render() {
|
3 |
return ( |
4 |
<div> |
5 |
{this.props.data.loading === true ? "Loading" : this.props.data.search.edges.map(data =>
|
6 |
<ul key={data.node.id}>
|
7 |
<li style={{fontWeight: 'bold'}}><a href={data.node.url}>{data.node.name}</a></li>
|
8 |
<li>{data.node.description}</li>
|
9 |
</ul> |
10 |
)} |
11 |
</div> |
12 |
); |
13 |
} |
14 |
} |
Я использовал тернарный оператор ?: для базовых встроенных условных выражений. Если loading равно true, мы показываем «Loading», а если false, мы используем функцию map для итерации по нашему массиву данных, чтобы отображать информацию внутри элементов <ul> и <li>.
Это всего лишь базовый пример. Вы можете использовать обычную инструкцию if-else и возвращать разные результаты для вашего метода render.
Вы можете проверить репозиторий Apollo-Client-with-React, клонировать его на свой компьютере и поиграть с ним.
P.S. Не забудьте заменить переменную token на свой собственный токен API для GitHub.
Заключение
Мы рассказали о том, как начать работу с Apollo Client для React. Мы установили необходимые модули, настроили клиент, а затем предоставили его нашему компоненту в верхней части иерархии компонентов. Мы научились быстро тестировать запросы GraphQL, прежде чем внедрять их в нашем реальном приложении. Наконец, мы интегрировали запрос в компонент React и отобразили извлеченные данные.



