Hooks can only be called inside of the body of a function component.
Unanswered
Briard posted this in #help-forum
BriardOP
I saved id in the context, how can I get all employees data using the id
const { editedUserId } = useContext(AppContext);
useEffect(() => {
if (editedUserId) {
const { data } = trpc.user.userById.useQuery(editedUserId);
if (data) {
const user: User = data;
setUser(user);
} else {
console.error("Data is undefined");
}
}
}, [editedUserId]);
62 Replies
Don’t do this! Setting a state with the data coming from TRPC is duplicating your state. Also, hooks can only be called at the Top Level of your components.
Just call your TRPC api with the user id and it’ll retrigger when the id changes
Just call your TRPC api with the user id and it’ll retrigger when the id changes
Pacific thread herring
You can not use useQuery inside useEffect. Also you don't need useEffect to watch 'editedUserId' because useQuery automatically does that
You get access to the data, error and a lot more of you let TRPC (actually React Query) handle it
BriardOP
actually im using the same add employee page , and just wanted to fill the inputs if the data already exist
but when calling it directly it causes infinite loop
const { data } = trpc.user.userById.useQuery(editedUserId);
setUser(user);
Don’t set user inside the react component body
Why do you need the user in another state?
If the data exists you know a user already exists and needs to be edited right? You don’t need a separate (duplicate) state
BriardOP
im storing my data using useForm Actually , so i think i just need to update them without seperating the state
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
name: "",
email: "",
username: "",
password: "",
role: "user",
},
});
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
<FormField
control={form.control}
name="name"
render={({ field }) => (
<FormItem>
<FormLabel>Name</FormLabel>
<FormControl>
<Input
placeholder="John Doe"
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/></form>
</Form>
Where you set the form’s default values do this:
name: data?.name ?? “”,
email: data?.email ?? “”
…
name: data?.name ?? “”,
email: data?.email ?? “”
…
If it exists it’ll start with the values
If it doesn’t not it’ll fallback to empty “”
BriardOP
that's true actually thanks, but sometimes its getting the data and sometimes its not
console.log("edit page start", editedUserId);
const { data } = trpc.user.userById.useQuery(editedUserId);
console.log("data", data);
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
name: data?.name ?? "",
email: data?.email ?? "",
username: data?.username ?? "",
password: "",
role: (data?.role as "admin" | "user") ?? "user",
},
});
console.log(form.getValues());
userById: publicProcedure.input(z.string()).query(async ({ input }) => {
const id = input;
if (!id) {
return null;
}
const user = await getUserById(id);
return user;
}),
i think it's not sending another request when id field presist
You say when you submit the form?
BriardOP
when i click on edit button, it redirect me to addpage with the id
the form gets populated (filled) if there is an id
the form gets populated (filled) if there is an id
That works so far? Or there’s still a problem with the form being populated?
BriardOP
its not getting populated unless i go to another page and go back again
Mmmh that’s a cache problem
Are you defining the queryKey?
Are you defining the queryKey?
If you need the query to re-run every time the userId changes you need to put the userId as part of the query key to help React Query know it needs to run the queryFn again
BriardOP
const { data, isLoading } = trpc.user.userById.useQuery(editedUserId, {
queryKey: ["userById", editedUserId],
});
it should be something like this but i got error i think im not doing a correct syntax
Well TRPC should take care of the queryFn dependencies, I assume
Does this work?
const { data } = trpc.user.userById.useQuery(editedUserId, { enabled: !!editedUserId });
Does this work?
const { data } = trpc.user.userById.useQuery(editedUserId, { enabled: !!editedUserId });
Make it only run if you provide a user Id via props
Seems like you can’t pass a query Key so you don’t mess up with the automatic query keys assigned by TRPC
@luis_llanes Well TRPC should take care of the queryFn dependencies, I assume
Does this work?
const { data } = trpc.user.userById.useQuery(editedUserId, { enabled: !!editedUserId });
BriardOP
i updated the code
but yea still the same
const { data } = trpc.user.userById.useQuery(editedUserId, {
enabled: !!editedUserId,
});
but yea still the same
deepseek provided a bad practice ig
// Reset form values when `data` changes
useEffect(() => {
if (data) {
form.reset({
name: data.name,
email: data.email,
username: data.username,
password: "", // Password is not fetched, so it remains empty
role: data.role as "admin" | "user",
});
}
}, [data, form]);
If you wanna rest the form values there’s a method useForm provides called “reset”
@Briard i updated the code
tsx
const { data } = trpc.user.userById.useQuery(editedUserId, {
enabled: !!editedUserId,
});
but yea still the same
BriardOP
yea thanks , but actually the fields are still not updated even when calling enabled option
You could trigger a reset() fn inside the effect when the userId changes, being the last resource?
I don’t like picking use effects as my first go to because they’re most of the time unnecessary and only brings more problems
BriardOP
that's true
i dont like to use useEffect
but this fixed the problem
useEffect(() => {
if (data) {
form.reset({
name: data.name,
email: data.email,
username: data.username,
password: "", // Password is not fetched, so it remains empty
role: data.role as "admin" | "user",
});
}
}, [data, form]);
If you open a page in which the user exists will it populate it with no problem then?
@luis_llanes If you open a page in which the user exists will it populate it with no problem then?
BriardOP
if i re open the page (navigate to another page and go back), it get populate with no problem
Btw if you leave the enabled option it’ll avoid calling the function with an empty value and it makes sense if you only care about getting the user data when the id gets passed
Idk if you got rid of it but it’ll prevent an extra call in cases where you’re adding and id doesn’t exist
i feel that i wanna build a project for trpc and nextjs and drizzle where we implement add edit delete update functionalities
and more
i feel that trpc documentation sucks regarding nextjs too
Well, do you know react query?
TRPC assumes you know the building blocks they’re built upon: React Query and TypeScript (mainly)
TRPC assumes you know the building blocks they’re built upon: React Query and TypeScript (mainly)
@luis_llanes Well, do you know react query?
TRPC assumes you know the building blocks they’re built upon: React Query and TypeScript (mainly)
BriardOP
i created my graduation project using react query it was powerful
and easy to implement
useQuery , mutations , query key for invalidation , and nice crazy options is all i needed
Yes, and TRPC uses React Query internally so you have access to the same benefits that RQ gives (revalidation, caching, loading states, data, error states, refetching, synchronization)
@Briard i feel that i wanna build a project for trpc and nextjs and drizzle where we implement add edit delete update functionalities
TRPC isn’t opinionated on how you do your data fetching, it’s just a Typesafe way to call your “endpoints” from the server or the client
BriardOP
i didnt use the ones on the server yet
oh no i did
it was extremly easy
implementing searching for employee will be my worst nightmare
but i will enjoy it
but i will enjoy it
BriardOP
good so far :d
If you already have all the users you could just make a filter locally.
If you want the backend to respond with only the filtered users then you’ll have to see how you implement searching directly at the database level with drizzle, that I’ve never done
If you want the backend to respond with only the filtered users then you’ll have to see how you implement searching directly at the database level with drizzle, that I’ve never done
The local filter works if you’re always getting the data for all users but if you’ll paginate the data later because you’ll have a lot of users you’ll probably want the server to retrieve only the users that match the filter
@luis_llanes If you already have all the users you could just make a filter locally.
If you want the backend to respond with only the filtered users then you’ll have to see how you implement searching directly at the database level with drizzle, that I’ve never done
BriardOP
yes true and i believe server filtering is better especially when implementing with pagination
actually it has advantages and disadvantages
on serverside ; data will be updated but at the same time exhaust the server
on client side: data wont be update but wont exhaust the server
on serverside ; data will be updated but at the same time exhaust the server
on client side: data wont be update but wont exhaust the server
implementing useDebounce and enabling caching would reduce the load on the server
@Briard implementing useDebounce and enabling caching would reduce the load on the server
Yes that should be implemented either way you do the filtering on the client or the server
And you got caching resolved thanks to React Query.
And you got caching resolved thanks to React Query.
yes, of course