Skip to content

Commit bc0f77f

Browse files
committed
♻️(frontend) Separate mutations from queries for auth logic
Introduces dedicated mutations (for authentication/user operations) separating them from queries to align with best practices for data fetching and state management. Queries remain responsible for READ operations, while mutations now handle CREATE, UPDATE, and DELETE actions (for user data) improving separation of concerns. Signed-off-by: Robin Weber <[email protected]>
1 parent 1a78019 commit bc0f77f

File tree

2 files changed

+81
-0
lines changed

2 files changed

+81
-0
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export * from './useAuthQuery';
2+
export * from './useAuthMutation';
23
export * from './types';
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import { useMutation, useQueryClient } from '@tanstack/react-query';
2+
3+
import { APIError, errorCauses, fetchAPI } from '@/api';
4+
5+
import { User } from './types';
6+
import { KEY_AUTH } from './useAuthQuery';
7+
8+
// Mutations are separated from queries to allow for better separation of concerns.
9+
// Mutations are responsible for C (CREATE), U (UPDATE), and D (DELETE) in CRUD.
10+
11+
// --- Create ---
12+
function createUser(): Promise<User> {
13+
throw new Error('Not yet implemented.');
14+
}
15+
16+
// --- Update ---
17+
async function updateUser(
18+
user: { id: User['id'] } & Partial<Omit<User, 'id'>>,
19+
): Promise<User> {
20+
const response = await fetchAPI(`users/${user.id}/`, {
21+
method: 'PATCH',
22+
headers: {
23+
'Content-Type': 'application/json',
24+
},
25+
body: JSON.stringify(user),
26+
});
27+
if (!response.ok) {
28+
throw new APIError(
29+
`Failed to update user profile for user ${user.id}`,
30+
await errorCauses(response, user),
31+
);
32+
}
33+
return response.json() as Promise<User>;
34+
}
35+
36+
// --- Delete ---
37+
function deleteUser(): Promise<User> {
38+
throw new Error('Not yet implemented.');
39+
}
40+
41+
// NOTE: Consider renaming useAuthMutation to useUserMutation for clarity.
42+
export function useAuthMutation() {
43+
const queryClient = useQueryClient();
44+
45+
const createMutation = useMutation<User, APIError, User>({
46+
mutationFn: createUser,
47+
onSuccess: () => {
48+
void queryClient.invalidateQueries({ queryKey: [KEY_AUTH] });
49+
},
50+
onError: (error) => {
51+
console.error('Error creating user', error);
52+
},
53+
});
54+
55+
const updateMutation = useMutation<User, APIError, User>({
56+
mutationFn: updateUser,
57+
onSuccess: () => {
58+
void queryClient.invalidateQueries({ queryKey: [KEY_AUTH] });
59+
},
60+
onError: (error) => {
61+
console.error('Error updating user', error);
62+
},
63+
});
64+
65+
const deleteMutation = useMutation<User, APIError, User>({
66+
mutationFn: deleteUser,
67+
onSuccess: () => {
68+
void queryClient.invalidateQueries({ queryKey: [KEY_AUTH] });
69+
},
70+
onError: (error) => {
71+
console.error('Error deleting user', error);
72+
},
73+
});
74+
75+
return {
76+
create: createMutation.mutateAsync,
77+
update: updateMutation.mutateAsync,
78+
delete: deleteMutation.mutateAsync,
79+
};
80+
}

0 commit comments

Comments
 (0)