Rumah  >  Soal Jawab  >  teks badan

Cara menggunakan pertanyaan RTK dengan pemilih

Saya sedang membina projek menggunakan Redux Toolkit dan RTK Query dan cuba mendapatkan beberapa entri daripada API. Saya menggunakan kaedah normalize data createEntityAdapter kerana dalam komponen tertentu saya memerlukan data sebagai tatasusunan, jadi saya akhirnya menggunakan pemilih. Sekarang masalah saya ialah sejak saya menambah penapis sebagai parameter pertanyaan, pemilih saya berhenti berfungsi.

Saya melihat soalan serupa di sini seperti: "Bagaimana untuk menggunakan pemilih pertanyaan RTK dengan parameter?", tetapi saya terlalu bodoh untuk memahami perkara yang perlu saya ubah suai. Saya cuba memahami dokumentasi pertanyaan RTK, tetapi saya tidak boleh.

Daripada soalan di atas, saya tahu bahawa pemilih saya juga perlu mempunyai parameter untuk mengetahui dengan tepat apa yang perlu dipilih, dan ini bukan corak yang disyorkan, tetapi saya tidak dapat memahami cara membuatnya berfungsi.

Potongan penyertaan saya:

import { createSelector, createEntityAdapter } from '@reduxjs/toolkit'
import { apiSlice } from './apiSlice'

const entryAdapter = createEntityAdapter()

const initialState = entryAdapter.getInitialState({
  ids: [],
  entities: {},
})

export const entryApiSlice = apiSlice.injectEndpoints({
  endpoints: (builder) => ({
    initialState,
    getEntry: builder.query({
      query: (filters) => ({
        url: '/history',
        params: filters,
      }),
      transformResponse: (responseData) => {
        return entryAdapter.setAll(initialState, responseData)
      },
      providesTags: (result, error, arg) => [
        { type: 'Entry', id: 'LIST' },
        ...result.ids.map((id) => ({ type: 'Entry', id })),
      ],
    }),
    addEntry: builder.mutation({
      query: (data) => ({
        url: '/history/new',
        method: 'POST',
        body: data,
      }),
      invalidatesTags: [{ type: 'Entry', id: 'LIST' }],
    }),
    updateEntry: builder.mutation({
      query: (initialEntry) => ({
        url: `/history/${initialEntry.Id}`,
        method: 'PUT',
        body: {
          ...initialEntry,
          date: new Date().toISOString(),
        },
      }),
      invalidatesTags: (result, error, arg) => [{ type: 'Entry', id: arg.id }],
    }),
    deleteEntry: builder.mutation({
      query: ({ id }) => ({
        url: `/history/${id}`,
        method: 'DELETE',
        body: { id },
      }),
      invalidatesTags: (result, error, arg) => [{ type: 'Entry', id: arg.id }],
    }),
  }),
})

export const {
  useGetEntryQuery,
  useAddEntryMutation,
  useUpdateEntryMutation,
  useDeleteEntryMutation,
} = entryApiSlice

export const selectEntryResult = (state, params) =>
  entryApiSlice.endpoints.getEntry.select(params)(state).data

const entrySelectors = entryAdapter.getSelectors(
  (state) => selectEntryResult(state) ?? initialState
)
export const selectEntry = entrySelectors.selectAll

Saya menggunakannya dalam komponen Entri seperti ini

const {
    data: entriesData = [],
    refetch,
    isLoading,
    isSuccess,
    isError,
    error,
  } = useGetEntryQuery(filters)

  const entries = useSelector(selectEntry)

Nota: Jika saya mengalih keluar "penapis" daripada pertanyaan dapatkan, semuanya berfungsi seperti sebelumnya (seperti yang dijangkakan, sudah tentu).

Penafian: Saya tidak tahu apa yang saya lakukan, saya telah membaca dokumentasi dan cuba memahaminya, jadi sebarang maklum balas amat dihargai. Terima kasih!

P粉729198207P粉729198207318 hari yang lalu656

