Вы заинтересованы в создании приложения 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
. Этот файл будет содержать конфигурацию, касающуюся клиента Apollo . apollo-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 объектов заголовка в массив со всеми запрошенными полями.
Добавление индикатора активности
Внимательно посмотрите на изображение выше в предыдущем разделе. В ответе вы найдете поле с именем, 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 и создании приложения с использованием React Apollo .
- Как создать интернет-магазин с использованием современного стека (Nest.js, GraphQL, Apollo) Часть 1 .
- GraphQL: основные характеристики, архитектура, плюсы и минусы .
Если вам понравилась эта статья и вы хотите больше узнать о GraphQL, ознакомьтесь с этой коллекцией руководств и статей по всем вопросам, связанным с GraphQL.