RTK 查询中单击按钮重新获取不会触发组件更新

jpx*_*car 9 reactjs ionic-framework redux-toolkit rtk-query

大家好,提前致谢。

首先,我知道天气数据不适合 RTK 查询,因为它总是在变化,在这种情况下我使用 RTK 查询只是出于练习目的。我想在单击按钮时重新获取天气数据,但组件没有更新,但是requestId通过检查控制台,我可以看到单击刷新按钮时确实发生了变化,并且正在检索数据。我正在按照官方文档中的示例进行重新获取:

https://redux-toolkit.js.org/rtk-query/usage/cache-behavior#re-fetching-on-demand-with-refetchinitiate

我还想知道使用 useLazyQuery 及其trigger函数是否更合适......

https://redux-toolkit.js.org/rtk-query/api/created-api/hooks#uselazyquery

...但如果是这样,我应该考虑什么才能决定使用 useQuery 还是 useLazyQuery?

    import {
  IonButton,
  IonButtons,
  IonCard,
  IonCol,
  IonContent,
  IonGrid,
  IonHeader,
  IonPage,
  IonRow,
  IonTitle,
  IonToolbar,
} from "@ionic/react";
import styles from "./Tab1.module.css";
import { RefreshOutline } from "react-ionicons";
import { Geolocation } from "@capacitor/geolocation";
import { useEffect } from "react";
import { RootState } from "../app/store";
import { useDispatch, useSelector } from "react-redux";
import { useGetCurrentPositionWeatherQuery } from "../services/weather";
import { setQueryCoord } from "../app/coordQuerySlice";
import TestSkeleton from "../components/TestSkeleton";

const Tab1: React.FC = (): JSX.Element => {
  const dispatch = useDispatch();
  const coordQueryState = useSelector((state: RootState) => state.coordQuery);
  const {
    requestId,
    refetch,
    data: weatherData,
    isLoading,
  } = useGetCurrentPositionWeatherQuery(
    {
      lat: coordQueryState.lat,
      lon: coordQueryState.lon,
      appid: "xxxx",
    },
    { skip: coordQueryState.skip }
  );

  const setCurrentPosition = async () => {
    const data = await Geolocation.getCurrentPosition();
    const {
      coords: { latitude: latFetched },
      coords: { longitude: lonFetched },
    } = data;
    dispatch(setQueryCoord({ lat: latFetched, lon: lonFetched, skip: false }));
  };

  useEffect(() => {
    setCurrentPosition();
  }, []);

  function refreshCurrentPositionHandler() {
    refetch();
  }

  console.log(requestId);
  return (
    <IonPage>
      <IonHeader>
        <IonToolbar className={styles["ion-toolbar-dashboard"]}>
          <IonTitle className="ion-margin-bottom" size="large">
            Dashboard
          </IonTitle>
          <IonButtons slot="end">
            <IonButton>
              <RefreshOutline
                onClick={refreshCurrentPositionHandler}
                color={"black"}
                height="35px"
                width="35px"
                cssClasses={styles.refreshOutline}
              />
            </IonButton>
          </IonButtons>
        </IonToolbar>
      </IonHeader>
      <IonContent fullscreen>
        <>{!weatherData && <TestSkeleton />}</>
        {weatherData && (
          <>
            <IonGrid>
              <IonRow style={{ margin: "10px" }}>
                <IonCol className="ion-text-center">
                  <h1 style={{ fontSize: "20px" }}>
                    Here's your location based weather
                  </h1>
                </IonCol>
              </IonRow>
            </IonGrid>
            <IonGrid>
              <IonCard>
                <IonRow>
                  <IonCol className="ion-text-center">test content 1</IonCol>
                </IonRow>
                <IonRow>
                  <IonCol className="ion-text-center">test content 2</IonCol>
                </IonRow>
                <IonRow>
                  <IonCol className="ion-text-center">test content 3</IonCol>
                </IonRow>
                <IonRow>
                  <IonCol></IonCol>
                  <IonCol></IonCol>
                </IonRow>
                <IonRow>
                  <IonCol></IonCol>
                </IonRow>
                <IonRow>
                  <IonCol></IonCol>
                </IonRow>
                <IonRow>
                  <IonCol></IonCol>
                </IonRow>
              </IonCard>
            </IonGrid>
          </>
        )}
      </IonContent>
    </IonPage>
  );
};

export default Tab1;
Run Code Online (Sandbox Code Playgroud)

Eug*_*nko 31

我还不能发表评论,所以我会在这里尝试回答您有关useLazyQueryvs 的问题useQuery

useQuery- 渲染时触发。参数更改时重新触发。如果缓存中有一些有效数据,则从缓存中返回数据。refetch允许忽略缓存,并强制进行真正的 API 调用。refetch没有查询参数,因此您需要将它们传递给初始挂钩调用。

useLazyQuery- 首先在trigger调用时触发,期望将查询参数传递给trigger,并且默认情况下将执行真正的 API 调用。要首先获取缓存数据(如果存在) - 您需要将参数preferCacheValue作为trigger第二个参数传递给函数。

因此,“经验法则”是 useQuery默认使用来获取组件挂载上的数据,refetch当您想要进行真正的 API 调用而忽略缓存时使用。

useLazyQuery- 对于像您这样的情况,当您只想稍后拨打电话(忽略渲染阶段)时,在某些事件(例如单击按钮)上调用“触发器”,并记住当preferCacheValue您有机会时的情况的选项已经缓存了响应 - 这将使响应感觉是即时的。

在我们的例子中 -useLazyQuery非常相关,因为您可以避免所有setCurrentPosition=> dispatch=> 的useSelector东西,并将所有逻辑拉到点击处理程序中,您将能够在其中获取Geolocation.getCurrentPosition()坐标并将其传递给trigger函数,这与单击时间,而不是渲染组件的时间。