본문으로 건너뛰기

뮤테이션

import { Switch, Match, Show } from 'solid-js'

function App() {
const mutation = useMutation(() => ({
mutationFn: (newTodo) => {
return axios.post('/todos', newTodo)
},
}))

return (
<div>
<Switch>
<Match when={mutation.isPending}>Adding todo...</Match>
<Match when={true}>
<Show when={mutation.isError}>
<div>An error occurred: {mutation.error.message}</div>
</Show>

<Show when={mutation.isSuccess}>
<div>Todo added!</div>
</Show>

<button
onClick={() => {
mutation.mutate({ id: new Date(), title: 'Do Laundry' })
}}
>
Create Todo
</button>
</Match>
</Switch>
</div>
)
}
const CreateTodo = () => {
const mutation = useMutation(() => ({
mutationFn: (formData) => {
return fetch('/api', formData)
},
}))
const onSubmit = (event) => {
event.preventDefault()
mutation.mutate(new FormData(event.target))
}

return <form onSubmit={onSubmit}>...</form>
}
import { createSignal, Show } from 'solid-js'

const CreateTodo = () => {
const [title, setTitle] = createSignal('')
const mutation = useMutation(() => ({ mutationFn: createTodo }))

const onCreateTodo = (e) => {
e.preventDefault()
mutation.mutate({ title: title() })
}

return (
<form onSubmit={onCreateTodo}>
<Show when={mutation.error}>
<h5 onClick={() => mutation.reset()}>{mutation.error}</h5>
</Show>
<input
type="text"
value={title()}
onInput={(e) => setTitle(e.currentTarget.value)}
/>
<br />
<button type="submit">Create Todo</button>
</form>
)
}
useMutation(() => ({
mutationFn: addTodo,
onMutate: (variables, context) => {
// A mutation is about to happen!

// Optionally return a result containing data to use when for example rolling back
return { id: 1 }
},
onError: (error, variables, onMutateResult, context) => {
// An error happened!
console.log(`rolling back optimistic update with id ${onMutateResult.id}`)
},
onSuccess: (data, variables, onMutateResult, context) => {
// Boom baby!
},
onSettled: (data, error, variables, onMutateResult, context) => {
// Error or success... doesn't matter!
},
}))
useMutation(() => ({
mutationFn: addTodo,
onSuccess: async () => {
console.log("I'm first!")
},
onSettled: async () => {
console.log("I'm second!")
},
}))
useMutation(() => ({
mutationFn: addTodo,
onSuccess: (data, variables, onMutateResult, context) => {
// I will fire first
},
onError: (error, variables, onMutateResult, context) => {
// I will fire first
},
onSettled: (data, error, variables, onMutateResult, context) => {
// I will fire first
},
}))

mutate(todo, {
onSuccess: (data, variables, onMutateResult, context) => {
// I will fire second!
},
onError: (error, variables, onMutateResult, context) => {
// I will fire second!
},
onSettled: (data, error, variables, onMutateResult, context) => {
// I will fire second!
},
})
useMutation(() => ({
mutationFn: addTodo,
onSuccess: (data, variables, onMutateResult, context) => {
// Will be called 3 times
},
}))

const todos = ['Todo 1', 'Todo 2', 'Todo 3']
todos.forEach((todo) => {
mutate(todo, {
onSuccess: (data, variables, onMutateResult, context) => {
// Will execute only once, for the last mutation (Todo 3),
// regardless which mutation resolves first
},
})
})
const mutation = useMutation(() => ({ mutationFn: addTodo }))

try {
const todo = await mutation.mutateAsync(todo)
console.log(todo)
} catch (error) {
console.error(error)
} finally {
console.log('done')
}
const mutation = useMutation(() => ({
mutationFn: addTodo,
retry: 3,
}))
const queryClient = new QueryClient()

// Define the "addTodo" mutation
queryClient.setMutationDefaults(['addTodo'], {
mutationFn: addTodo,
onMutate: async (variables, context) => {
// Cancel current queries for the todos list
await context.client.cancelQueries({ queryKey: ['todos'] })

// Create optimistic todo
const optimisticTodo = { id: uuid(), title: variables.title }

// Add optimistic todo to todos list
context.client.setQueryData(['todos'], (old) => [...old, optimisticTodo])

// Return a result with the optimistic todo
return { optimisticTodo }
},
onSuccess: (result, variables, onMutateResult, context) => {
// Replace optimistic todo in the todos list with the result
context.client.setQueryData(['todos'], (old) =>
old.map((todo) =>
todo.id === onMutateResult.optimisticTodo.id ? result : todo,
),
)
},
onError: (error, variables, onMutateResult, context) => {
// Remove optimistic todo from the todos list
context.client.setQueryData(['todos'], (old) =>
old.filter((todo) => todo.id !== onMutateResult.optimisticTodo.id),
)
},
retry: 3,
})

// Start mutation in some component:
const mutation = useMutation(() => ({ mutationKey: ['addTodo'] }))
mutation.mutate({ title: 'title' })

// If the mutation has been paused because the device is for example offline,
// Then the paused mutation can be dehydrated when the application quits:
const state = dehydrate(queryClient)

// The mutation can then be hydrated again when the application is started:
hydrate(queryClient, state)

// Resume the paused mutations:
queryClient.resumePausedMutations()

오프라인 뮤테이션 영구 저장하기

persistQueryClient 플러그인을 사용하여 오프라인 뮤테이션을 영구 저장하는 경우, 기본 뮤테이션 함수를 제공하지 않으면 페이지를 다시 로드할 때 뮤테이션을 재개할 수 없습니다.

const mutation = useMutation(() => ({
mutationFn: addTodo,
scope: {
id: 'todo',
},
}))

추가 자료

뮤테이션에 관한 자세한 내용은 TanStack Query의 뮤테이션을 깊이 다룬 TkDodo의 글을 참조하세요.