Введение:

В этом сообщении в блоге я пытаюсь объяснить сравнение между React, React + Redux и React + GraphQL в отношении управления состоянием приложения.

Приложение React:

Нет необходимости внедрять библиотеку управления состоянием, такую ​​как «Redux», во все реагирующие приложения. Мы можем управлять изменениями состояния в самом родительском / корневом компоненте. Родительские компоненты должны отправлять объект состояния как свойства дочерним компонентам, чтобы они могли получить доступ к состоянию. Имейте в виду, что мы также должны передавать ссылку на функцию мутации дочерним компонентам. Любые изменения состояния можно производить в ближайших контейнерах.

Передача состояния дочерним компонентам:

<TodoList deleteClicked={this.removeTodo} todos={this.state.todos} changeClicked={this.changeTodo}>
</TodoList>

Как видите, список todos передается его дочернему компоненту TodoList как props для его визуализации.

Компонент TodoList может получать доступ к данным, как показано ниже, из свойств.

let pendingList = this.props.todos.filter(todo => todo.completed === false);

Здесь вы можете проверить исходный код простого приложения TODO ..

Примечание. Я создал все компоненты как компоненты с отслеживанием состояния, чтобы продемонстрировать варианты использования в приведенном выше демонстрационном проекте. Лучше всего создавать как можно больше компонентов без состояния.

Этот метод будет работать для небольшого приложения, такого как упомянутое выше. Представьте, что если у нас есть 5 или 6 дочерних компонентов, у нас может получиться очень огромный родительский / корневой компонент с множеством методов и свойств. Если наименьший дочерний компонент хочет получить доступ к некоторому свойству состояния, он должен быть передан всем дочерним компонентам, чтобы достичь компонента более низкого уровня, что создает накладные расходы. Передача свойств состояния и множества обратных вызовов сделает код некрасивым и очень сложным в обслуживании. Чтобы преодолеть все вышеперечисленные недостатки, они ввели библиотеку redux для управления состоянием приложения.

Недостатки:

  • С большим количеством дочерних компонентов и сложным пользовательским интерфейсом будет очень сложно и беспорядочно управлять состоянием в родительском компоненте.
  • Любое изменение состояния повторно отображает все дочерние компоненты внутри родительского компонента, что влияет на производительность.
  • Повторное использование компонентов будет затруднено, поскольку свойства дочерних компонентов тесно связаны с родительским компонентом.
  • Если несколько компонентов используют одни и те же данные, поток данных будет затруднен.
  • Очень сложно отслеживать состояние приложения при отладке.

Реагировать с Redux:

Redux - это библиотека управления состоянием для приложений JavaScript. Redux используется для хранения всего состояния приложения в одном месте. Дочерние компоненты могут получить доступ к состоянию из этого единственного хранилища и не должны передавать состояние от родителя к потомку.

Redux дает нам четкое разделение состояния приложения (а не локального состояния компонента) и его уровня представления. В шаблоне redux любой компонент может изменить состояние, и все компоненты, которые заинтересованы в этом конкретном объекте состояния, будут уведомлены. Это может быть достигнуто с помощью диспетчеризации, действий и редукторов. Изображение ниже объясняет, как работает redux.

В нашем демонстрационном примере добавьте компонент TodoList, как показано ниже.

<div className="home">
<div className="title shadow-sm p-3 mb-5 bg-white rounded">TODOAPP</div>
<AddTodo />
<TodoList />
</div>

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

const _TodoList = connect(state => ({ todoList: [...state.todoList.todoList] }),dispatch => bindActionCreators({ ...Actions }, dispatch),)(TodoList);

Теперь наш дочерний компонент обернут провайдером хранилища redux. Используя redux, мы можем разделять состояние приложения между компонентами, и теперь код очень легко поддерживать. Чем больше компонентов, тем сложнее код, redux уменьшит эту сложность, разделив состояние приложения. Мы можем отслеживать состояние приложения в любой момент во время отладки.

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

Проверить реализацию redux здесь.

Реагируйте с GraphQL:

Клиенты GraphQL, используемые для отправки и получения запросов GraphQL и ответов от сервера GraphQL. В этой статье я использую react-apollo в качестве клиента GraphQL. Клиент Apollo очень полезен для управления данными между нашим сервером и клиентом.

Используя react-apollo, мы можем избавиться от огромного количества кода, который мы написали для redux для управления состоянием приложения. Клиенты Apollo выпустили специальные компоненты для запросов, мутаций и подписок. Apollo-client упростил жизнь разработчика, выпустив компоненты высшего порядка, без которых разработчик, без которого разработчик, должен создавать компоненты высокого порядка, чтобы обернуть наши пользовательские компоненты для работы с запросами и изменениями. Везде, где мы хотим использовать запрос или мутацию, мы можем просто обернуть наш компонент этими HOC apollo.

