如何在 React-query 中使用惰性查询?

How to use Lazy query with React-query?

我正在为我的 API 调用使用 React-query。我想知道是否有一种方法可以以惰性方式调用查询。

意味着仅当查询参数更改时才调用查询。

这是我目前拥有的;我正在使用带有“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 是否有本地方法来处理这个问题。

这样做

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

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

Preferably, I would like to call the query in the "handleOnSearchSubmit" function.

这是一种非常命令式的思考方式,但 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。在该示例中实际的表单状态是不受控制的,但您也可以为此使用状态或表单库