#reactjs #react-hooks #react-admin
Вопрос:
Цель состоит в том, чтобы выполнить автоматическую проверку ввода значения фильтра не только непосредственно в списке предложений, но и в ссылках предложений на различные ресурсы. В частности, предположим, что Цитата содержит ссылку на Контакт и Адрес, и пользователь вводит «abc» во ввод. Теперь цитата, адрес которой содержит «abc», также должна отображаться в списке предложений. Самым элегантным способом было бы использовать крючок useGetOne, как в следующем фрагменте кода, но вы не можете вызвать этот крючок извне компонента React.
const matchAnyNested = (filter, value) => {
if (matchAnyField(filter, value)) return true;
const { data: contact } = useGetOne('contacts', value.contact_id);
if (matchAnyField(filter, contact)) return true;
const { data: account } = useGetOne('accounts', contact.account_id);
if (matchAnyField(filter, account)) return true;
for (let item of value.part_items) {
const part = useGetOne('parts', item.part_id);
if (matchAnyField(filter, part)) return true;
}
return false;
};
[...]
<AutocompleteInput ... matchSuggestion={matchAnyNested} />
Есть ли способ извлечения записей из функции matchSuggestion или какой-либо другой способ проверки предложений на основе вложенных записей ? Спасибо за любую помощь
Ответ №1:
Из-за правил реагирования на крючки это кажется невозможным. В итоге я реализовал эту функцию фильтрации в бэкэнде.
Ответ №2:
useGetOne
Крючок, как и другие крючки поставщика данных, принимает enabled
опцию. Пример из документации react-admin показывает его использование:
// fetch posts
const { ids, data: posts, loading: isLoading } = useGetList(
'posts',
{ page: 1, perPage: 20 },
{ field: 'name', order: 'ASC' },
{}
);
// then fetch categories for these posts
const { data: categories, loading: isLoadingCategories } = useGetMany(
'categories',
ids.map(id=> posts[id].category_id),
// run only if the first query returns non-empty result
{ enabled: ids.length > 0 }
);
Это относится и к вашему делу:
const matchAnyNested = (filter, value) => {
const { data: contact } = useGetOne(
'contacts',
value.contact_id,
{ enabled: !matchAnyField(filter, value) }
);
const { data: account } = useGetOne(
'accounts',
contact.account_id,
{ enabled: !matchAnyField(filter, contact) }
);
// ...
};
Однако это не решит вашу проблему в цикле из-за правил крючков.
Если вам действительно нужен этот цикл, лучше всего использовать крючок useDataProvider для прямого вызова поставщика данных:
const matchAnyNested = async (filter, value) => {
const dataProvider = useDataProvider();
if (matchAnyField(filter, value)) return true;
const { data: contact } = await dataProvider.getOne('contacts', { id: value.contact_id });
if (matchAnyField(filter, contact)) return true;
const { data: account } = await dataProvider.getOne('accounts', { id: contact.account_id });
if (matchAnyField(filter, account)) return true;
for (let item of value.part_items) {
const part = await dataProvider.getOne('parts', { id: item.part_id });
if (matchAnyField(filter, part)) return true;
}
return false;
};
Комментарии:
1. Спасибо за ваш ответ, я не знал об этом
enabled
варианте. Проблемы с зацеплением в цикле можно избежать, вызвав getList (), а затем зациклившись на данных ответа. Основная проблема, с которой я просил о помощи, заключается в том, что для сопоставления предложений требуется функция, поэтому крючки вообще нельзя использовать для сопоставления предложений. Это просто ограничение администратора React или есть другой способ извлечения записей во время процесса сопоставления ? Спасибо2. Вы можете определить функцию, которую вы передаете для сопоставления, в компоненте React, и в этом компоненте использовать крючок