membalas semua(1)saya akan balas

  • P粉779565855

    P粉7795658552023-12-29 00:13:52

    Ya, ini adalah topik yang agak sensitif, kerana dokumentasi RTKQ cenderung menunjukkan contoh paling mudah, iaitu pertanyaan yang tidak menggunakan sebarang parameter sama sekali. Saya sendiri mempunyai banyak masalah.

    Apa pun, anda telah mengisytiharkan selectEntryResult sebagai fungsi dua parameter: keadaan dan param. Kemudian, apabila anda mencipta pemilih penyesuai di bawahnya, anda memanggilnya dengan hanya satu parameter: keadaan. Juga, apabila anda menggunakan pemilih akhir dalam komponen anda seperti ini:

    const entries = useSelector(selectEntry);
    
    Parameter

    tiada di mana-mana, secara lalai ia 未定义 dan tiada data yang dikaitkan dengan parameter pertanyaan sedemikian boleh ditemui.

    Perkara penting untuk difahami di sini ialah anda sebenarnya perlu melepasi parameter pertanyaan melalui setiap peringkat pemilih (setiap pembungkus) entah bagaimana.

    Salah satu cara di sini ialah "majukan" parameter melalui pemilih:

    export const selectEntryResult = createSelector([state => state, (_, params) => params], (state, params) =>
      entryApiSlice.endpoints.getEntry.select(params)(state)?.data ?? initialState)
    

    Di sini kami menggunakan fungsi createSelector yang dieksport daripada RTK. Kemudian dalam komponen anda, anda akan melakukan sesuatu seperti ini:

      const {...} = useGetEntryQuery(filters);
    
      const entries = useSelector(state => selectEntry(state, filters));
    

    Ini dibuat menggunakan Penyesuai Entiti selectAll 选择器时有效,但在使用 selectById 时会导致问题,因为该选择器也是参数化的。简而言之,selectById Pemilih ditakrifkan secara dalaman untuk mengambil argumen kedua bagi id entiti yang anda ingin dapatkan, manakala kaedah yang saya tunjukkan menggunakan argumen kedua untuk menghantar parameter pertanyaan (penapis dalam peranti anda). kes).

    Setahu saya, tiada penyelesaian setakat ini yang berfungsi dengan sempurna dan merangkumi semua perkara berikut:

    • Gunakan Penormalan Entiti
    • Dapatkan semula data menggunakan pemilih
    • Gunakan pertanyaan berparameter

    Pendekatan lain mungkin adalah dengan mencipta beberapa kilang pemilih yang mencipta pemilih asas secara dinamik untuk kombinasi parameter pertanyaan tertentu.

    Saya pernah membuat pembalut sedemikian yang boleh digunakan dalam semua keadaan. Malangnya saya tidak dapat berkongsinya kerana ia adalah pakej peribadi, tetapi idea asasnya adalah untuk menukar parameter supaya selectByIdselectAll (dan semua pemilih lain) berfungsi dengan baik, dengan menghantar parameter pertanyaan kepada pemilih sebagai argumen ketiga, dan kemudian seterusnya balut semula setiap pemilih penyesuai entiti:

    export const createBaseSelector = (endpoint) =>
      createSelector(
        [(state) => state, (_, other) => other, (_, _other, params) => params],
        (state, _other, params) => endpoint.select(params)(state)
      );
    
    const selectors = adapter.getSelectors(baseSelector);
    
    // And then rewrap selectAll and selectById from 'selectors' above
    

    Saya tahu ini kedengaran rumit dan saya hampir tidak menyelesaikannya jadi cuba elakkan pergi ke arah ini :)

    Artikel berguna yang saya temui di sepanjang jalan boleh didapati di sini, ia juga menerangkan beberapa cara untuk mencipta pemilih pada peringkat komponen dan mengingatinya, tetapi saya belum mencuba kesemuanya. Sila lihat, mungkin anda akan menemui cara yang lebih mudah untuk menyelesaikan masalah khusus anda.

    balas
    0
  • Batalbalas