【问题标题】:Is there a way to check nested resources in react-admin's matchSuggestion?有没有办法检查 react-admin 的 matchSuggestion 中的嵌套资源?
【发布时间】:2021-11-30 10:46:43
【问题描述】:

目标是不仅直接在建议列表中,而且在建议对不同资源的引用中对过滤器值进行 AutocompleteInput 检查。 具体来说,假设 Quote 引用了 Contact 和 Address,并且用户在输入中输入了“abc”。现在,地址包含“abc”的报价也应该显示在建议列表中。 最优雅的方法是使用 useGetOne 钩子,如下面的代码 sn-p 所示,但您不能从 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 函数中获取记录,或者通过其他方式来验证基于嵌套记录的建议?感谢您的帮助

【问题讨论】:

    标签: reactjs react-hooks react-admin


    【解决方案1】:

    因为React rules of hooks,这似乎是不可能的。我最终在后端实现了这个过滤功能。

    【讨论】:

      【解决方案2】:

      useGetOne 挂钩与其他 dataProvider 挂钩一样,接受 enabled 选项。 the react-admin documentation 的例子展示了它的用法:

      // 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) }
        );
        // ...
      };
      

      但是,由于钩子的规则,这不会解决您在循环中的问题。

      如果您确实需要该循环,最好的办法是使用the useDataProvider hook 直接调用 dataProvider:

      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;
      };
      

      【讨论】:

      • 感谢您的回答,我不知道enabled 选项。可以通过调用 getList() 然后遍历响应的数据来避免循环中的钩子问题。不过,我寻求帮助的主要问题是 matchSuggestion 需要一个函数,因此根本不能使用钩子来匹配建议。这仅仅是 React 管理员的限制,还是在匹配过程中获取记录的另一种方法?谢谢
      • 您可以在 React 组件中定义传递给 matchsuggestion 的函数,并在该组件中使用钩子
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多