9

I have some state with React recoil, but whenever the page is manually refreshed, the recoil state is reset.

Is this normal behaviour, because i know other state management libraries like flux and react-redux will do this.

Is it best practise to save it into localStorage to actually have it persisted in the browser (because localStorage is also a synchronous api, so that could definitely also cause some issues.)

Even though it is a fairly new library, is there some way to persist state even on manual page refreshes?

Kristoffer Tølbøll
  • 3,157
  • 5
  • 34
  • 69
  • 3
    Flux and Redux doesn't do persist out of box. If you want to store your state into the browser you can either use localStorage / sessionStorage or IndexedDB (async). – Alexandre Nicolas Aug 11 '20 at 11:46

3 Answers3

15

I have some state with React recoil, but whenever the page is manually refreshed, the recoil state is reset.

Yes, it's normal behavior.

Is this normal behavior because I know other state management libraries like flux and react-redux will do this.

Yes, only a subset of the state management libraries persists the data themselves. It's more common to find external libraries that do that or custom solutions.

Is it best practice to save it into localStorage to actually have it persisted in the browser (because localStorage is also asynchronous API, so that could definitely also cause some issues.)

It depends on your needs:

  • do you want to offer a full offline experience? Go for it
  • are you concerned by the performance implications in case of big amount of data? You could consider indexedDB
  • are you just trying to persist some auth tokens? Probably sessionStorage could be the right solution
  • does the server need to know the stored data? You could opt for cookies

Let's say that without knowing your use case it's hard to suggest something

Even though it is a fairly new library, is there some way to persist state even on manual page refreshes?

Yes, with useRecoilTransactionObserver_UNSTABLE you could get notified of every Recoil change and persisting the data. Then, with RecoilRoot' initializeState you could restore it. As you said, the library is new and the APIs could change rapidly in the next months

NoriSte
  • 3,589
  • 1
  • 19
  • 18
12

You could use recoil-persist library to persist state to localStorage.

Here how you could use it:

import { recoilPersist } from 'recoil-persist'

const { persistAtom } = recoilPersist()

const counterState = atom({
  key: 'count',
  default: 0,
  effects_UNSTABLE: [persistAtom],
})
Ivan
  • 2,463
  • 1
  • 20
  • 28
6

This works nicely, from the docs here.

Any change to the order state gets written to localStorage, and the value from localStorage is read into the order state on refresh.

// define this function somewhere
const localStorageEffect = key => ({setSelf, onSet}) => {
  const savedValue = localStorage.getItem(key)
  if (savedValue != null) {
    setSelf(JSON.parse(savedValue))
  }
  onSet(newValue => {
    localStorage.setItem(key, JSON.stringify(newValue))
  })
}

// this is an example state atom
export const orderState = atom({
  key: 'orderState',
  default: {
    store: {}, // { id, name, phone, email, address }
    items: {}, // { [itemId]: { id, name, sizeTable, quantity, size } }
    contact: { deliveryOption: 'ship' }, // { name, email, phone, address, city, state, zipcode, promotions, deliveryOption }
  },
  // add these lines to your state atom, 
  // with the localStorage key you want to use
  effects_UNSTABLE: [
    localStorageEffect('order'),
  ],
})
Brian Burns
  • 20,575
  • 8
  • 83
  • 77
  • 1
    This is nice thank you. My only concern is `localStorage`'s `synchrnous` behaviour. Would it not be incompatible with Recoil? – Kristoffer Tølbøll Dec 04 '20 at 15:44
  • 1
    And why not store empty values inside your default state? `store: {id: 0, name: "" ...}` – Kristoffer Tølbøll Dec 04 '20 at 15:45
  • This worked really great. I was having trouble upgrading Recoil, so, using yarn, uninstalled and reinstalled. You really need to be up to date to use this at the moment. The side effects are very new. – Jake Dec 22 '20 at 12:20