Есть запрос:
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 и архитектуры кода?