Reputation: 147
Hello all and thanks in advance.
Just to begin with, I am aware that weather data is not a suitable use case for RTK Query as it is always changing, I am using RTK Query in this case just for practicing purposes.
I want to refetch weather data upon a button click but the component is not being updated, however I can see that the requestId
is indeed changing when clicking the refresh button and that data is being retrieved, by checking the console.
I am doing the refetch as in the example that can be found in the official docs:
I am also wondering if it would be more suitable to use useLazyQuery and its trigger
function instead...
https://redux-toolkit.js.org/rtk-query/api/created-api/hooks#uselazyquery
...but if so, what should I take into account in order to decide if I use useQuery or 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;
Upvotes: 12
Views: 36819
Reputation: 994
I'm not allowed to leave a comment yet, so I'll try to answer you question regarding useLazyQuery
vs useQuery
here:
useQuery
- got triggered on render. Retriggered on params change. Returns data from cache if the cache has some valid data. refetch
allows to ignore cache, and forces to make a real API call. refetch
has no query params, so you'll need to pass them to initial hook call.
useLazyQuery
- got triggered firstly on trigger
call, expecting the query params to be passed to trigger
, and by default will do a real API call. To get the cached data first (if exists) - you'll need to pass the preferCacheValue
param to the trigger
function as the second param.
So the "rule of thumb" will be to use
useQuery
by default to fetch data on the component mount, use refetch
when you want to make a real API call ignoring the cache.
useLazyQuery
- for cases like yours, when you want to make a call only later (ignoring the render stage) calling the "trigger" on some event (like a button click), and remember about the preferCacheValue
option for a case when you have a chance to have the response already cached - this will allow making response feels instantaneous.
In our case - useLazyQuery
is MUCH relevant, due to you can avoid all that setCurrentPosition
=> dispatch
=> useSelector
stuff, and pull all that logic just in click handler, where you'll be able to fetch Geolocation.getCurrentPosition()
and pass coordinates to trigger
function, that where relevant to the click time, not to the time when the component was rendered.
Upvotes: 34