Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Sergio Daniel Xalambrí
Sergio Daniel Xalambrí

Posted on • Originally published atsergiodxa.com

     

Using Immer with SWR to mutate data

SWR comes with a nice function calledmutate that let you change the cached data for a given key, it comes with multiple different options but one of the nicest one is to pass a function, get the current data and update it, from anywhere.

import{mutate}from"swr"mutate("/api/me",user=>({...user,name:"Sergio"}))
Enter fullscreen modeExit fullscreen mode

This function update the name of the user cached as/api/me, and if there is a component subscribed to that cache key it will trigger a revalidation, this is however something we can disable passing afalse as third argument.

If you see the example above we used restructuring to copy theuser object, this is required because SWR uses object reference to avoid unnecessary re-renders.

Enter Immer, this small lib let you mutate an object while performing an immutable change, let's see the example updated

import{mutate}from"swr"importproducefrom"immer'mutate("/api/me", produce(user => {  user.name ="Sergio"}))
Enter fullscreen modeExit fullscreen mode

Thisproduce function will receive a callback and it will execute it passing a "draft" copy of the object, in this draft we could mutate the object however we want, then produce will return a new function that receives the original object to mutate, it run our callback, and generate a new object with our changes applied, lastly it will return the new updated object.

Looks like a lot of work, and it is, however for the user of Immer it's only a few lines as we saw above, what will happen combined withmutate is that the returned function will be passed tomutate as we did before and it will receive the cached value, then it will return the updated value and it will update the cache, triggering a re-render of any component subscribed to that cache key.

And this is great because it allow use to implement Optimistic UI easier, let's see an example

importReactfrom'react'importuseSWR,{mutate}from'swr'importproducefrom"immer"asyncfunctionfetcher(...args){constres=awaitfetch(...args)returnawaitres.json()}exportdefault()=>{const[text,setText]=React.useState('');const{data}=useSWR('/api/data',fetcher)asyncfunctionhandleSubmit(event){event.preventDefault()// in this mutate call we will optimistically update the UImutate("/api/data",produce(draftData=>{draftData.push(text)// here we push the new text}),false)// we don't trigger a revalidation// in this mutate call, we will POST the API and update the UI// if the update fails it will rollback the optimistic changeawaitmutate('/api/data',awaitfetch('/api/data',{method:'POST',body:JSON.stringify({text})}))setText('')// after the update we clear the input}return<div><formonSubmit={handleSubmit}><inputtype="text"onChange={event=>setText(event.target.value)}value={text}/><button>Create</button></form><ul>{data?data.map(datum=><likey={datum}>{datum}</li>) : 'loading...'}</ul></div>}
Enter fullscreen modeExit fullscreen mode

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

  • Location
    Lima, Perú
  • Work
    Web Developer at Daffy.org
  • Joined

More fromSergio Daniel Xalambrí

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp