5. Query: useMutation
Что такое мутации?
Заголовок раздела «Что такое мутации?»Мутации — это операции, которые изменяют данные на сервере: создание, обновление, удаление.
В отличие от useQuery (который работает автоматически), useMutation выполняется вручную.
Хук useMutation
Заголовок раздела «Хук useMutation»const mutation = useMutation({ mutationFn: (newUser: NewUser) => createUser(newUser), onSuccess: (data) => { console.log('Пользователь создан:', data) }, onError: (error) => { console.error('Ошибка:', error.message) }, onSettled: () => { // Выполняется всегда: и при успехе, и при ошибке queryClient.invalidateQueries({ queryKey: ['users'] }) },})mutate vs mutateAsync
Заголовок раздела «mutate vs mutateAsync»useMutation возвращает два метода для вызова мутации:
mutate — синхронный вызов, не возвращает Promise:
mutateAsync — асинхронный вызов, возвращает Promise:
try { console.log('ID нового пользователя:', user.id)} catch (error) { console.error(error)}Используйте mutateAsync, когда нужно дождаться результата для следующих действий.
Коллбэки жизненного цикла
Заголовок раздела «Коллбэки жизненного цикла»| Коллбэк | Когда вызывается | Аргументы |
|---|---|---|
onMutate | До выполнения запроса | variables |
onSuccess | При успехе | data, variables, context |
onError | При ошибке | error, variables, context |
onSettled | Всегда после завершения | data?, error?, variables, context |
const mutation = useMutation({ mutationFn: updateUser, onMutate: (variables) => { // Оптимистичное обновление UI (до ответа сервера) return { previousData: queryClient.getQueryData(['users']) } }, onSuccess: (data, variables, context) => { // data — ответ сервера // variables — то, что передали в mutate() // context — то, что вернул onMutate }, onError: (error, variables, context) => { // Откат изменений при ошибке queryClient.setQueryData(['users'], context.previousData) }, onSettled: () => { queryClient.invalidateQueries({ queryKey: ['users'] }) },})Статусы мутации
Заголовок раздела «Статусы мутации»const { mutate, mutateAsync, isPending, // true пока запрос выполняется isSuccess, // true после успешного выполнения isError, // true при ошибке isIdle, // true до первого вызова data, // данные ответа при успехе error, // объект ошибки reset, // сброс состояния мутации} = useMutation({ mutationFn })Инвалидация после мутации
Заголовок раздела «Инвалидация после мутации»Лучшая практика — инвалидировать связанные запросы после мутации:
const queryClient = useQueryClient()
const addUser = useMutation({ mutationFn: createUser, onSuccess: () => { // Перезагрузить список пользователей queryClient.invalidateQueries({ queryKey: ['users'] }) },})