React-query:onSuccess、onError、onSettled 已弃用。我应该用什么来代替?

net*_*ite 21 reactjs react-query

在此代码片段中,当我将鼠标悬停在onSuccess回调上时,它表示它已被弃用并将在下一个主要版本中删除。onError和回调也会发生同样的情况onSettled。我该用什么来代替?

  const { isError, error, data, refetch, isFetching } = useQuery(
    ["posts"],
    fetchPosts,
    { enabled: false, onSuccess: () => {} }
  );
Run Code Online (Sandbox Code Playgroud)

net*_*ite 32

onError

onError您可以在queryCache选项中使用回调QueryClient

import {
  QueryCache,
  QueryClient,
} from "@tanstack/react-query";
import { toast } from "react-toastify";

const queryClient = new QueryClient({
  queryCache: new QueryCache({
    onError: (error) => {
      toast(`Something went wrong: ${error.message}`),
    }
  }),
})
Run Code Online (Sandbox Code Playgroud)

然后像平常一样用它包装您的应用程序:

function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <Posts />
    </QueryClientProvider>
  )
}
Run Code Online (Sandbox Code Playgroud)

如果您需要更多可定制的onError副作用,请使用钩子meta选项useQuery。您可以向其传递任何您想要的数据,然后您可以使用这些数据来确定要触发的副作用。

我想出了这个解决方案:

定义一个包含用于触发副作用的错误代码的枚举:

export const enum TErrCodes {
  POSTS_FETCH_FAILED,
  // other error codes...
}
Run Code Online (Sandbox Code Playgroud)

meta在钩子的选项中指定错误代码useQuery

const query = useQuery(["posts"], fetchPosts, {
  meta: { errCode: TErrCodes.POSTS_FETCH_FAILED },
});
Run Code Online (Sandbox Code Playgroud)

检测回调中的错误代码queryCache onError并执行您需要的副作用。react-toastify我使用库作为示例显示通知:

const queryClient = new QueryClient({
  queryCache: new QueryCache({
    onError: queryCacheOnError,
  }),
});

function queryCacheOnError(err: unknown, query: Query) {
  switch (query.meta?.errCode) {
    case TErrCodes.POSTS_FETCH_FAILED:
      return toast.error("Could not fetch posts");
    default:
      return toast.error("Something went wrong");
  }
}
Run Code Online (Sandbox Code Playgroud)

或者,您可以onError从查询函数触发副作用,如下所示:

async function fetchPosts() {
  try {
    const resp = await axios.get<TPost[]>("/posts");
    return resp.data;
  } catch (err) {
    if (!isKnownErr(err)) {
      return toast("Something went wrong");
    }

    switch (err.response.data.errCode) {
      case "INVALID_CREDENTIALS":
        toast("Invalid sign-in credentials");
        break;
      // more cases...
      default:
        toast("Something went wrong");
    }

    throw new Error(); // prevent query from being successful
  }
}

const query = useQuery(["posts"], fetchPosts);
Run Code Online (Sandbox Code Playgroud)

onSuccess

您也可以onSuccess从查询函数内部触发副作用,如下所示:

async function fetchPosts() {
  const resp = await axios.get<TPost[]>("/postss");
  yourSideEffect();
  return resp.data;
}
const query = useQuery(["posts"], fetchPosts);
Run Code Online (Sandbox Code Playgroud)

为什么它们首先被删除?

这大部分摘自这篇文章

  1. 回调的行为不一致。可以针对同一查询多次调用它们,从而导致重复的副作用或状态更新。例如,这可能会导致同一查询显示 2 个重复的错误通知。

  2. 一些开发人员滥用回调来执行状态同步操作,这通常会导致很难发现的错误。您应该使用诸如 之类的东西来派生状态const postsCount = posts.length;postsCount每当组件重新渲染时,该变量都会更新。

  3. 使用回调有时会导致 redux 和其他状态管理器出现意外行为。

这是关于该主题的另一篇文章

希望您觉得这有帮助!

  • 如何使另一个函数的查询缓存无效?我将 API 调用方法与组件代码分开,以便很好地测试它们。所以我不能使用 `useQueryClient();` 挂钩来使缓存无效。例如,使用 `queryClient.invalidateQueries(["products"]);` (4认同)
  • @tobias 对于 `useMutation` 钩子,我没有改变任何东西,因为只有 `useQuery` 会改变。为此,我只是改变了调用函数的方式。我不只是提供函数,而是将所有内容重写为 .. async () =&gt; {await fetchPosts(); queryClient.invalidate();}..除了提出的解决方案之外,它还可以正常工作 (2认同)