Peform
Peform2mo ago

TRPC response data changing to undefined when typing in a form field.

Hello, I'm currently having a very strange issue, I am using a form to input some data and send off to a trpc endpoint to retrieve some data from the server when I click the submit button. However, the respnose userData variable is being changed to undefined whenever I type into the form field. I am not sure why this is happening as I do not mutate userData anywhere, and there are no new TRPC queries running (verified checking network tab) and the TRPC endpoint is set to disabled. So it will only fetch data once I call the refetch function... Anyone have any idea?
2 Replies
Peform
Peform2mo ago
export function UserLookup() {
const searchParams = useSearchParams();
const [filters, _setFilters] = useState();
const [filteredGenerations, _setFilteredGenerations] = useState<
RouterOutputs["userLookup"]["getGenerations"]
>([]);

const form = useForm<z.infer<typeof lookupUserSchema>>({
resolver: zodResolver(lookupUserSchema),
defaultValues: {
userId: searchParams.get("userId") ?? "",
},
});

const { data: userData, refetch: refetchUserData } =
api.userLookup.find.useQuery(
{
userId: form.getValues("userId"),
},
{
enabled: false,
},
);

const handleLookupUser = async () => {
const response = await refetchUserData();
if (response.error) {
toast({
title: "Error",
description: response?.error?.message ?? "An unknown error occurred",
});
}
};

console.log(1, userData);

return (
<>
<div className="flex flex-col gap-4">
<Form {...form}>
<form onSubmit={form.handleSubmit(handleLookupUser)}>
<FormField
control={form.control}
name="userId"
render={({ field }) => (
<FormItem className="grow">
<FormLabel>Prompt</FormLabel>
<FormControl>
<Input
placeholder="Enter your prompt"
maxLength={2048}
className="resize-none"
type="text"
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button className="mt-3" type="submit">
Lookup user
</Button>
</form>
</Form>
{userData && (...)}
</>
export function UserLookup() {
const searchParams = useSearchParams();
const [filters, _setFilters] = useState();
const [filteredGenerations, _setFilteredGenerations] = useState<
RouterOutputs["userLookup"]["getGenerations"]
>([]);

const form = useForm<z.infer<typeof lookupUserSchema>>({
resolver: zodResolver(lookupUserSchema),
defaultValues: {
userId: searchParams.get("userId") ?? "",
},
});

const { data: userData, refetch: refetchUserData } =
api.userLookup.find.useQuery(
{
userId: form.getValues("userId"),
},
{
enabled: false,
},
);

const handleLookupUser = async () => {
const response = await refetchUserData();
if (response.error) {
toast({
title: "Error",
description: response?.error?.message ?? "An unknown error occurred",
});
}
};

console.log(1, userData);

return (
<>
<div className="flex flex-col gap-4">
<Form {...form}>
<form onSubmit={form.handleSubmit(handleLookupUser)}>
<FormField
control={form.control}
name="userId"
render={({ field }) => (
<FormItem className="grow">
<FormLabel>Prompt</FormLabel>
<FormControl>
<Input
placeholder="Enter your prompt"
maxLength={2048}
className="resize-none"
type="text"
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button className="mt-3" type="submit">
Lookup user
</Button>
</form>
</Form>
{userData && (...)}
</>
And as an extra question, is this method of data querying a best practise? I feel like for data querying like this a useMutation is better suited, even though mutations are for changing data not querying... the syntax for mutations is much better suited for this scenario I believe.
wise_pomelo_81978
As I mentioned in https://discord.com/channels/867764511159091230/1248003136543522876, it is likely changing to undefined because form.getValues("userId") is changing every time you type and the query cache only has a value for userData for the value that is in the box when you hit submit. You should have your submit button set something in react state and use that for your userId parameter to the query. That way the value will be stable and only change when submit is pressed.