Apollo graphql client представляет удобный лаконичный спсоб работы с данными в приложениях react. В большинстве случаев все то, что мы привыкли делать с помощью redux, гораздо проще сделать при помощи Apollo graphql client. То, о чем я хотел бы рассказать в этой статье — это что связка react + apollo client + graphql существенно (на порядок) упрощает разработку приложений react.
Для работы мы будем использовать тестовый сервер graphql по адресу. graphql из коробки предлагает, кроме всего прочего, консоль для выполнения запросов, и в ней же интегрированную документацию. Предлагаю раскрыть эту панель. В левой панели можно вводить запрос, в правой будет выводиться ответ. Попробуйте ввести самый простой запрос:
allUsers это имя запроса, а внутри фигурных скобок — имена полей которые будут возвращены. Более сложные запросы могут содержать список параметров и содержать поля вложенных объектов:
В данном случае параметры orderBy и limit не следует воспринимать как в SQL. Это просто имена параметров которые сами по себе без реализации не делают сортировку или ограничение выборки.
Другие параметры и выходные поля этих запросов можно посмотреть из интерфейса консоли.
В качестве основы для приложения возьмем react-create-app. Дополнительно установим apollo-client и react-router-dom:
Изменим основной компонент приложения App.js:
AploolProvider и ApolloClient — это все что нужно для того чтобы во всех компонентах можно было использовать graphql.
Проще всего передать данные в компонент с использованием тэга Query. Давайте выведем в компоненте список пользователей (сам запрос мы уже опробовали в консоли раньше):
Для добавления или изменения состояния на сервере используются Mutation:
Когда я знакомился с примерами компонетов react с использованием apollo graphql client я чувствовал себя не совсем уютно. А все дело в том что разработчик веб-приложения мыслит скорее императивно, чем декларативно. Нам хочется действия. «Установить фильтр», «сохранить запись» и т.п. И когда мы переходим к тому что нам нет необходимости думать о том как данные грузятся с сервера мы вместо того чтобы принять такой подход и использоватьего преимущества задумываемся над тем как мы будем контролировать store.
Дополняю текст еще одним примером, в котором в запросе graphql используется параметр принятый от охватывающего компонента (роута).
Исходный код.
Также Apollo client работает и в условиях серверного рендеринга и универсальных приложений. Предзагрузка данных для серверного рендеринга (включая и все вложенные компоненты) реализована «из коробки». Парадокс в том что соединив несколько технологий которые часто критикуют за усложненность получили в результате существенное упрощение приложения.
apapacy@gmail.com
11 мая 2018 года.
Для работы мы будем использовать тестовый сервер graphql по адресу. graphql из коробки предлагает, кроме всего прочего, консоль для выполнения запросов, и в ней же интегрированную документацию. Предлагаю раскрыть эту панель. В левой панели можно вводить запрос, в правой будет выводиться ответ. Попробуйте ввести самый простой запрос:
query { allUsers { id name } }
allUsers это имя запроса, а внутри фигурных скобок — имена полей которые будут возвращены. Более сложные запросы могут содержать список параметров и содержать поля вложенных объектов:
query { allPosts(orderBy: updatedAt_DESC, first: 7){ id title user { id name } } }
В данном случае параметры orderBy и limit не следует воспринимать как в SQL. Это просто имена параметров которые сами по себе без реализации не делают сортировку или ограничение выборки.
Другие параметры и выходные поля этих запросов можно посмотреть из интерфейса консоли.
В качестве основы для приложения возьмем react-create-app. Дополнительно установим apollo-client и react-router-dom:
npm install apollo-boost react-apollo graphql-tag graphql --save npm install react-router-dom --save
Изменим основной компонент приложения App.js:
import React from 'react'; import { Route, Switch, BrowserRouter } from 'react-router-dom'; import { ApolloProvider } from 'react-apollo'; import ApolloClient from 'apollo-boost'; import Layout from './Layout'; import AllUsers from './AllUsers'; import TopPosts from './TopPosts'; import NewPost from './NewPost'; const client = new ApolloClient({ uri: 'https://api.graph.cool/simple/v1/ciyz901en4j590185wkmexyex', }); const App = () => ( <ApolloProvider client={client}> <BrowserRouter> <Layout> <Switch> <Route exact path='/' component={ AllUsers } /> <Route exact path='/posts' component={ TopPosts } /> <Route exact path='/user/:userId' component={ NewPost } /> </Switch> </Layout> </BrowserRouter> </ApolloProvider> ); export default App;
AploolProvider и ApolloClient — это все что нужно для того чтобы во всех компонентах можно было использовать graphql.
Проще всего передать данные в компонент с использованием тэга Query. Давайте выведем в компоненте список пользователей (сам запрос мы уже опробовали в консоли раньше):
import React from 'react'; import { Link } from 'react-router-dom' import { Query } from "react-apollo"; import gql from "graphql-tag"; import TopPosts from './TopPosts'; const AllUsers = () => ( <Query query={gql` query { allUsers { id name } } `} > {({ loading, error, data }) => { for (let key in arguments[0]) console.log(key, arguments[0][key]); console.log('data', data) if (loading) return <p>Loading...</p>; if (error) return <p>Error :(</p>; return ( <ul key='allUsers'> {data.allUsers.map(({ id, name }) => ( <li key={id}><Link to={`/user/${id}`}>{name ? name : 'incognoito'}</Link></li> ))} </ul> ); }} </Query> ); export default AllUsers
Для добавления или изменения состояния на сервере используются Mutation:
import React from 'react'; import { Link } from 'react-router-dom' import { Mutation } from 'react-apollo'; import gql from 'graphql-tag'; const NewPost = (props) => ( <Mutation mutation={gql` mutation createPost($text: String!, $title: String!, $userId: ID!){ createPost(text: $text, title: $title, userId: $userId) { id } } `} > {(createPost, { loading, error, data }) => { if (loading) return <p>Loading...</p>; if (error) return <p>Error :(</p>; let userId, title, text return ( <form onSubmit={e => { e.preventDefault(); createPost({ variables: { userId: userId.value , title: title.value , text: text.value , }}); }}> <input type='hidden' value={ props.match.params.userId } ref={ node => userId = node } /> <input type='text' ref={ node => title = node } /> <textarea ref={ node => text = node } /> <button type='submit' /> </form> ); }} </Mutation> ); export default NewPost;
Когда я знакомился с примерами компонетов react с использованием apollo graphql client я чувствовал себя не совсем уютно. А все дело в том что разработчик веб-приложения мыслит скорее императивно, чем декларативно. Нам хочется действия. «Установить фильтр», «сохранить запись» и т.п. И когда мы переходим к тому что нам нет необходимости думать о том как данные грузятся с сервера мы вместо того чтобы принять такой подход и использоватьего преимущества задумываемся над тем как мы будем контролировать store.
Дополняю текст еще одним примером, в котором в запросе graphql используется параметр принятый от охватывающего компонента (роута).
import React from 'react'; import { Link } from 'react-router-dom' import { Query } from 'react-apollo'; import gql from 'graphql-tag'; const Post = (props) => ( <Query query={gql` query { Post(id: "${props.match.params.postId}") { id title text } } `} fetchPolicy='network-only' > {({ loading, error, data }) => { if (loading) return <p>Loading...</p>; if (error) return <p>Error :(</p>; return ( <ul key='topPosts'> <li>{data.Post.id}</li> <li>{data.Post.title}</li> <li>{data.Post.text}</li> </ul> ); }} </Query> ); export default Post;
Исходный код.
Также Apollo client работает и в условиях серверного рендеринга и универсальных приложений. Предзагрузка данных для серверного рендеринга (включая и все вложенные компоненты) реализована «из коробки». Парадокс в том что соединив несколько технологий которые часто критикуют за усложненность получили в результате существенное упрощение приложения.
apapacy@gmail.com
11 мая 2018 года.
