Найти тему
Codogenerator

Пробуем Apollo GraphQL с React JS

Это введение в то, как мы можем взаимодействовать с сервером Apollo GraphQL из внешнего интерфейса.

В этой статье мы поговорим о:

  • Базовых настройках, мы должны указать URL - адрес для нашего сервера и экземпляр клиента
  • query , Есть компоненты Query, которые мы можем использовать для запроса данных
  • мутации , мы можем выполнить мутации, используя компонент мутации
  • polling / explicitfetch, посмотрим как готовится polling, explicitly и fetching данных

Чтобы настроить приложение React с GraphQL, нам нужны библиотеки apollo-boost и react-apollo.

Apollo-boost предоставляет нам ApolloClient - нам нужно создать экземпляр данного URL.

React-apollo дает нам Higher Order Provider, которым нам нужно обернуть наше приложение. Сначала установим нужные пакеты:

yarn add react-apollo apollo-boost graphql

После того, как мы установили все, мы готовы все настроить. Перейдите к index.js и вставьте в файл следующее:

import React, { Component } from "react";
import ApolloClient from "apollo-boost";
import { ApolloProvider } from "react-apollo";
import Local from “./components/Local”;

const localGraphQL = "http://localhost:4000/graphql";

const client = new ApolloClient({
uri: localGraphQL
});

class App extends Component {
render() {
return (
<ApolloProvider client={client}>
<div>
<h2>My first Apollo app </h2>
</div>
</ApolloProvider>
);
}
}
export default App;

Мы сначала создаем экземпляр ApolloClient и в инициализации сообщаем url до нашего сервера GraphQL.

Во-вторых, мы обертываем все приложение нашим ApolloProvider и передаем в качестве аргумента экземпляр класса client.

Теперь мы готовы к взаимодействию с нашим сервером GraphQL.

#Query

Чтобы иметь возможность запрашивать данные с сервера Apollo, нам нужно сделать три вещи:

  • Написать наш gql запрос
  • Используя компонент Query, который нам предоставляет react-apollo запросить данные
  • Осуществить рендеринг данных

Чтобы написать наш gql запрос, нам нужно импортировать, graphql-tag, а затем написать запрос GraphQL, например, так:

const getRates = gql`
{
rates(currency: “USD”) {
currency
rate
}
}`;

После этого нам нужно импортировать Query компонент из react-apollo и в качестве входного аргумента передать только что определенный запрос, например так:

const Data = () => (
<Query query={getRates} >
// render the query results
</Query>
);

Теперь, когда мы понимаем свойства и как мы можем их использовать, давайте соберем все вместе:

import React from "react";
import { Query } from "react-apollo";
import gql from "graphql-tag";

const getRates = gql`
{
products(type: "DVD") {
name
price
}
}`;

