I have a React Query component like this:
function test () {
const [var, setVar] = useState("")
const options = {
method: "GET",
url: "https://api.themoviedb.org/3/search/tv",
params: {
query: var,
page: "1",
},
headers: {
accept: "application/json",
Authorization:
"Bearer insertAuthKey123456789",
},
};
function fetchTvData(): Promise<void | ShowData> {
return axios.request(options);
}
const { data} = useQuery({
queryKey: ["tvSearchQuery", tvSearchQuery],
queryFn: fetchTvData,
});
console.log(data?.data);
}
When I fetch data, it always fetches the previous query result. So if I search "foo", and then search "bar", it will return as if I passed "foo" into the query. I read the docs on passing variables into queries, however I'm not familiar how to do it when using an options object that accepts the query and passing that object into axios.request(object). Any help would be appreciated, thanks!
Here is the "un-abbreviated" version of the code in case the one above doesn't provide enough context:
import { useQuery } from "react-query";
import axios from "axios";
import { Stack, TextField, Button } from "@mui/material";
import { useForm } from "react-hook-form";
import { useState } from "react";
interface FormValues {
tvSearch: string;
}
interface Tv {
id: number;
}
interface ShowData {
data: Tv[];
}
function ShowBox() {
const [tvSearchQuery, setTvSearchQuery] = useState("");
const form = useForm<FormValues>({
defaultValues: {
tvSearch: "",
},
});
const { register, handleSubmit, formState } = form;
const { errors } = formState;
const options = {
method: "GET",
url: "https://api.themoviedb.org/3/search/tv",
params: {
query: tvSearchQuery,
include_adult: "false",
language: "en-US",
page: "1",
},
headers: {
accept: "application/json",
Authorization:
"Bearer key1234",
},
};
function onSubmit(data: FormValues) {
setTvSearchQuery(data.tvSearch);
refetch();
}
function fetchTvData(): Promise<void | ShowData> {
return axios.request(options);
}
function onSuccess(data: object) {
console.log("success", data);
}
function onError(error: Error) {
console.log("ERROR", error);
}
const { data, refetch } = useQuery({
queryKey: ["tvSearchQuery", tvSearchQuery],
queryFn: fetchTvData,
refetchOnWindowFocus: false,
enabled: false,
onSuccess,
onError,
});
console.log(data?.data);
return (
<form onSubmit={handleSubmit(onSubmit)} noValidate>
<Stack spacing={2}>
<TextField
label="Enter a show or movie"
type="tvSearch"
{...register("tvSearch")}
error={!!errors.tvSearch}
helperText={errors.tvSearch?.message}
/>
<Button type="submit" variant="contained">
Search
</Button>
</Stack>
</form>
);
}
You have set enabled: false
in useQuery
. This means the query won't run by default. In onSubmit
refetch is called, which will trigger the query even though it is not enabled
. At this point you have called setTvSearchQuery
, but that change have not taken effect yet, meaning the refetch
will fetch the previous tvSearchQuery
.
The correct way to set this up is by setting enabled: true
(or possibly enabled
only if there is a tvSearchQuery
). And also removing the refetch
call.
function onSubmit(data: FormValues) {
setTvSearchQuery(data.tvSearch);
}
// [...]
const { data } = useQuery({
queryKey: ["tvSearchQuery", tvSearchQuery],
queryFn: fetchTvData,
refetchOnWindowFocus: false,
// enabled: true is the default so the following line can be removed
enabled: true,
// alternatively enable the query only if there is a tvSearchQuery
// enabled: !!tvSearchQuery
onSuccess,
onError,
});