Статьи

Интегрировать приложение React Native с GraphQL и клиентом Apollo

Вы заинтересованы в создании приложения React Native , которое использует конечные точки API GraphQL? Тогда вы должны прочитать этот урок. Вы узнаете, как использовать Apollo для создания клиентского приложения GraphQL с React Native и Expo.

Apollo имеет целую экосистему для создания приложений GraphQL. Вы можете использовать его для разработки клиентских и серверных приложений по отдельности. Apollo имеет больше возможностей и поддержки, чем его конкуренты с открытым исходным кодом в GraphQL для мира JavaScript.

Начиная

Для начала создайте новое приложение React Native с помощью следующей команды:

npx expo init expo-apollo-demo

# after the project directory is generated
cd expo-apollo-demo

Теперь давайте установим все  npm зависимости, которые будут использоваться в этом демонстрационном приложении. Вы узнаете о каждой отдельной зависимости, когда это необходимо, в оставшейся части руководства. Обратите внимание, что некоторые из этих зависимостей являются одноранговыми, и вы не можете использовать их напрямую.

yarn add apollo-client apollo-cache-inmemory graphql-tag apollo-link-rest apollo-link graphql graphql-anywhere qs

Вам также может понравиться: почему и когда использовать GraphQL .

После того, как все зависимости установлены, давайте добавим компонент заголовка в  App.js файл и заменим остальное содержимое, которое поставляется по умолчанию, приложением Expo.

//App.js
import React, { Component } from 'react'
import { StyleSheet, Text, View } from 'react-native'

class App extends Component {
  render() {
    return (
      <View style={styles.container}>
        <View style={styles.header}>
          <Text style={styles.headerText}>Headlines App</Text>
        </View>
        <View style={styles.contentContainer}>
          <Text>Open up App.js to start working on your app!</Text>
        </View>
      </View>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff'
  },
  header: {
    marginTop: 50,
    alignItems: 'center',
    borderBottomWidth: StyleSheet.hairlineWidth
  },
  headerText: {
    marginBottom: 5,
    fontSize: 30,
    fontWeight: 'bold'
  },
  contentContainer: {
    marginTop: 30,
    alignItems: 'center',
    justifyContent: 'center'
  }
})

export default App

Просто чтобы увидеть, все ли работает, вернитесь в окно терминала и выполните команду,  yarn start чтобы запустить клиентское приложение Expo. Нажмите,  i если вы используете симулятор iOS или  a эмулятор Android.

При первом визуализации компонента App вы получите следующий вывод:

Начальный вывод

Настройте клиент Apollo в собственном приложении React

Создайте новый файл с именем  Client.js inside  src/graphql. Этот файл будет содержать конфигурацию, касающуюся клиента Apolloapollo-client Пакет, наряду с  apollo-cache-inmemory и  apollo-link, это полнофункциональный GraphQL клиент , который может быть интегрирован в Реагировать или Реагировать Родные приложения.

Для начала откройте вновь созданный файл и импортируйте следующие операторы.

import { ApolloClient } from 'apollo-client'
import { InMemoryCache } from 'apollo-cache-inmemory'
import { RestLink } from 'apollo-link-rest'

apollo-link-rest Пакет позволяет использовать сторонние API — интерфейсы , которые не имеют GraphQL конечных точек или Отдыхайте конечные точки , но то , что вы хотите , чтобы передать их в GraphQL.

Конечная точка API, которую вы собираетесь использовать в этом руководстве, является конечной точкой REST и известна как  News API . Не забудьте получить  ключ API, войдя сюда  ( это бесплатно ).

Добавьте RestLink для конечной точки Rest API и pass  headers, который представляет собой объект, представляющий значения, которые будут отправлены в качестве заголовков в запросе. Значение, которое необходимо отправить при запросе данных от конечной точки API, является ключом API.

const restLink = new RestLink({
  uri: 'https://newsapi.org/v2/',
  headers: {
    Authorization: '47e036d83ccc4058b1f85362bc2be1f4'
  }
})