Apollo использует встроенный механизм кеширования для синхронизации состояния приложения для всех компонентов пользовательского интерфейса. То же самое приложение TODO создано с помощью r eact и react-apollo. Вы можете очень хорошо сравнить код с реализацией redux, чтобы лучше понять, как response-apollo полезен для сокращения строк кода.

Компонент запроса:

Чтобы запросить список задач, нам просто нужно обернуть наш JSX Query HOC из apollo, как показано ниже:

<Query
query={gql`
query {
allTodos{
id ,todoItem ,completed
}
}
`}>
{({ loading, error, data }) => {
if (loading) return <p>Loading...</p>;
if (error) return <p>Error :(</p>;
return (
<div className="completed-list">
<div className="todo-pending">
{data.allTodos.filter(todo => todo.completed === false).map(function (todo, index) {return 
(<div className="todo-item row shadow-sm p-3 mb-5 bg-white rounded" key={index}>
<span className="todo-item-label"> {todo.todoItem} </span>
</div>);
}, this)}
</div>
</Query>

В приведенном выше коде перечислены все задачи. Как видите, состояние ошибки и загрузка также выполняются самим клиентом apollo, что упрощает жизнь разработчика. Если вы хотите показать какой-либо другой компонент на основе ошибки или загрузки, вы можете использовать эти реквизиты. Запросы можно использовать внутри самого компонента, что очень полезно для поддержки кода. Для повторного использования запросы могут храниться в отдельном файле и могут быть импортированы куда угодно, как я это делал в демонстрационном приложении.

В методе redux, как мы это делаем, создаем хранилище и создаем состояние для задач и сохраняем ответ сервера в состоянии задач. В redux мы должны реструктурировать данные на основе представления пользовательского интерфейса. Используя redux connect, компоненты могут получить состояние из магазина. Любые другие компоненты должны отображать те же данные, их можно получить в магазине.

В Apollo-client, когда приложение запрашивает определенные данные, оно извлекает их с сервера, нормализует и сохраняет в кеше. Apollo-cache хранит данные как объекты вместо простых строк JSON. Любой другой компонент, запрашивающий те же данные, получит их из кеша, благодаря чему сокращается круговой обход серверных запросов и данные всех компонентов синхронизируются. Более того, в Apollo-client нам не нужно реструктурировать данные, так как мы можем указывать структуру при запросе данных.

Компонент мутации:

Подобно компоненту запроса, компонент мутации используется для обертывания компонента / элемента, в котором вы хотите вызвать функцию изменения. Ниже приведен пример функции изменения:

Как видите, addTodo - это мутация на сервере, которая будет вызываться при нажатии кнопки. Если вы ссылаетесь на код, нажатие кнопки «новая задача» добавит новую задачу в список задач на сервере, но это изменение не отразится в пользовательском интерфейсе, поскольку состояние пользовательского интерфейса находится из внутреннего кеша. При каждом изменении данных мы должны также обновить кеш apollo, используя встроенную функцию writequery, предоставляемую компонентом Mutation. Теперь данные сервера и клиента синхронизированы, и любой компонент, использующий список задач, будет обновлен.

Если пользователь меняет состояние задачи на завершенное, при мутации не требуется вызывать метод кеширования обновлений, так как он выполняется apollo-client. Убедитесь, что вы возвращаете уникальный идентификатор для этого запроса на мутацию, чтобы эта функция работала правильно.

Состояние приложения синхронизируется между компонентами, а также между сервером и клиентом. Все эти функции достигаются благодаря великолепной библиотеке apollo-client с очень меньшим количеством строк кода.

Кэш Apollo-client сможет управлять только данными сервера. Для управления локальными данными (например, данными, совместно используемыми только компонентами этого экземпляра) можно использовать redux . Разработчики сообщества Apollo хотят сохранить кэш Apollo как единственный источник истины, поэтому они ввели библиотеки apollo-link-state и apollo-link. Это будет полная замена redux, поскольку вы можете управлять локальными данными и данными сервера в самом кэше. Мы можем подробно рассказать о apollo-link-state и apollo-link в моей следующей статье.

Подписки:

Подписки - одна из горячих тем в GraphQL, используемая для передачи данных в реальном времени между сервером и клиентом. Здесь мы используем веб-сокеты для передачи данных. Вы можете пройти через официальную страницу о том, как настроить подписки на стороне клиента. Вы можете посмотреть мое простое демонстрационное видео о том, как работает подписка и отмена подписки в react-apollo.

Модель подписки очень легко настроить в клиентском приложении с помощью apollo-react. Представьте, как сложно было бы настроить то же самое без apollo-react.

Исходный код:

Реагировать с GraphQL

Реализация сервера GraphQL

Вы можете найти полный исходный код всех демонстрационных приложений в:



Сравните код сами, и вы обязательно станете поклонником клиента Apollo.

Вывод:

Apollo-client дает нам множество простых в использовании функций с меньшим количеством кода и минимальными настройками. Компоненты запроса, мутации и подписки стали большим преимуществом в экономии времени на разработку.

Попробуйте использовать apollo-client для реагирования и сообщите мне о своем опыте.