- Оригинальный адрес:The future of state management
- Оригинальный автор:Peggy Rayzis
- Перевод с:Программа перевода самородков
- Постоянная ссылка на эту статью:GitHub.com/rare earth/gold-no…
- Переводчик:yct21
По мере увеличения размера приложения состояние приложения, которое оно содержит, обычно становится более сложным. Как разработчикам, нам, возможно, придется координировать данные, отправляемые с нескольких удаленных серверов, а также управлять локальными данными, участвующими во взаимодействиях с пользовательским интерфейсом. Нам нужно хранить эти данные подходящим образом, чтобы компоненты в приложении могли иметь краткий доступ к этим данным.
Многие разработчики говорили нам, что с помощью Apollo Client можно хорошо управлять удаленными данными, и эта часть данных обычно составляет общий объем данных.80%о. Так что же делать с оставшимися 20% локальных данных (такими как глобальные флаги, результаты, возвращаемые API-интерфейсами устройств и т. д.)?
В прошлом пользователи Apollo обычно использовали отдельное хранилище Redux/Mobx для управления этой частью локальных данных. Во времена Apollo Client 1.0 это было жизнеспособным решением. Но когда Apollo Client перешел на версию 2.0 и больше не зависел от Redux, синхронизировать локальные и удаленные данные стало сложнее, чем раньше. Мы получили отзывы от многих пользователей и надеемся, что у нас будет решение, которое сможет полностью инкапсулировать состояние приложения в Apollo Client, чтобы достичьединственный источник правды.
фундамент для решения проблем
Мы знаем, что эту проблему нужно решать, теперь давайте подумаем, как правильно управлять состоянием в Apollo Client? Во-первых, давайте рассмотрим, что нам нравится в Redux, например его инструменты разработки и то, как он привязывает компоненты к состоянию приложения.connectфункция. В то же время нам также необходимо учитывать болевые точки использования Redux, такие как громоздкий шаблонный код, и, например, в процессе использования Redux есть много основных требований, включая создание асинхронного действия или реализацию состояния. Кэш или стратегия активного интерфейса Принятие часто требует, чтобы мы реализовали ее сами.
Чтобы получить идеальное решение для управления состоянием, мы должны использовать Redux как в целом, так и в целом. Кроме того, в GraphQL есть возможность интегрировать запросы к нескольким источникам данных в один запрос, и здесь мы воспользуемся этой возможностью в полной мере.
Выше приведена диаграмма архитектуры потока данных клиента Apollo.
GraphQL: однажды изучив, используйте где угодно
Существует распространенное заблуждение о GraphQL: реализация GraphQL зависит от конкретной реализации на стороне сервера. На самом деле GraphQL очень гибкий. GraphQL не волнует, отправлен ли запросgRPC-сервер, илиКонечная точка REST, илиКэш клиента. GraphQL — этоОбщий язык для данных, не имеет ничего общего с источником данных.
И именно поэтому запросы и мутации в GraphQL прекрасно описывают состояние приложения. Вместо отправки действия мы можем использовать мутации GraphQL для выражения изменений в состоянии приложения. Запросы GraphQL также могут декларативно описывать данные, необходимые компонентам, при запросе состояния приложения.
Одним из самых больших преимуществ GraphQL является то, что при добавлении соответствующих директив GraphQL к полям в операторе GraphQL один запрос может извлекать данные из нескольких источников данных, будь то локально или удаленно. Рассмотрим конкретный метод.
Управление состоянием в Apollo Client
Apollo Link— это модульный сетевой стек Apollo, который можно использовать для вставки кода ловушки на любом этапе жизненного цикла запроса GraphQL. Apollo Link позволяет управлять локальными данными в клиенте Apollo, получая данные с сервера GraphQL, используяHttpLink, а для запроса данных из кэша Apollo требуется новая ссылка:apollo-link-state.
import { ApolloClient } from 'apollo-client';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { ApolloLink } from 'apollo-link';
import { withClientState } from 'apollo-link-state';
import { HttpLink } from 'apollo-link-http';
import { defaults, resolvers } from './resolvers/todos';
const cache = new InMemoryCache();
const stateLink = withClientState({ resolvers, cache, defaults });
const client = new ApolloClient({
cache,
link: ApolloLink.from([stateLink, new HttpLink()]),
});
Приведенный выше код используетapollo-link-stateИнициализировать клиент Apollo.
Чтобы инициализировать ссылку состояния, вам необходимо включитьresolvers,defaultsиcacheОбъект поля используется как параметр для вызова Apollo Link.withClientStateфункция. Затем добавьте эту ссылку состояния в цепочку ссылок Apollo Client. Ссылка на состояние должна быть размещена вHttpLinkРаньше такие локальные запросы и мутации перехватывались перед отправкой на сервер.
Defaults
предыдущийdefaultsПоле представляет собой объект, представляющий начальное значение состояния.Когда ссылка на состояние только что создана, это значение по умолчанию будет записано в кэш клиента Apollo. Хотя это и не обязательный параметр, прогрев кеша является важным шагом, входящиеdefaultТак что компонент не будет делать ошибок, потому что данные не могут быть запрошены.
export const defaults = {
visibilityFilter: 'SHOW_ALL',
todos: [],
};
приведенного выше кодаdefaultsПредставляет начальное значение кэша Apollo.
Resolvers
После использования Apollo Client для управления состоянием приложения кэш Apollo становится единственным источником данных для приложения, включая локальные и удаленные данные. Итак, как мы должны запрашивать и обновлять данные в кеше? Здесь в игру вступает Resolver. Если вы использовали его раньше на стороне сервераgraphql-tools, то вы обнаружите, что сигнатура типа распознавателя обоих типов одинакова.
fieldName: (obj, args, context, info) => result;
Если вы не видели приведенную выше сигнатуру типа, не нервничайте, просто помните два важных момента: передается переменная запроса или мутацииargsАргументы передаются распознавателю, в качестве которого будет использоваться кеш Apollo.contextЧасть параметра передается распознавателю.
export const defaults = { // same as before }
export const resolvers = {
Mutation: {
visibilityFilter: (_, { filter }, { cache }) => {
cache.writeData({ data: { visibilityFilter: filter } });
return null;
},
addTodo: (_, { text }, { cache }) => {
const query = gql`
query GetTodos {
todos @client {
id
text
completed
}
}
`;
const previous = cache.readQuery({ query });
const newTodo = {
id: nextTodoId++,
text,
completed: false,
__typename: 'TodoItem',
};
const data = {
todos: previous.todos.concat([newTodo]),
};
cache.writeData({ data });
return newTodo;
},
}
}
Вышеупомянутая функция Resolver — это способ запроса и обновления кеша Apollo.
Чтобы записать данные в корень кэша Apollo, вы можете вызватьcache.writeDataметод и передать соответствующие данные. Иногда данные, которые нам нужно записать, зависят от исходных данных в кеше Apollo, например, как показано выше.addTodoметод. В этом случае вы можете использоватьcache.readQueryЗапросите данные один раз. Чтобы записать фрагмент в существующий объект, передайте необязательный параметрid, этот параметр является индексом кеша соответствующего объекта. Выше мы использовалиInMemoryCache, поэтому индекс должен иметь вид__typename:id.
apollo-link-stateПоддерживаются асинхронные методы преобразователя, которые можно использовать для выполнения некоторых асинхронных побочных эффектов, таких как доступ к некоторым API-интерфейсам устройств. Однако мы не рекомендуем делать запросы к конечным точкам REST в преобразователях. Правильный способ - использовать[apollo-link-rest](https://github.com/apollographql/apollo-link-rest), этот пакет содержит@restинструкция.
@clientинструкция
Когда пользовательский интерфейс приложения запускает мутацию, сетевому стеку Apollo необходимо знать, существуют ли обновляемые данные на стороне клиента или сервера.apollo-link-stateиспользовать@clientдиректива для маркировки полей, которые должны существовать только локально на стороне клиента, а затем,apollo-link-stateДля этих полей вызываются соответствующие методы преобразователя.
const SET_VISIBILITY = gql`
mutation SetFilter($filter: String!) {
visibilityFilter(filter: $filter) @client
}
`;
const setVisibilityFilter = graphql(SET_VISIBILITY, {
props: ({ mutate, ownProps }) => ({
onClick: () => mutate({ variables: { filter: ownProps.filter } }),
}),
});
Приведенный выше код проходит@clientДирективы ограничивают изменение данных локальным.
Форма запроса аналогична мутации. Если вы используете асинхронный запрос в запросе, Apollo Client будет отслеживать загрузку данных и статус ошибки для вас. Если вы используете React, вы можете сделать это в компонентеthis.props.dataВ нем будет много вспомогательных методов, таких как повторный запрос, пейджинг и опрос и другие функции.
Очень захватывающая функция GraphQL — запрос данных из нескольких источников данных в одном запросе. В приведенном ниже примере мы запрашиваем сервер GraphQL, хранящийся в том же запросе.userданных и в кеше АполлонаvisibilityFilterданные.
const GET_USERS_ACTIVE_TODOS = gql`
{
visibilityFilter @client
user(id: 1) {
name
address
}
}
`;
const withActiveState = graphql(GET_USERS_ACTIVE_TODOS, {
props: ({ ownProps, data }) => ({
active: ownProps.filter === data.visibilityFilter,
data,
}),
});
Используйте приведенный выше код@clientКоманда запрашивает кэш Apollo.
в нашемна последней странице документации, можно найти больше примеров, и некоторыеapollo-link-stateСоветы по интеграции в приложение.
Дорожная карта до версии 1.0
несмотря на то чтоapollo-link-stateразработка достаточно стабильна, чтобы ее можно было использовать в практической разработке приложений, но есть еще некоторые функции, которые мы надеемся реализовать в ближайшее время:
-
схема данных клиента: в настоящее время мы не поддерживаем проверку типов для структур схемы данных на стороне клиента, потому что если вы хотите создавать и проверять схемы данных во время выполнения
graphql-jsПомещение модулей в зависимости может значительно увеличить размер файла ресурсов веб-сайта. Чтобы избежать этого, мы хотим перенести построение схемы данных на этап сборки проекта, чтобы мы могли поддерживать проверку типов, а также использовать всевозможные интересные функции в GraphiQL. - Вспомогательные компоненты: Наша цель — сделать управление состоянием Apollo как можно более плавным с приложениями. Мы напишем некоторые компоненты React, чтобы сделать реализацию некоторых общих требований более необременительной, например, на уровне кода переменные в программе могут быть напрямую переданы в качестве параметров в мутацию, а затем напрямую реализованы в виде мутации внутри. .
Если Вас интересуют вышеуказанные вопросы, Вы можетеGitHubПрисоединяйтесь к нам в разработке и обсуждениях или войдите в Apollo Slack#local-stateканал. Приглашаем присоединиться к нам в создании нового поколения методов управления состоянием!
Программа перевода самородковэто сообщество, которое переводит высококачественные технические статьи из Интернета сНаггетсДелитесь статьями на английском языке на . Охват контентаAndroid,iOS,внешний интерфейс,задняя часть,блокчейн,продукт,дизайн,искусственный интеллекти другие поля, если вы хотите видеть больше качественных переводов, пожалуйста, продолжайте обращать вниманиеПрограмма перевода самородков,официальный Вейбо,Знай колонку.