Затем добавьте следующую конфигурацию с кэшем по умолчанию и  RestLink завершите настройку клиента Apollo.

export const client = new ApolloClient({
  link: restLink,
  cache: new InMemoryCache()
})

Отправка запроса в конечную точку REST с помощью Apollo

В этом разделе мы напишем запрос для подключения клиента Apollo для получения результатов с конечной точки API REST. Однако запрос будет выполнен на языке запросов GraphQL с помощью  graphql-tag.

В  src/graphql каталоге создайте новый файл с именем  Queries.js и импортируйте  graphql-tag.

import gql from 'graphql-tag`

Затем экспортируйте, используя шаблон из  gql тега, и добавьте запрос, который будет получать верхние заголовки из API новостей. Используя  @rest директиву Apollo управляет тем, как анализировать этот запрос.

export const Headlines = gql`
  query TopHeadlines {
    headlines
      @rest(
        type: "HeadlinesPayload"
        path: "top-headlines?country=us&category=technology"
      ) {
      totalResults
      articles @type(name: "ArticlePayload") {
        title
        publishedAt
        url
        urlToImage
        source @type(name: "SourcePayload") {
          name
        }
      }
    }
  }
`

Чтобы использовать запрос, импортируйте его в  App.js файл вместе с настроенным клиентом Apollo, добавив следующие два оператора импорта.

import { client } from './src/graphql/Client'
import { Headlines } from './src/graphql/Queries'

Запрос должен выполняться всякий раз, когда компонент собирается монтировать, таким образом, используя метод жизненного цикла,  componendDidMount вы можете вызвать запрос для получения результатов. А пока давайте запишем результат в  console.log оператор и посмотрим, какие результаты дает конечная точка.

requestHeadlines() Функция будет вызывать запрос с использованием Apollo Client. Вызов запроса просто завершается добавлением обещания.

class App extends Component {
 componentDidMount() {
 this.requestHeadlines()
 }

 requestHeadlines = () => {
 client
 .query({
 query: Headlines
 })
 .then(response => {
 console.log('RESPONSE ==>', response)
 })
 .catch(error => {
 console.log('ERROR ==>', error)
 })
 }

С клиентом Expo существует возможность  удаленной отладки JS . Он открывает вкладку консоли в инструментах разработчика браузера и позволяет видеть результаты операторов журнала ( как в веб-разработке ).

Вот результат вышеуказанного запроса. При вызове он выбирает 20 объектов заголовка в массив со всеми запрошенными полями.

Извлечение 20 заголовочных объектов

Добавление индикатора активности

Внимательно посмотрите на изображение выше в предыдущем разделе. В ответе вы найдете поле с именем,  loading которое сообщает приложению, что запрос выполнен для извлечения данных. Это может быть полезно при добавлении индикатора активности для отображения того же сообщения конечному пользователю в реальном мобильном приложении.

Импортируйте  ActivityIndicator компонент из Reaction-native и добавьте в него следующее состояние  App .

import { StyleSheet, Text, View, ActivityIndicator } from 'react-native'

// ... inside App component
state = {
  loading: true
}

Затем измените метод рендеринга, чтобы он отображал компонент индикатора активности, когда переменная состояния  loading имеет значение true.

render() {
 const { loading } = this.state
 if (loading) {
 return (
 <View
 style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
 <ActivityIndicator size='large' />
 </View>
 )
 }

 return (
 <View style={styles.container}>
 <View style={styles.header}>
 <Text style={styles.headerText}>Headlines App</Text>
 </View>
 <View style={styles.contentContainer}>
 <Text>Open up App.js to start working on your app!</Text>
 </View>
 </View>
 )
 }

Вы получите следующий вывод:

Чтобы заставить его останавливаться и вести себя так, как требует приложение, обновите состояние,  loading когда обещание разрешается внутри метода запроса.

.then(response => {
 console.log('RESPONSE ==>', response)
 this.setState({ loading: response.loading })
})

Обновите клиент Expo, и вы заметите, что через несколько секунд при получении данных индикатор загрузки исчезнет, ​​и экранный интерфейс отобразится, как и раньше.

Отображение статей из API

Вы все настроены на отображение отдельного компонента статьи, который выбирается из конечной точки API. Добавьте еще одну переменную в объект состояния с именем  articles. Чтобы отобразить список данных, давайте использовать  FlatList компонент из Reaction-native.

import {
  StyleSheet,
  Text,
  View,
  ActivityIndicator,
  FlatList
} from 'react-native'

// inside the App component
state = {
  loading: true,
  // add this
  articles: []
}

Затем обновите  articles состояние с помощью массива из ответа, когда обещание будет разрешено.

this.setState({
  loading: response.loading,
  // add this
  articles: response.data.headlines.articles
})

FlatList Компонент требует три атрибута для отображения списка элементов данных.

