在 RTK 查询中单击按钮重新获取不会触发组件更新
Refetching upon a button click in RTK Query does not trigger component update
大家好,提前致谢。
首先,我知道天气数据不是 RTK 查询的合适用例,因为它总是在变化,我在这种情况下使用 RTK 查询只是为了练习目的。
我想在单击按钮时重新获取天气数据,但组件没有更新,但是我可以看到 requestId
在单击刷新按钮时确实发生了变化,并且正在通过检查控制台检索数据。
我正在按照官方文档中的示例进行重新获取:
我也想知道使用 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;
我还不能发表评论,所以我会尝试在这里回答你关于 useLazyQuery
和 useQuery
的问题:
useQuery
- 在渲染时被触发。在参数更改时重新触发。 Returns 如果缓存有一些有效数据,则来自缓存的数据。 refetch
允许忽略缓存,并强制进行真正的 API 调用。 refetch
没有查询参数,因此您需要将它们传递给初始挂钩调用。
useLazyQuery
- 在 trigger
调用时首先触发,期望查询参数传递给 trigger
,默认情况下会进行真正的 API 调用。要首先获取缓存数据(如果存在)——您需要将 preferCacheValue
参数作为第二个参数传递给 trigger
函数。
所以“经验法则”将使用
useQuery
默认情况下在组件装载上获取数据,当你想进行真正的 API 调用时使用 refetch
忽略缓存。
useLazyQuery
- 对于像您这样的情况,当您只想稍后进行调用(忽略渲染阶段)时调用某个事件的“触发器”(例如单击按钮),并记住preferCacheValue
当您有机会缓存响应的情况下的选项 - 这将使响应感觉即时。
在我们的例子中 - useLazyQuery
非常重要,因为你可以避免所有 setCurrentPosition
=> dispatch
=> useSelector
的东西,然后拉所有那些单击处理程序中的逻辑,您可以在其中获取 Geolocation.getCurrentPosition()
并将坐标传递给 trigger
函数,该函数与单击时间相关,而不是组件呈现的时间。
大家好,提前致谢。
首先,我知道天气数据不是 RTK 查询的合适用例,因为它总是在变化,我在这种情况下使用 RTK 查询只是为了练习目的。
我想在单击按钮时重新获取天气数据,但组件没有更新,但是我可以看到 requestId
在单击刷新按钮时确实发生了变化,并且正在通过检查控制台检索数据。
我正在按照官方文档中的示例进行重新获取:
我也想知道使用 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;
我还不能发表评论,所以我会尝试在这里回答你关于 useLazyQuery
和 useQuery
的问题:
useQuery
- 在渲染时被触发。在参数更改时重新触发。 Returns 如果缓存有一些有效数据,则来自缓存的数据。 refetch
允许忽略缓存,并强制进行真正的 API 调用。 refetch
没有查询参数,因此您需要将它们传递给初始挂钩调用。
useLazyQuery
- 在 trigger
调用时首先触发,期望查询参数传递给 trigger
,默认情况下会进行真正的 API 调用。要首先获取缓存数据(如果存在)——您需要将 preferCacheValue
参数作为第二个参数传递给 trigger
函数。
所以“经验法则”将使用
useQuery
默认情况下在组件装载上获取数据,当你想进行真正的 API 调用时使用 refetch
忽略缓存。
useLazyQuery
- 对于像您这样的情况,当您只想稍后进行调用(忽略渲染阶段)时调用某个事件的“触发器”(例如单击按钮),并记住preferCacheValue
当您有机会缓存响应的情况下的选项 - 这将使响应感觉即时。
在我们的例子中 - useLazyQuery
非常重要,因为你可以避免所有 setCurrentPosition
=> dispatch
=> useSelector
的东西,然后拉所有那些单击处理程序中的逻辑,您可以在其中获取 Geolocation.getCurrentPosition()
并将坐标传递给 trigger
函数,该函数与单击时间相关,而不是组件呈现的时间。