React Native
Relay (GraphQL)
Рендеринг запросов в React Native с Relay и GraphQL на Back4App
29 мин
рендерер запросов на back4app введение в нашем предыдущем руководстве , мы узнали, как подготовить нашу среду relay теперь вы готовы начать разработку вашего приложения на react native в этом руководстве вы узнаете, как сделать ваш первый запрос на back4app мы погрузимся в рендерер запросов relay, поймем его основные принципы и используем его для получения ваших первых данных из back4app цели получить обзор рендерера запросов relay; сделать запрос к back4app graphql api из приложения react native с использованием relay; предварительные требования приложение создано на панели управления back4app приложение react native с настроенной средой relay согласно предыдущим документам прочитайте о узлах relay и соединениях что такое рендерер запросов? так же, как react строит дерево компонентов, relay строит дерево компонентов данных это означает, что каждый компонент приложения будет владельцем своих фрагментов данных фрагмент будет содержать информацию о данных, необходимую для его отображения на экране, и relay гарантирует, что эти данные доступны перед рендерингом компонента управляя этим подходом, рендерер запросов является корневым компонентом, необходимым для составления этих фрагментов и подготовки запроса для получения из нашего бэкенда почему важно понимать рендерер запросов? понимание использования рендерера запросов важно для абстрагирования вашего приложения различными способами хорошая абстракция кода может предотвратить часы работы, ошибки, время отладки и т д как работает рендерер вместе с api back4app в последнем уроке мы подготовили файл окружения relay, который указывает информацию о подключении к back4app используя эту конфигурацию, relay будет заботиться о взаимодействии с api back4app вам не нужно беспокоиться о подключении просто сосредоточьтесь на создании компонентов данных 1 создание класса на панели управления back4app давайте создадим ваш первый класс и заполним его несколькими объектами, используя консоль graphql back4app класс person имеет 2 поля name, которое является строкой, и salary, которое является целым числом перейдите в панель управления >core >консоль graphql и используйте код ниже 1 mutation createclass { 2 createclass(input { 3 name "person" 4 schemafields { 5 addstrings \[{name "name"}] 6 addnumbers \[{name "salary"}] 7 } 8 }){ 9 class{ 10 schemafields{ 11 name 12 typename 13 } 14 } 15 } 16 } вы увидите результат ниже создание класса теперь давайте создадим несколько объектов внутри этого класса перейдите к мутации создания объекта руководство https //www back4app com/docs/parse graphql/graphql mutation create object#mutation generic , чтобы увидеть, как обработать этот случай убедитесь, что вы используете последнюю версию parse server, чтобы использовать наиболее актуальную нотацию graphql api, доступную на back4app 1 mutation createobject{ 2 createhero(input {fields {name "allana foley", salary 1000}}){ 3 person { 4 id 5 name 6 salary 7 } 8 } 9 } создание объекта теперь класс person создан и имеет поля имя и зарплата после создания нового класса back4app автоматически генерирует все необходимые ресурсы для безопасного использования бэкенда одним из примеров является список объектов back4app уже создал необходимые соединения для запроса списка person people чтобы лучше понять, перейдите на площадку, обновите страницу и откройте вкладку документации, затем найдите people back4app сгенерировал поле соединения вы также можете запрашивать класс person как список обратите внимание, что поле query people является personconnection relay будет использовать поле соединения для отображения списка объектов person документация по полю person и документация по полю соединения people (person) 2 обновление схемы важно помнить, что если в ваше приложение добавляется новый класс, необходимо обновить схему внутри корня приложения react native при необходимости перейдите в скачать схему документацию и повторите шаги для обновления схемы 3 первый пример контейнера фрагмента прежде чем продолжить учебник, давайте познакомим вас с контейнером фрагмента давайте создадим компонент, который будет владельцем информации о person этот компонент будет содержать имя и зарплату человека здесь вы можете запросить любое поле person для создания вашего компонента теперь мы собираемся продолжить с этими двумя полями создайте файл и назовите его personcard js personcard js внутри него давайте создадим простой функциональный компонент 1 import react from 'react'; 2	 3 const personcard = () => { 4 return ( 5 \<div> 6 7 \</div> 8 ); 9 }; замените строку export default на код ниже 1 export default createfragmentcontainer(personcard, { 2 person graphql` 3 fragment personcard person on person { 4 id 5 name 6 salary 7 } 8 `, 9 }); код выше создаст фрагмент person, который запрашивает только id, имя и зарплату завершите обновление остальной части компонента следующим кодом 1 const personcard = ({person}) => { 2 return ( 3 \<view> 4 \<text>name {person name}\</text> 5 \<text>salary {person salary}\</text> 6 \</view> 7 ); 8 }; конечный результат должен выглядеть так 1 import react from "react"; 2 import { createfragmentcontainer, graphql } from "react relay"; 3 import { view, text } from "react native"; 4	 5 const personcard = ({person}) => { 6 return ( 7 \<view> 8 \<text>name {person name}\</text> 9 \<text>salary {person salary}\</text> 10 \</view> 11 ); 12 }; 13	 14 export default createfragmentcontainer(personcard, { 15 person graphql` 16 fragment personcard person on person { 17 id 18 name 19 salary 20 } 21 `, 22 }); 4 создание рендерера запроса следующий шаг создать рендерер запроса для вашего списка объектов рендерер запроса это корневой компонент для получения данных компонентов и подготовки их для извлечения данных из бэкенда вы узнаете, как извлекать данные для класса person на back4app 4 1 создание файла создайте новый файл и назовите его personrenderer js personrenderer js скопируйте код ниже и вставьте его в файл personrenderer 1 const personrenderer = () => { 2 return ( 3 \<queryrenderer 4 environment={environment} 5 query={graphql``} 6 variables={null} 7 render={({error, props}) => { 8 if (error) { 9 return ( 10 \<view> 11 \<text>{error message}\</text> 12 \</view> 13 ); 14 } else if (props) { 15 // @todo here will be implement the person card for each item from result 16 } 17 return ( 18 \<view> 19 \<text>loading\</text> 20 \</view> 21 ); 22 }} 23 /> 24 ); 25 }; 26	 27 export default personrenderer; 4 2 понимание свойств queryrenderer давайте начнем с query renderer с пустыми свойствами graphql, variables и render шаг за шагом вы будете реализовывать каждое из них поэтапно прежде всего, ваше приложение должно указать запрос для query renderer здесь наше приложение будет использовать список людей в свойствах запроса вставьте следующий код 1 graphql` 2 query personrendererquery { 3 people { 4 edges { 5 node { 6 personcard person 7 } 8 } 9 } 10 }` graphql поступает из react relay и реализует запрос в виде строки важно понимать связи между edges и node запрос выше использует соединение узлов людей с сервера back4app каждый раз, когда вы создаете новый класс, за ним будет следовать соединение узлов переменные при необходимости рендерер запросов будет использовать переменные хороший пример когда приложение запрашивает запрос для человека по id поскольку это не так в данный момент, давайте передадим null в свойства переменных заполнение карточки человека этот запрос вернет список людей рендерер запросов гарантирует, что данные будут доступны для рендеринга если это не так, будет выдана ошибка свойства, ответственные за это, это render заполните свойства рендеринга следующим кодом 1 render={({error, props}) => { 2 if (error) { 3 return ( 4 \<view> 5 \<text>{error message}\</text> 6 \</view> 7 ); 8 } else if (props) { 9 return props people edges map(({node}) => \<personcard person={node} />); 10 } 11 return ( 12 \<view> 13 \<text>loading\</text> 14 \</view> 15 ); 16 }} замените закомментированный todo на javascript map для рендеринга карточки человека для каждого результата из списка как уже было сказано, рендерер запросов берет на себя ответственность за то, чтобы данные были доступны только тогда, когда они готовы до тех пор будет отображаться сообщение о загрузке если произойдет ошибка, она будет отображена на экране, предотвращая неожиданное завершение работы приложения наконец, давайте улучшим рендеринг людей, заменив map на новую функцию поместите её перед query renderer 1 const renderpersons = (people) => { 2 return people edges map(({node}) => \<personcard person={node} />); 3 }; и конечный результат должен выглядеть так 1 import react from "react"; 2 import { queryrenderer } from "react relay"; 3 import environment from " /relay/environment"; 4 import personcard from " /personcard"; 5 import { view, text } from "react native"; 6	 7 const personrenderer = () => { 8 const renderpersons = (people) => { 9 return people edges map(({node}) => \<personcard person={node} />); 10 }; 11	 12 return ( 13 \<queryrenderer 14 environment={environment} 15 query={graphql` 16 query personrendererquery { 17 people { 18 edges { 19 node { 20 personcard person 21 } 22 } 23 } 24 } 25 `} 26 variables={null} 27 render={({error, props}) => { 28 if (error) { 29 return ( 30 \<view> 31 \<text>{error message}\</text> 32 \</view> 33 ); 34 } else if (props) { 35 return renderpersons(props people); 36 } 37 return ( 38 \<view> 39 \<text>loading\</text> 40 \</view> 41 ); 42 }} 43 /> 44 ); 45 }; 46	 47 export default personrenderer; 5 создание вашего первого запроса теперь пришло время получить данные о человеке, используя personrenderer если всё в порядке, ваше приложение теперь имеет два новых компонента personrenderer и personcard перед запуском приложения relay нуждается в relay compiler для выполнения и генерации типов компонентов для этого выполните в вашем терминале в app js добавьте следующий код 1 import react from 'react'; 2 import { safeareaview, statusbar, view, text } from 'react native'; 3	 4 import providers from ' /providers'; 5 import personrenderer from ' /components/home/person/personrenderer'; 6	 7 const app = () => { 8 return ( 9 \<providers> 10 \<statusbar barstyle="dark content" /> 11 \<safeareaview> 12 \<view 13 style={ { 14 flexdirection 'column', 15 justifycontent 'center', 16 alignitems 'center', 17 margintop 100, 18 } }> 19 \<text style={ {fontweight "bold", textalign "center"} }> 20 back4app react native relay query renderer list example 21 \</text> 22 \<personrenderer /> 23 \</view> 24 \</safeareaview> 25 \</providers> 26 ); 27 }; 28	 29 export default app; код app js изначально взят из create react native app он добавил view с стилем для центрирования содержимого на экране с отступом 10px сверху внутри него есть текст с меткой, чтобы дать некоторый контекст для вывода, и personrenderer для отображения списка людей вам нужно получить следующий результат рендеринг в нашем приложении back4app react native мы импортируем personrenderer непосредственно в app js app js поскольку personrenderer является корневым компонентом и имеет свой queryrenderer, person должен отображаться без каких либо ошибок 6 типизация компонентов этот шаг имеет смысл для приложения, которое работает с typescript если ваше приложение не использует typescript, продолжайте одна из возможностей relay compiler заключается в том, чтобы генерировать типы из каждого компонента данных давайте типизируем personrenderer и personcard, чтобы сделать приложение более мощным типизация personrenderer типизируйте аргумент функции renderperson people people в personrenderer 1 const renderpersons = (people personrendererquery\['response']\['people']) => { 2 return people edges map(({node}) => \<personcard person={node} />); 3 }; импортируйте тип personrendererquery personrendererquery из generated generated папки, созданной внутри той же папки, что и personrenderer типизация personcard перейдите к personcard, создайте новый объект типа и назовите его personcardprops 1 type personcardprops = {}; импортируйте тип personcard person personcard person из generated generated папок 1 import {personcard person} from ' / generated /personcard person graphql'; добавьте человека внутри типа personcardprops 1 type personcardprops = { 2 person personcard person; 3 }; в аргументах props от personcard, типизируйте компонент с personcardprops personcardprops конечный результат обоих компонентов должен выглядеть так personrenderer 1 import react from 'react'; 2 import {graphql, queryrenderer} from 'react relay'; 3 import {environment} from ' / / /relay'; 4 import personcard from ' /personcard'; 5 import {view, text} from 'react native'; 6 import {personrendererquery} from ' / generated /personrendererquery graphql'; 7	 8 const personrenderer = () => { 9 const renderpersons = (people personrendererquery\['response']\['people']) => { 10 return people edges map(({node}) => \<personcard person={node} />); 11 }; 12	 13 return ( 14 \<queryrenderer 15 environment={environment} 16 query={graphql` 17 query personrendererquery { 18 people { 19 edges { 20 node { 21 personcard person 22 } 23 } 24 } 25 } 26 `} 27 variables={null} 28 render={({error, props}) => { 29 if (error) { 30 return ( 31 \<view> 32 \<text>{error message}\</text> 33 \</view> 34 ); 35 } else if (props) { 36 return renderpersons(props people); 37 } 38 return ( 39 \<view> 40 \<text>loading\</text> 41 \</view> 42 ); 43 }} 44 /> 45 ); 46 }; 47	 48 export default personrenderer; personcard 1 import react from 'react'; 2	 3 import {createfragmentcontainer, graphql} from 'react relay'; 4	 5 import {view, text} from 'react native'; 6 import {personcard person} from ' / generated /personcard person graphql'; 7	 8 type personcardprops = { 9 person personcard person; 10 }; 11	 12 const personcard = ({person} personcardprops) => { 13 return ( 14 \<view> 15 \<text>name {person name}\</text> 16 \<text>salary {person salary}\</text> 17 \</view> 18 ); 19 }; 20	 21 export default createfragmentcontainer(personcard, { 22 person graphql` 23 fragment personcard person on person { 24 id 25 name 26 salary 27 } 28 `, 29 }); заключение конечный результат queryrenderer продемонстрировал, как приложение может быть абстрагировано приложение может отображать персону внутри query renderer поскольку personcard имеет больше компонентов, это не изменяет способ, которым был построен query renderer personrenderer был создан, чтобы показать, как можно выполнить запрос в простых шагах, в сочетании с мощью сервера back4app в следующем руководстве вы узнаете, как получить конкретный объект персоны и показать его атрибуты