Some way to check if the query in Next.js is loading or some way to check if the query was skipped?

I currently have a problem where I want to check if my query was skipped or if it is just waiting for the response.
const { locale, query, replace } = useRouter();

const cityById = useQuery(
convexApi.getCity.findCityById,
typeof query.cityId === "string" ? { id: parseInt(query.cityId) } : "skip",
);

if (!(typeof query.cityId === "string")) { /* <- This somehow always is triggered/true so idk maybe a stupid idea to check for that */
if (activeCity$.id.get() !== 0 && activeCity$.name.get() !== "") {
void replace("/home?cityId=" + activeCity$.id.get());
return;
} else {
void replace("/search");
return;
}
}
const { locale, query, replace } = useRouter();

const cityById = useQuery(
convexApi.getCity.findCityById,
typeof query.cityId === "string" ? { id: parseInt(query.cityId) } : "skip",
);

if (!(typeof query.cityId === "string")) { /* <- This somehow always is triggered/true so idk maybe a stupid idea to check for that */
if (activeCity$.id.get() !== 0 && activeCity$.name.get() !== "") {
void replace("/home?cityId=" + activeCity$.id.get());
return;
} else {
void replace("/search");
return;
}
}
27 Replies
erquhart
erquhart•12mo ago
You can: 1. check the dashboard for logs to see if the function ran 2. console log the result of your conditional there
FleetAdmiralJakob 🗕 🗗 🗙
So I basically have multiple options: - I'm waiting for the response: Just wait longer if the response shows that no value is there and in the global state is no city than just redirect the person to /search - In the url is no city but in the global state is in the city: just put the city in the url and start again - If the value is only in the url it's fine we can just use that Yes, but I cant programmatically see if the function runs right? I want to have something like a loading state or something to see if the function runs.
erquhart
erquhart•12mo ago
As long as useQuery() is returning undefined, it's loading - anything else, it's no longer loading. If you want both loading and skipped to appear as loading, you can combine those two conditions.
const isLoading = cityById === undefined && typeof query.cityId !== 'string'
const isLoading = cityById === undefined && typeof query.cityId !== 'string'
FleetAdmiralJakob 🗕 🗗 🗙
Oh nice, I will try it out This seems not to work... if there is no query.cityId (it's undefined) and because of that the convex query returns undefined isLoading is true even if it isn't loading
erquhart
erquhart•12mo ago
Oh if you only want isLoading to be true if query.cityId is defined, just switch the logic for that part
const isLoading = cityById === undefined && typeof query.cityId === 'string'
const isLoading = cityById === undefined && typeof query.cityId === 'string'
That will only evaluate true if query.cityId is defined and useQuery() is returning undefined. In this case you know the query is not being skipped, is so it's actually loading.
FleetAdmiralJakob 🗕 🗗 🗙
@erquhart Ok, but unfortunately the is loading thing turn into false before there is an actual value.
const cityById = useQuery(
convexApi.getCity.findCityById,
typeof query.cityId === "string" ? { id: parseInt(query.cityId) } : "skip",
);

useEffect(() => {
const cityByIdIsLoading =
cityById === undefined && typeof query.cityId === "string";
console.log("cityByIdIsLoading", cityByIdIsLoading);
console.log("type of query.cityId", typeof query.cityId);
console.log("cityById", cityById);
if (!cityByIdIsLoading && !cityById) {
if (activeCity$.id.get() !== 0 && activeCity$.name.get() !== "") {
void replace("/home?cityId=" + activeCity$.id.get());
return;
} else {
console.log("cityByIdIsLoading 2", cityByIdIsLoading);
console.log("type of query.cityId 2", typeof query.cityId);
console.log("cityById 2", cityById);
// void replace("/search");
return;
}
}
});
const cityById = useQuery(
convexApi.getCity.findCityById,
typeof query.cityId === "string" ? { id: parseInt(query.cityId) } : "skip",
);

useEffect(() => {
const cityByIdIsLoading =
cityById === undefined && typeof query.cityId === "string";
console.log("cityByIdIsLoading", cityByIdIsLoading);
console.log("type of query.cityId", typeof query.cityId);
console.log("cityById", cityById);
if (!cityByIdIsLoading && !cityById) {
if (activeCity$.id.get() !== 0 && activeCity$.name.get() !== "") {
void replace("/home?cityId=" + activeCity$.id.get());
return;
} else {
console.log("cityByIdIsLoading 2", cityByIdIsLoading);
console.log("type of query.cityId 2", typeof query.cityId);
console.log("cityById 2", cityById);
// void replace("/search");
return;
}
}
});
FleetAdmiralJakob 🗕 🗗 🗙
As you can see here the cityByIdIsLoading is first getting false and after that the actual value is there
No description
FleetAdmiralJakob 🗕 🗗 🗙
so it's like: not loading and no value <- Here I think is the problem because in this state my app thinks that there is no data loading and no value not loading and value
erquhart
erquhart•12mo ago
Right, if query.cityId is not a string you're effectively "pre-loading" So if you want to do something different before loading actually starts, you can check for that first
FleetAdmiralJakob 🗕 🗗 🗙
Interesting... mhmm... idk man how to do that. but maybe for the convex part it's done and I have to figure out why Next.js does not give me the value immediately seems weird that my url params are first not there and then they come all of the sudden could you tell me more about pre-loading? so how can I find out if it's the actual url param that is undefined or the url param is not loaded yet
erquhart
erquhart•12mo ago
Sorry, by "preloading" I just mean loading hasn't actually started since you don't have the query param yet Is it taking like a few seconds for next to provide the query params or is it really short?
FleetAdmiralJakob 🗕 🗗 🗙
idk, why does this matter? should I make a timeout or something like that?
erquhart
erquhart•12mo ago
If it's short you could just treat both states as loading, unless this is a view where the query string can keep changing and you need to keep loading to update Ah just reread your original post, you're navigating based on this state so you need resolution before moving forward Yeah delayed query params is a problem. Is this a client or server component?
FleetAdmiralJakob 🗕 🗗 🗙
This app is still on the pages dir so it's a client component maybe I need to switch in the future (i get more and more problems with it)
erquhart
erquhart•12mo ago
Ah! useRouter() returns an isReady prop actually... that may be old
erquhart
erquhart•12mo ago
but they should have something to that effect
FleetAdmiralJakob 🗕 🗗 🗙
it is safe to use? I think it works now. with the isReady prop, update you if it isn't working anymore
erquhart
erquhart•12mo ago
Looks like they recommend using useSearchParams from next/navigation instead: https://nextjs.org/docs/app/api-reference/functions/use-router#router-events
Functions: useRouter | Next.js
API reference for the useRouter hook.
erquhart
erquhart•12mo ago
instead of query oh isReady is there?
FleetAdmiralJakob 🗕 🗗 🗙
useSearchParams only exist on app dir 🫤
erquhart
erquhart•12mo ago
interesting, it's not in the docs ah, gotcha
erquhart
erquhart•12mo ago
if isReady is working, great! undocumented though it seems, so may want to keep an eye on it. Are you using an old version of next maybe? ooohhh
FleetAdmiralJakob 🗕 🗗 🗙
Functions: useRouter | Next.js
Learn more about the API of the Next.js Router, and access the router instance in your page with the useRouter hook.
erquhart
erquhart•12mo ago
I guess App Router is different
FleetAdmiralJakob 🗕 🗗 🗙
yes, they changed the apis for app router

Did you find this page helpful?