T
TanStack2y ago
dependent-tan

Is it possible to extract useMutation from the component/page file in Next.js?

I would like to define all the useMutations and useQueries (like updateUser, deleteUser, createUser, getUsers, getUser) together inside a UserAPI.ts file. I found the following example where they have extracted them from the main component: https://v2.mantine-react-table.com/docs/examples/editing-crud
Editing CRUD Mantine React Table Example
Learn how to use editing and all the CRUD functionality of Mantine React Table
7 Replies
dependent-tan
dependent-tanOP2y ago
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
This is the error I am getting.
evident-indigo
evident-indigo2y ago
Did you read the error message?
dependent-tan
dependent-tanOP2y ago
Yes, of course. But in the example I linked in the first message it looks like they have defined the useMutations like useCreateUser and useUpdateUser outside of the main component if I am not mistaken. So I was wondering how they did it? Or if it is outdated?
evident-indigo
evident-indigo2y ago
And what does your code look like? Is it really the same?
dependent-tan
dependent-tanOP2y ago
This is the code I have in my EmployeeAPI.ts:
export const useCreateEmployee = (team: number) => {
const queryClient = useQueryClient();

return useMutation({

mutationFn: (newEmployee: Employee) => addEmployee(newEmployee),
onMutate: async (newEmployee: Employee) => {
const locationId = newEmployee.location ? newEmployee.location : [team];
console.log('Hi ', locationId);

await queryClient.cancelQueries({queryKey: ['employees']});
const previousEmployees = queryClient.getQueryData(['employees', team]);
// const previousEmployees: [Employee[]] = [[]];
// locationId.map((location: number) => {
// previousEmployees.push(queryClient.getQueryData(['employees', location]));
// })
// Optimistically update to the new value
console.log('Optimistically updating');
queryClient.setQueryData(['employees', team], (old: Employee[]) => [...old, newEmployee]);

return {previousEmployees};
},
// If the mutation fails,
// use the context returned from onMutate to roll back
// onError: (err, variables, context) => {
// if (context?.previousEmployees) {
// queryClient.setQueryData(['employees', '1'], context.previousEmployees);
// }
// },
// Always refetch after error or success:
// onSettled: () => {
// console.log('here');
// queryClient.invalidateQueries({queryKey: ['employees', '1']});
// },

});
}
export const useCreateEmployee = (team: number) => {
const queryClient = useQueryClient();

return useMutation({

mutationFn: (newEmployee: Employee) => addEmployee(newEmployee),
onMutate: async (newEmployee: Employee) => {
const locationId = newEmployee.location ? newEmployee.location : [team];
console.log('Hi ', locationId);

await queryClient.cancelQueries({queryKey: ['employees']});
const previousEmployees = queryClient.getQueryData(['employees', team]);
// const previousEmployees: [Employee[]] = [[]];
// locationId.map((location: number) => {
// previousEmployees.push(queryClient.getQueryData(['employees', location]));
// })
// Optimistically update to the new value
console.log('Optimistically updating');
queryClient.setQueryData(['employees', team], (old: Employee[]) => [...old, newEmployee]);

return {previousEmployees};
},
// If the mutation fails,
// use the context returned from onMutate to roll back
// onError: (err, variables, context) => {
// if (context?.previousEmployees) {
// queryClient.setQueryData(['employees', '1'], context.previousEmployees);
// }
// },
// Always refetch after error or success:
// onSettled: () => {
// console.log('here');
// queryClient.invalidateQueries({queryKey: ['employees', '1']});
// },

});
}
This is how I call the function in my React Table using a modal:
<form onSubmit={form.onSubmit((values) => {
useCreateEmployee(team).mutate(createEmployee(values));
close();
})}>
<form onSubmit={form.onSubmit((values) => {
useCreateEmployee(team).mutate(createEmployee(values));
close();
})}>
evident-indigo
evident-indigo2y ago
This is not allowed. You are calling a hook in a callback Now read the error message again
dependent-tan
dependent-tanOP2y ago
Okay, I got it working now, thank you for your help!!

Did you find this page helpful?