ApolloClient: Как вы справляетесь с нормализацией / вложением в кеш? - PullRequest
0 голосов
/ 23 марта 2020

Мне неясно, как работать с ApolloClient InMemoryCache в отношении полей, в которых есть вложенность.

Например, у меня есть мутация GraphQL, которая, когда помечает задачу как «выполненную», также помечает всех ее дочерних элементов как «выполненную». На бэкэнде «child» - это отношение между «parent_id» и «id».

  "data": {
    "upsertTodos": [
      {
        "todo": {          
          "__typename": "rc_todos",
          "is_completed": true,
          "label": "Go to the store",
          "id": 1252,
          "parent_id": null
          "children": [
            {
              "__typename": "rc_todos",
              "id": 1040,
              "is_completed": true,
              "label": "Buy some milk",
              "parent_id": 1252
            }
          ],
        }
      }
    ]
  }
}

Итак, оба этих предмета являются задачами (одинаковыми __typename), и оба имеют id. Я хочу убедиться, что кеш "понимает" их как во вложенном, так и в не вложенном состоянии.

  1. Может ли ApolloClient "выяснить" отношения между "parent_id" и "id", или есть что-то, что я могу / следует убедиться, что он понимает это, чтобы правильно обрабатывать нормализацию и денормализацию?
  2. Предположим, что "Купить немного молока" уже кэшировано из запроса ALL_TODOS, который до сих пор получил "плоский" список всех Todos. Если я writeQuery против ALL_TODOS просто обновляю задачу "Go to store" - с "Buy some milk" в "children", как в ответе выше - понимает ли кеш, что уровень "root «Купи немного молока» todo должно быть обновлено? (Так как он видит, что __typename и id одинаковы) Или мне нужно вручную выполнить какое-то преобразование в функции обновления мутации, чтобы это работало?
  3. Вообще говоря, существуют ли "лучшие практики", которым необходимо следовать при работе с InMemoryCache с данными, которые иногда запрашиваются "плоскими", а иногда "вложенными" таким образом?

1 Ответ

1 голос
/ 23 марта 2020

Кэш нормализует данные из ответа, сохраняя только ссылки на объекты, возвращаемые сервером. Если поле разрешено для объекта, этот объект будет извлекаться и кэшироваться отдельно, а значение поля будет просто ссылкой на этот объект (т. Е. Ключ кэша, созданный путем объединения полей __typename и id). Если поле разрешено в список объектов, каждый объект в списке будет извлекаться и кэшироваться отдельно, а значение поля будет просто массивом ссылок на каждый объект.

Поскольку объекты кэшируются согласно вышеупомянутому ключу кэша, не имеет значения как запрос возвращает конкретный объект - если объект находится в ответе, он переопределит то, что уже находится в кэше. Любые родительские / дочерние отношения не имеют отношения к механизму. То же самое касается ручной записи в кеш.

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

Что хитро, так это мутации, которые влияют на членство объекта в списке. Например, у вас может быть запрос, который возвращает список завершенных задач, и другой запрос, который возвращает список ожидающих задач. В кеше будет храниться массив ключей кеша для каждого запроса, соответствующего объектам дел. Если мутация изменяет статус дела с ожидающего на завершенное, Apollo не может знать, что ему нужно удалить его из одного запроса и добавить к другому (это бизнес-логика c, которую знает только ваш сервер ). В этом случае мы должны выполнить ручную запись в кэш и самостоятельно обновить запросы.

Тот же принцип применим к созданию или удалению задачи - Аполлон не может знать, "эта мутация создала задачу ", и даже если бы он это сделал, он не смог бы узнать, к каким спискам он должен быть добавлен.

...