How to useQuery and invalidateQueries with ReactQuery 如何使用 invalidateQueries 場景與用途

Tips:

使用 ReactQuery 要記得, qureryKey 是 String Array ,用 invalidateQueries 。 qureryKey 是用來讓 ReactQuery 判斷要刷新哪些資料的。

使用場景

當我們使用 useMutation ,希望自動刷新目前新的狀態時,可以在 useMutation onSuccess 時,呼叫 queryClient.invalidateQueries,來讓目前快取中的 status 失效,去刷新新的資料。

import { useQuery, useQueryClient } from "@tanstack/react-query";

// 从上下文中获取 QueryClient
const queryClient = useQueryClient();

queryClient.invalidateQueries({ queryKey: ["todos"] });

// 下面的两个查询都会被无效
const todoListQuery = useQuery({
  queryKey: ["todos"],
  queryFn: fetchTodoList,
});
const todoListQuery = useQuery({
  queryKey: ["todos", { page: 1 }],
  queryFn: fetchTodoList,
});

Case Study

import { Button, Col, Descriptions, Row, Space, Tag } from "antd";
import styles from "./setting-page.module.less";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { getPaymentSetting, setPaymentSetting } from "@service/api";
import Authenticated from "@components/auth/Authenticated";

export const PREFERENCE_STATUS_QUERY_KEY = ["preference", "status"];
const PreferencesPage: React.FC = () => {
  const queryClient = useQueryClient();

  const { data: paymentSetting } = useQuery(
    PREFERENCE_STATUS_QUERY_KEY,
    getPaymentSetting
  );
  const { mutate: performSetPaymentSetting } = useMutation(setPaymentSetting, {
    onSuccess: () => {
      queryClient.invalidateQueries(PREFERENCE_STATUS_QUERY_KEY);
    },
    onError: (error) => {
      console.error("error:", error);
    },
  });

  return (
    <Authenticated>
      <div className={styles.panelBox}>
        <div className={styles.panelTitle}>
          <div className={styles.caption}>Preferences</div>
        </div>{" "}
        <div className={styles.panelBody}>
          <Row gutter={[16, 0]}>
            <Col span={14}>
              <Descriptions
                column={2}
                title="Sync Payments from Quickbooks Online to "
              >
                <Descriptions.Item label="Payment Sync Status">
                  {paymentSetting?.enable_payment_sync ? (
                    <Tag color="green">On</Tag>
                  ) : (
                    <Tag color="red">Off</Tag>
                  )}
                </Descriptions.Item>
              </Descriptions>{" "}
              <div className={styles.actionBox}>
                <Space direction="horizontal">
                  <Button
                    block
                    type="primary"
                    onClick={() => {
                      performSetPaymentSetting({ enable_payment_sync: true });
                    }}
                  >
                    Turn Payment Sync On
                  </Button>
                  <Button
                    block
                    danger
                    onClick={() => {
                      performSetPaymentSetting({ enable_payment_sync: false });
                    }}
                  >
                    Turn Payment Sync Off
                  </Button>
                </Space>{" "}
              </div>{" "}
            </Col>{" "}
          </Row>{" "}
        </div>{" "}
      </div>{" "}
    </Authenticated>
  );
};

export default PreferencesPage;

API Call Tips

Sometime useMutation onSuccess and onError won't be call, because the wrong data type being return from the back-end.

有些時候 useMutation onSuccess 都不會被執行,可能要檢查,在呼叫 api 時,定義的 Content-Type 後端是否有回傳正確。

是因為 await response.json();解不出來 string 導致的。

const DEFAULT_HEADERS = {
  "Content-Type": "application/json",
};

export const request = async <ResponseType>(
  url: string,
  init?: RequestInit
): Promise<ResponseType> => {
  const { headers, ...rest } = init ?? {};
  const response = await fetch(url, {
    headers: combineHeaders(headers),
    ...rest,
  });
  const data = await response.json();
  if (response.ok) {
    return data;
  } else {
    return Promise.reject(data);
  }
};

Metadata

Status :: #status/🌱

Note Type :: #📩/📰

Source URL :: 主动查询失效 Query Invalidation | TanStack Query 中文文档

Author :: {作者名稱}

Topics :: {筆記跟什麼主題有關,用[Topic],[Topic] 格式子}

To Me :: #mind

Parent Link :: {可以連結到哪個父筆記}

Sibling Link :: {可以連結到哪個相關筆記}

Child Link :: {可以連結到哪個子筆記}