0

我真的不知道如何问清楚,但我会先粘贴我的代码并在下面提问。

function useToDos() {
  const queryCache = useQueryCache();
  const fetchTodos = useQuery(
    'fetchTodos',
    () => client.get(paths.todos).then(({ data }: any) => data),
    { enabled: false }
  );

  const createTodo = async ({ name ) =>
    await client.post(paths.todos, { name }).then(({ data }) => data);

  return {
    fetchTodos,
    createTodo: useMutation(createTodo, {
      onMutate: newItem => {
        queryCache.cancelQueries('fetchTodos');
        const previousTodos = queryCache.getQueryData('fetchTodos');
        queryCache.setQueryData('fetchTodos', old => [
          ...old,
          newItem,
        ]);
        return () => queryCache.setQueryData('fetchTodos', previousTodos);
      },
    }),
  };
}

如您所见,我正在尝试创建自己的自定义挂钩来包装反应查询功能。因此,我需要将我的fetchTodos查询设置为禁用,这样它就不会立即运行。但是,这会破坏所有后台数据获取吗?

具体来说,当我运行createTodoonMutate触发该方法时,理想情况下,我希望fetchTodos在后台更新查询,以便更新前端的待办事项列表,而无需再次发出请求。但似乎最初将查询设置为禁用,后台更新不会生效。

因为我不认为将 react-query 钩子包装到自定义钩子库中是一个非常好的主意,所以我可能会对相同的设置有更多问题,但现在,我将从这里开始。谢谢你。

4

2 回答 2

2

突变不会自动触发重新获取。使用 react-query 实现此目的的方法是通过queryCache.invalidateQueries在突变后使缓存无效。从文档:

invalidateQueries 方法可用于根据查询键或查询的任何其他功能可访问的属性/状态使缓存中的单个或多个查询无效并重新获取。默认情况下,所有匹配的查询都会立即标记为过时,并且活动查询会在后台重新获取。

因此,您可以将 配置为useMutation在突变解决时使查询无效。例子:

function useToDos() {
  const queryCache = useQueryCache();
  const fetchTodos = useQuery(
    'fetchTodos',
    () => client.get(paths.todos).then(({ data }: any) => data),
    { enabled: false }
  );

  const createTodo = async ({ name ) =>
    await client.post(paths.todos, { name }).then(({ data }) => data);

  return {
    fetchTodos,
    createTodo: useMutation(createTodo, {
      onMutate: newItem => {
        queryCache.cancelQueries('fetchTodos');
        const previousTodos = queryCache.getQueryData('fetchTodos');
        queryCache.setQueryData('fetchTodos', old => [
          ...old,
          newItem,
        ]);
        return () => queryCache.setQueryData('fetchTodos', previousTodos);
      },

      onSettled: () => {
        cache.invalidateQueries('fetchTodos');
      }

    }),
  };
}
于 2020-11-08T11:50:51.193 回答
0

将逻辑拆分为两个不同的钩子怎么样?而不是像useToDos?

这样你就可以有一个钩子来获取:

const fetchData = _ => client.get(paths.todos).then(({ data }: any) => data)

export default function useFetchTodo(
  config = {
    refetchOnWindowFocus: false,
    enabled: false
  }
) {
  return useQuery('fetchData', fetchData, config)
}

在你的突变钩子中,你可以手动重新获取,之前createTodo

import useFetchTodo from './useFetchTodo'
//
const { refetch } = useFetchTodo()

// before createTodo
refetch()

于 2020-09-19T12:40:46.293 回答