Notes on SWR

Exploring the use case for SWR and if i can use it as a replacement for Redux

tl;dr:

  • Application state !== remote data from a server. Remote data should be in a cache, application state should be in state (React Context is fine)
  • Once you accept the above, you'll stop using Redux to store everything that comes back from the server (i.e. remote data)
  • Because you stopped making a client side copy of the server side data, you no longer have to worry about your state becoming stale
  • You can access the data from the SWR cache the same way you can access data from a store. Because SWR cahce is a global state object. (fyi, server side data is also called server cache)
  • You can use Axios with SWR, it will not force you to give it up. As a matter of fact, you can use any library you want for making HTTP requests
  • With SWR, you no longer have to worry about manually updating error, loading, success state and write reducers for them. SWR gives you these out of the box
  • SWR is only meant for reading data (GET), for other CRUD operations, you can handle them outside SWR
  • You can use a mutate function to update SWR cache
  • You still need global app state, (be it Redux or React Context), we just don't store remote data in it.

Basic mentality behind SWR is that remote data is not state, it belongs in a cache.

"Remote data is read-only. It doesn’t belong in the same location as our UI state."

If you don't keep server side data in state (making a client side copy), it won't become stale.

Server cacheLocal (UI) state
State that's actually stored on the server and we store in the client for quick-accessState that's only useful in the UI for controlling the interactive parts of our app
Conversations, User profiles, Blog postsIs the modal open? Is the box checked?

Bandwidth concerns

SWR is great if we're using GraphQL, because then you are not making multiple HTTP calls every time you need data, so all the revalidating is less expensive. But if you're using plain old REST APIs with lots of HTTP requests, i wonder how much bandwidth it'll consume and if we can afford making so many calls so frequently?

Deduping

The key you pass to useSWRhelps SWR identify our request. If the key is the same for multiple requests, only one API call will be made and all components will get the results.

all components fetching the same data are updated when the data changes.

Transitioning an existing app that uses Redux

You can use onSuccess callback on useSWR to dispatch redux actions..

Persisting SWR cache?

SWR is using an in-memory Map for the cache (both React and React Native). It does not save cache with AsyncStorage or MemoryStore in React Native. Right now it clears everything on hard refresh. According to folks from Vercel, LocalStorage is IO heavy and slowed down rendering. ANd IndexedDb is async, which means SWR can not return data from cache synchronously.

With Redux, persisting is simple, you use redux-persist. A similar ready made solution for SWR doesn't exist yet. There is swr-sync-storage from a guy who used to work at Vercel, and it'll sync SWR cache with localStorage or sessionStorage to get offline cache. But it's for web and not React Native.

There is this solution that derindutz is using in production. You can switch out localforage for whichever caching mechanism you want.

tl;d: you can do it, but it'll save the entire cache and is not performant as disk IO is heavy.

We did an extensive experiment with IndexedDB and it was awful from a product perspective. Disks are slow and customers tend to want strong reads from the kind of apps and dashboards that you use SWR for.

- Vercel CEO

Conclusion

As of now, i can't use SWR in React Native apps because a solution to persist it by synching it to AsyncStorage (HDD/Disk) doesn't exist (yet). So the in-memory (RAM) cache will be gone every time i exit the app. If i exit the app and the next time i open it and i'm offline, the cache will be blank and i won't have any data to make the app usable offline.

I can use it in React on the web, and i can persist it to Web localStorage or sessionStorage.

My ideal scenario is using SWR on the web with GraphQL API and persisting it to web storage for offline access.

Links

Please note that this site and the posts on it are, and will always be, a work in progress. If i waited for perfection, i’d never get anything done.