【问题标题】:How to use Lazy query with React-query?如何在 React-query 中使用惰性查询?
【发布时间】:2022-01-27 14:32:48
【问题描述】:

我正在使用 React-query 进行 API 调用。我想知道是否有办法以懒惰的方式调用查询。

表示仅在查询参数更改时才调用查询。

这是我目前拥有的;我正在使用带有“useEffect”的hack,如果recipeName发生变化,则运行refetch函数。

export const searchRecipeByName = async (recipeName: string) => {
  return await api.get(
    `/recipes/complexSearch?apiKey=${process.env.NEXT_PUBLIC_SPOONACULAR_API_KEY}&query=${recipeName}&addRecipeInformation=true&fillIngredients=true`
  );
};
  const [recipeName, setRecipeName] = useState("");

  const { data, refetch } = useQuery(
    "homePageSearchQuery",
    () => searchRecipeByName(recipeName),
    { enabled: false }
  );

// HACK
  useEffect(() => {
    if (!!recipeName) {
      refetch();
    }
  }, [recipeName]);

  const handleOnSearchSubmit = async (recipeSearch: RecipeSearch) => {
    setRecipeName(recipeSearch.search);
  };

最好在“handleOnSearchSubmit”函数中调用查询。

我可以创建一个自定义的 useLazyQuery 挂钩来处理这个问题,但我想知道 React-query 是否有本地方法来处理这个问题。

【问题讨论】:

    标签: javascript reactjs api react-query


    【解决方案1】:

    这样做

    const { isLoading, data } = useQuery([
        'homePageSearchQuery',
        {recipeName}],
        () => searchRecipeByName(recipeName), {}
    );
    

    只要 recipeName 的值发生变化,它就会运行查询。

    【讨论】:

    • 嗨易卜拉欣,我最初尝试过,但它不起作用。我还尝试在“handleOnSearchSubmit”函数中调用 refetch 函数。但是 refetch 不接受查询字符串参数
    • 好的,删除启用确实有效。但这似乎也会在每次重新渲染时触发查询
    • 很高兴它正在工作,因为您最初将启用值设置为 false,它正在阻止钩子触发 fetch 查询。关于重新渲染,您需要检查导致多次重新渲染的原因并加以处理。
    • 如果您使用它进行搜索,我也建议您在使用查询时使用debounce。我个人使用lodash中的debounce函数
    • 谢谢,它用于搜索,但它是在单击按钮时进行搜索。但是有没有办法只在调用“handleOnSearchSubmit”时才运行查询?在 Apollo 客户端中,原生有 useLazyQuery 钩子。
    【解决方案2】:

    最好在“handleOnSearchSubmit”函数中调用查询。

    这是一种非常必要的思考方式,但 react-query 更具声明性。您没有指定:“当我单击该按钮时,我想获取”,但您只是说:“这些是我需要的输入”并且 react-query 将在这些输入更改时重新获取。

    所以你想要做的就是把你的查询运行所需的东西放入查询键中,以便 react-query

    • 为每个依赖项分别缓存
    • 只要依赖项还没有准备好,你就可以禁用它
    const [recipeName, setRecipeName] = React.useState('')
    const { isLoading, data } = useQuery(
      ['homePageSearchQuery', recipeName],
      () => searchRecipeByName(recipeName),
      {
        enabled: !!recipeName
      }
    ])
    

    然后,您只需在handleOnSearchSubmit 中调用setRecipeName,react-query 就会进行查询。

    您可能需要考虑的其他事项:

    • 如果您想避免在recipeName 更改之间出现硬加载状态,请设置keepPreviousData: true
    • 上述代码将在每次recipeName 更改时运行一个查询。如果单击按钮时没有发生这种情况,但只要用户在输入字段中键入内容时说,您就想消除它。对于这些情况,请考虑useDebounce
    const [recipeName, setRecipeName] = React.useState('')
    const debouncedRecipeName = useDebounce(recipeName, 1000)
    const { isLoading, data } = useQuery(
      ['homePageSearchQuery', debouncedRecipeName],
      () => searchRecipeByName(debouncedRecipeName),
      {
        enabled: !!debouncedRecipeName
      }
    ])
    

    这将允许您输入数据并将其显示在文本字段中,但只会创建一个新的缓存条目/在 1 秒不活动后触发一个新请求。

    • 如果你想有一个提交表单的按钮,最好“提升状态”:有一个查询所依赖的更全局的状态,以及表单的一些本地状态。一旦用户点击“提交”,您将用户选择保存在更高的状态中,这将触发查询。我喜欢为此使用 url,并且我有一个完整的codesandbox example here。在该示例中,实际的表单状态不受控制,但您也可以为此使用 state 或表单库

    【讨论】:

    • 感谢 TKDodo 的广泛回答。遗憾的是 React-query 没有像 Apollo 客户端那样原生的 useLazyQuery。我会试一试
    猜你喜欢
    • 1970-01-01
    • 2021-05-31
    • 2017-02-07
    • 1970-01-01
    • 2022-11-17
    • 1970-01-01
    • 2019-09-16
    • 2013-05-02
    • 2014-08-27
    相关资源
    最近更新 更多