Как грамотно обрабатывать isFetching для одного и того же запроса в нескольких компонентах (React Query)?
Есть запрос:
export const useGetClients = (params?: GetClientsRequest) => useQuery({ queryKey: ['clients', 'list', params], queryFn: () => ClientClient.getClientApiInstance().getClients(params), });
По вводным: на странице два основных компонента: таблица и кнопка, открывающая сайдбар.
Таблица:
const Wallets = () => { const { wallets, isLoading, isFetching } = useGetWallets(); return ( <div className="flex flex-col gap-4"> <div className="flex flex-wrap items-center justify-between gap-2"> <DepositFundsButton /> </div> <DataTable columns={Columns} data={wallets} isLoading={isLoading} isFetching={isFetching} /> </div> ); };
Где:
export const useGetWallets = () => { const { data: accounts, isLoading: isAccountsLoading, isFetching: isAccountsFetching, } = useGetLedgerAccounts(); const { data: clients, isLoading: isClientsLoading, isFetching: isClientsFetching, } = useGetClients({ clientType: ClientType.Client, }); const accountsWithClientName: AccountWithClientName[] = accounts && clients ? accounts.map((account) => ({ ...account, context: { ...account.context, ...(account.context.clientId && { clientName: clients.clients.find( (client) => client.id === account.context.clientId, )?.name, }), }, })) : []; return { wallets: accountsWithClientName, isLoading: isAccountsLoading || isClientsLoading, isFetching: isAccountsFetching || isClientsFetching, }; };
По вводным: при нажатии на кнопку Deposit funds открывается сайдбар с формой.
По вводным: в форме тот же запрос вызывается повторно (с теми же параметрами), чтобы получить список клиентов для выпадающего списка:
export const DepositFundsForm = ({ onClose }: DepositFundsFormProps) => { const { data, isFetching: isClientsFetching } = useGetClients({ clientType: ClientType.Client, }); return ( <> <Form {...methods}> <form className="space-y-6 overflow-y-auto px-4"> <SelectField name="clientId" loading={isClientsFetching} control={control} label="Client" placeholder="Client" options={clientOptions} className="min-w-[300px]" /> </form> </Form> <SheetFooter> <SheetClose asChild> <Button variant="secondary">Cancel</Button> </SheetClose> <Button onClick={handleSubmit(onSubmit)} isLoading={isSubmitting}> Deposit </Button> </SheetFooter> </> ); };
Проблема:
По вводным: когда форма открыта, я вижу два спиннера — один в таблице и второй в сайдбаре. С UX точки зрения это выглядит неправильно, ведь запрос одинаковый и данные уже есть в кеше.
Возможные решения:
Сейчас ситуация такая: - Показывать спиннер в таблице только если isAccountsFetching, а не при isAccountsFetching || isClientsFetching.
По вводным: - Передавать дополнительный ключ запроса (query key) из таблицы или сайдбара, чтобы у них были разные ключи и независимые состояния.
По вводным: - Обернуть таблицу и кнопку с сайдбаром в контекст-провайдер, где данные клиентов будут загружаться один раз и шариться между компонентами.
По вводным: в случае с последним решением возникают вопросы:
Нужно понять: a) что показывать, пока в провайдере идёт загрузка клиентов — скелетон вместо таблицы?
По вводным: b) если форма будет использоваться в других местах, нужно всегда оборачивать её в провайдер, что может быть неудобно
Вопрос:
Нужно понять: какой подход здесь будет наиболее правильным с точки зрения UX и архитектуры кода?
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопрос