Есть ли способ проверить вложенные ресурсы в запросе соответствия react-admin?

#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, и в этом компоненте использовать крючок