  • data: массив данных, который предоставляется переменной состояния  articles.
  • renderItem: содержит JSX для каждого элемента в массиве данных, для которого давайте создадим новый компонент, который будет вызываться  Article в отдельном файле в следующем разделе.
  • keyExtractor: используется для извлечения уникального ключа для данного элемента по указанному индексу, для которого давайте будем использовать URL каждой статьи, для которого он будет уникальным.

Тем не менее, измените  render функцию, как показано ниже:

return (
  <View style={styles.container}>
    <View style={styles.header}>
      <Text style={styles.headerText}>Headlines App</Text>
    </View>
    <View style={styles.contentContainer}>
      <FlatList
        data={articles}
        renderItem={({ item }) => <Article {...item} />}
        keyExtractor={item => `${item.url}`}
      />
    </View>
  </View>
)

Небольшая модификация стилей:

container: {
 flex: 1,
 backgroundColor: '#fff',
 marginBottom: 70
 },

 // ... rest remains same
contentContainer: {
 marginTop: 30,
 }

Создание компонента товара

Внутри  src/components каталога создайте новый файл с именем  Article.js. На данный момент этот компонент будет отображать заголовок и источник каждого заголовка.

Article Компонент будет компонентом презентации , которая получает все от  App компонента в качестве реквизита. Добавьте следующее в файл.

import React from 'react'
import { View, Text, StyleSheet } from 'react-native'

const Article = ({ title, source }) => (
  <View style={styles.content}>
    <Text style={styles.source}>{source.name}</Text>
    <Text style={styles.title}>{title}</Text>
  </View>
)

const styles = StyleSheet.create({
  content: {
    marginLeft: 10,
    flex: 1
  },
  source: {
    color: '#3d3c41',
    fontSize: 14,
    fontWeight: '500',
    marginBottom: 3
  },
  title: {
    fontSize: 18,
    fontWeight: 'bold',
    marginBottom: 15
  }
})

export default Article

Почему  title и  source получение деструктурированного? Это происходит потому , что в  App.js файле, при прохождении  item внутри  renderItem атрибута  FlatList компонента, вы уже деструктурированные  с item помощью  spread оператора.

renderItem={({ item }) => <Article {...item} />}

Импортируйте  Article компонент в  App.js файл для его работы.

import Article from './src/components/Article'

Теперь вернитесь к симулятору, в котором вы работаете с клиентом Expo, и вы получите результат, подобный следующему.

Окончательный вывод

Заключение

Поздравляем!  Вы успешно интегрировали клиент Apollo и преобразовали конечную точку REST в запрос, используя язык запросов GraphQL. Надеюсь, вам понравится читать этот вводный урок, который охватывает важный аспект разработки React Native с GraphQL.

Дальнейшее чтение


Если вам понравилась эта статья и вы хотите больше узнать о GraphQL, ознакомьтесь с этой коллекцией руководств и статей  по всем вопросам, связанным с GraphQL.