const Data = () => (
<Query query={getRates} >
{({ loading, error, data }) => {
if (loading) return <p>Loading…</p>;
if (error) return <p>Error :(</p>;
return data.products.map(({ name, price }) => (
<div key={name}>
<p>{`${name}: ${price}`}</p>
</div>
));
}}
</Query>
);
export default Data;

Теперь мы узнали, как мы можем читать данные с сервера GraphQL и представлять их нашему интерфейсу.

#Polling

Порой данные удобно получать непрерывно через определенные промежутки времени без явного перехода на определенную страницу или нажатия на кнопку для запуска запроса GET.

Например, в приложении чата, чтобы достичь ощущения реального времени. Используя тот же самый Query компонент, но установив аргумент pollInterval (число миллисекунд), мы будем получать данные на регулярной основе . Давайте посмотрим, как это может выглядеть:

import React from "react";
import { Query } from "react-apollo";
import gql from "graphql-tag";

const GET_DATA = gql`
{
products {
name
id
}
}`;

const DataPull = () => (
<Query query={GET_DATA} pollInterval={500}>
{(loading, error, data, startPolling, stopPolling) => {
if (loading) return null;
if (error) return `Error!: ${error}`;
return (
<React.Fragment>
{data.products.map(p => <div>{p.name}</div>)}
<button onClick={()=> startPolling()}>Start polling</button>
<button onClick={() => stopPolling()}>Stop polling</button>
</React.Fragment>;
)
}}
</Query>
);
export default DataPull;

Выше мы ввели следующие новые концепции:

  • pollInterval , это то, что ожидает интервал опроса в миллисекундах, как вы можете видеть, мы устанавливаем 500, например, полсекунды
  • startPolling, это функция, в которой мы можем начать опрос заново, если мы предварительно остановили его
  • stopPolling, это функция, которая позволяет нам останавливать опрос в любое время

#Refetch

Для того, чтобы держать данные в актуальном состоянии в процессе работы пользователя с интерфейсом, нам надо получать их заново.

Давайте посмотрим, как мы можем использовать метод refetch:

import React from "react";
import { Query } from "react-apollo";
import gql from "graphql-tag";

const GET_DATA = gql`
{
products {
name
id
}
}`;

const Refetch = () => (
<Query query={GET_DATA}>
{(loading, error, data, refetch) => {
if (loading) return null;
if (error) return `Error!: ${error}`;
return (
<React.Fragment>
<div>
{data.prop}
<button onClick={() => refetch()}>Fetch</button>
</div>
</React.Fragment>
)
}}
</Query>
);
export default Refetch;

Мы добавили аргумент в функцию следующим образом:

{(loading, error, data, refetch) => {}}

Мы можем смело вызывать этот метод навесив его на кнопку в нашей разметке следующим образом:

<button onClick={() => refetch()}>Fetch</button>

#Mutation

Когда нам необходимо изменить какие-либо данные, например, добавить нового пользователя мы прибегаем к запросам на мутацию. Итак, давайте начнем с первого, нашего запроса:

Мы будем использовать gql хелпер из graphql-tag библиотеки для создания нашего запроса, используя ключевое слово mutation, после чего присваиваем мутации имя и указываем ее входной параметр $person. На данный момент у нас есть следующий запрос:

const ADD_PERSON = gql`
mutation AddPerson($person: Person!) {
}`;

Теперь мы готовы вызвать фактическую мутацию addPerson, которую мы определили на нашем сервере GraphQL. Ваш запрос на мутацию теперь должен выглядеть так:

const ADD_PERSON = gql`
mutation AddPerson($person: Person!) {
addPerson(person: $person) {
id
}
}`;

Следующим шагом является использование запроса на мутацию, работая с нашим компонентом React Mutation.

Давайте начнем с первого использования Mutation компонента и установим его mutation свойство следующим образом:

import React from "react";
import { Mutation } from "react-apollo";
import gql from "graphql-tag";

const ADD_PERSON = gql`
mutation AddPerson($person: Person!) {
addPerson(person: $person) {
id
}
}`;

<Mutation mutation={ADD_PERSON}></Mutation>

Ожидается, что приведенная выше функция вернет JSX. Ожидается, что мы определим часть JSX, которая позволит нам использовать следующее:

  • addPerson() , эта функция, которая будет выполнять запрос мутации.
  • loading , это логическое значение сообщит нам, осуществляется ли наша мутация или нет, используйте это значение, чтобы запускать спиннер или скрывать его
  • data , это данные, которые возвращаются после завершения запроса на мутацию

Теперь, когда мы понимаем, для чего предназначены параметры функции, давайте определим наш JSX. Когда мы хотим собирать данные, принято определять форму, поэтому давайте сделаем это:

<form onSubmit={e => {
e.preventDefault();
addPerson({ variables: { person: { name: input.value } } });
input.value = “”;
}} >
<input ref={node => { input = node; }} />
<button type=”submit”>Add Person</button>
{loading &&
<div>adding person…</div>
}
{ data &&
<div>response data</div>
}
{ error &&
<div>Error adding person…</div>
}
</form>

Вот и все, что нужно, чтобы вызвать мутацию с некоторыми параметрами и показать ответ, будь то фактические данные или ошибка.

Ниже приведен весь код целиком.

import React from "react";
import { Mutation } from "react-apollo";
import gql from "graphql-tag";

const ADD_PERSON = gql`
mutation AddPerson($person: Person!) {
addPerson(person: $person) {
id
}
}`;

const DataInput = () => {
let input;
return (
<Mutation mutation={ADD_PERSON}>
{(addPerson, { data, loading, error }) => (
<div>
<form onSubmit={e => {
e.preventDefault();
addPerson({ variables: { person: { name: input.value } } });
input.value = “”;
}} >
<input ref={node => { input = node; }} />
<button type=”submit”>Add Person</button>
{loading &&
<div>adding person…</div>
}
{ data &&
<div>response data</div>
}
{ error &&
<div>Error adding person…</div>
}
</form>
</div>
)}
</Mutation>)
}

export default DataInput;

#Резюме

Мы рассмотрели различные способы взаимодействия с данными и запросы к серверной части.

  • Выборка данных, если мы используем Query компонент, мы можем получить данные, заполнив его query атрибут gql запросом
  • Опрос данных, если мы установим атрибут pollInterval для Query компонента, мы сможем опрашивать наш бэкэнд GraphQL с интервалом
  • Явное извлечение данных, используя дополнительный аргумент refetch, мы можем явно извлекать данные, когда хотим
  • Запуская мутации, мы узнали, что можем использовать Mutation компонент для проведения мутаций.

Рад что дочитали статью до самого конца и надеюсь вы смогли найти в ней что-то интересное и полезное. Ставьте лайки, подписывайтесь на канал и, конечно, делитесь с коллегами материалом. Успешно "покодить"!