Подключение RTK Query API с редуктором и селектором redux

Я думаю, что мне что-то не хватает в отношении инструментов Redux и RTK Query. Я также использую для этого кодогенератор RTK Query OpenAPI.

Прямо сейчас у меня есть API, которое выглядит так ->

      export const api = generatedApi.enhanceEndpoints({
  endpoints: {
    getMaterials: {
      transformResponse: response => normalize(response),
    },
  },
})

Это возвращает мне нормализованные данные в моем компоненте:

      const Materials = () => {
  const { data, isLoading, error } = useGetMaterialsQuery()

  /*
    Cool this gives me data back like:
    {
      [id]: {
        id,
        prop1: 'blah',
        prop2: 'blah2'
      }
    }
  */

  console.log(data)

  // but now I want to structure this data differently using selector

  const newDataStructure = useSelector(addSomeMetaDataAndStructureDifferentlySelector)

  return <MyComponent structuredData={newDataStructure} />
}

Но когда я смотрю на состояние в этом селекторе, это выглядит так:

Когда в селекторе я действительно хочу использовать что-то вроде ->

      const addSomeMetaDataAndStructureDifferentlySelector = state => 
    // create new data structure from state.materials.byId that I will pass to `MyComponent`

Мой магазин сейчас выглядит так ->

      import { configureStore } from '@reduxjs/toolkit'
import { setupListeners } from '@reduxjs/toolkit/query'
import { api } from 'gen/rtk-openapi'
// import materialsReducer from 'state/materials/materialsSlice'

const store = configureStore({
  reducer: {
    [api.reducerPath]: api.reducer,
  },
  middleware: getDefaultMiddleware =>
    getDefaultMiddleware().concat(api.middleware),
})

setupListeners(store.dispatch)

export default store

Так что мне нужно пройти data прямо из useGetMaterialsQuery в функцию и просто преобразовать ее?

Или я могу каким-то образом создать новый срез редуктора, который каким-то образом правильно инициализируется данными, чтобы я мог получить доступ state.materials.byId в селекторе?

Или мне здесь что-то принципиально не хватает?

1 ответ

Вы пропустили важный момент: RTK-Query - это не нормализованный кеш , а кеш документа.

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

Это может показаться недостатком, но создание реального «нормализованного» кеша в качестве общей библиотеки практически невозможно, особенно для чего-то неоднозначного, как REST apis. Даже для GraphQL это очень сложная проблема, и даже решения, специализированные на GraphQL (например, apollo), имеют множество проблем и заканчиваются большим количеством рукописного кода для обработки таких случаев, как добавление / удаление из коллекций.

Итак, в конце у вас остается два варианта: написать собственное нормализованное решение для кэширования вручную, явно ориентированное на ваши структуры данных, или использовать кеш документов.

В большинстве случаев кеша документов достаточно. И именно здесь появляется RTK-Query, который пытается предоставить вам как можно больше инструментов для «синхронизации» данных между вашими документами: автоматическая повторная выборка и где вы хотите избежать этого, возможность выполнять оптимистические обновления вручную для управления определенными записями в кеше. .

Как правило, я бы не рекомендовал копировать эти данные в рукописные фрагменты. Таким образом, вы потеряете множество преимуществ RTK-Query, например, отслеживание подписки и автоматическую очистку кеша после того, как ни один из компонентов не использует значение через 60 секунд. Это может показаться необычным после использования Redux с рукописными фрагментами в течение некоторого времени, но в большинстве ситуаций он работает очень хорошо - с гораздо меньшим количеством кода.

Что касается того, как его использовать: как правило, вы просто звоните своему useGetMaterialsQuery() во всех компонентах, которые нуждаются в материалах, и просто отфильтруйте то, что вам нужно в своем компоненте, или используйте selectFromResult возможность просто выбрать то, что вам действительно нужно.

Другие вопросы по тегам