mutation()
mutation() is query()'s write
half: creating, updating, deleting.
You call mutate(input) to run
it, and it tracks the loading and error states for you. No import.
<script>
const createPost = mutation('/api/posts', { method: 'POST' })
function create() {
createPost.mutate({ title: 'New Post' })
}
</script>
<button onclick="create()" disabled={createPost.loading}>
{createPost.loading ? 'Creating...' : 'Create Post'}
</button>
method defaults to POST. The other accepted values
are PUT, PATCH and DELETE.
What you get back
| Property | Type | What it is |
|---|---|---|
mutate(input) |
(input) => Promise |
Run it |
data |
T | undefined |
The last successful result |
loading |
boolean |
In progress |
error |
Error | undefined |
It failed |
reset() |
() => void |
Clear data and error |
Refreshing queries afterwards
List invalidates and those queries refetch as soon as the
mutation succeeds:
<script>
const posts = query('posts', '/api/posts')
const deletePost = mutation('/api/posts', {
method: 'DELETE',
invalidates: ['posts'] // refetches the posts query on success
})
</script>
{posts.data && posts.data.map(post => (
<div key={post.id}>
{post.title}
<button onclick={() => deletePost.mutate({ id: post.id })}>Delete</button>
</div>
))}
invalidates matches the whole cache key,
which is the query's name plus its serialised params. So
invalidates: ['posts'] hits
query('posts', '/api/posts') and nothing else - a query with
params has a different key. Name the queries you intend to
invalidate, and keep them param-free.
Callbacks
onSuccess and onError run after the request settles:
<script>
const updateProfile = mutation('/api/profile', {
method: 'PUT',
invalidates: ['profile'],
onSuccess: () => ui.toast.show('Profile saved', { type: 'success' }),
onError: (err) => ui.toast.show(err.message, { type: 'error' })
})
</script>
Sending it yourself
Pass a function instead of a URL for full control of the request:
<script>
const customMutation = mutation(async (data) => {
const res = await fetch('/api/custom', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
})
if (!res.ok) throw new Error('Failed')
return res.json()
}, { invalidates: ['custom'] })
</script>
Want instant feedback? Update your local state the moment
the button is clicked, then let invalidates reconcile it with
the server.