polemius / recoil-persist

Package for recoil state manager to persist and rehydrate store

Home Page:https://polemius.dev/recoil-persist/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Doesn't seem to handle atomFamily

lmartins opened this issue · comments

I've noticed that the library doesn't seem to be able to restore state when the item being restored belongs to an atomFamily, is there a way around it?

@lmartins Thank you for reporting the issue. Sorry for this delay. I just released new 0.7.0 version and this issue should be fixed.

@polemius sweet! I now see the values showing up on the Local Storage inspector, but they don't seem to hydrate on reload. I'll try figure out where it may be failing, and comment back here.

@lmartins Thank you for your feedback. Could you try to make something like this:

  <RecoilRoot
    initializeState={({ set }) => {
      set({key: atomName}, value)
      // updateState({ set });
    }}
  >
    <RecoilPersist />
    <App />
  </RecoilRoot>

Change atomName to name of your atom and value to some value.
And please check if you have any errors in console.

@polemius that gives out a an error and the app crashes:

Error: Missing definition for RecoilValue: "params => {
    var _stableStringify;

    const cachedAtom = atomCache.get(params);

    if (cachedAtom != null) {
      return cachedAtom;
    }

    const newAtom = Recoil_atom({ ...options,
      key: `${options.key}__${(_stableStringify = Recoil_stableStringify(params)) !== null && _stableStringify !== void 0 ? _stableStringify : 'void'}`,
      default: atomFamilyDefault(params),
      effects_UNSTABLE: typeof options.effects_UNSTABLE === 'function' ? options.effects_UNSTABLE(params) : options.effects_UNSTABLE // prettier-ignore
      // @fb-only: scopeRules_APPEND_ONLY_READ_THE_DOCS: mapScopeRules(
      // @fb-only: options.scopeRules_APPEND_ONLY_READ_THE_DOCS,
      // @fb-only: params,
      // @fb-only: )

    });
    atomCache = atomCache.set(params, newAtom);
    return newAtom;
  }""

Interestingly, after reverting the test above and clearing my Local Storage, these atomFamily atoms are now saving as regular atoms, not families so maybe there's something else going on here.

For the atomFamily declaration:

export const frameSwatches = atomFamily({
  key: 'frameSwatch',
  default: null,
  persistence_UNSTABLE: { type: true },
});

Which I then subscribe to on the component:

const { index, colors } = props;
const [swatch, setSwatch] = useRecoilState(frameSwatches(index));

What is saved to localStorage is:

frameSwatch: {id: "color1", label: "Mustard", hex: "#9e978e", pantone: "Pantone name"}

while before it would be something like:

frameSwatch__1: {id: "color1", label: "Mustard", hex: "#9e978e", pantone: "Pantone name"},
frameSwatch__2: {id: "color4", label: "Color Name", hex: "#9e978e", pantone: "Pantone name"}

I'm using Recoil 0.0.13 btw, I've updated both Recoil and this library yesterday after your comment.

@lmartins This error Error: Missing definition for RecoilValue: means that recoil couldn't find the atom with some name.

Try this code:

 <RecoilRoot
    initializeState={({ set }) => {
      set({key: 'frameSwatch'}, {id: 'test'})
      // updateState({ set });
    }}
  >
    <RecoilPersist />
    <App />
  </RecoilRoot>

this on start should set for atom frameSwatch value {id: 'test'}.

Are you using lazy loading components?

@polemius yes, I'm using Webpack's dynamic imports. Could that be the reason?

Running a build rather than the dev environment, it does save state like before, but as I was mentioning before it is not saving as an indexed atom but storing as a normal one:

What is saved to localStorage is:

frameSwatch: {id: "color1", label: "Mustard", hex: "#9e978e", pantone: "Pantone name"}

instead of:

frameSwatch__1: {id: "color1", label: "Mustard", hex: "#9e978e", pantone: "Pantone name"},
frameSwatch__2: {id: "color4", label: "Color Name", hex: "#9e978e", pantone: "Pantone name"}

If you don't feel this to be an issue with the library please feel free to close this. I'll keep looking to what the cause may be. With the persistence API changing sometime in the future, maybe this won't be a problem anymore.

@polemius I was taking a look at your commits to bring this functionality, and while tests may be passing I think the tests are also not set to capture the issue I'm seeing.

For you to see the issue, you need to have multiple atoms in the same family and try to persist each instance on its own. What is happening is that each instance saves on top of the previous one, effectively behaving like a normal atom.

Your tests won't capture this as you are testing for a single instance of the family with a key of key. If you create a new counter with for example key2 you'll notice that the last counter of that group edited, is what will be persisted.

On 3852768#diff-168726dbe96b3ce427e7fedce31bb0bcR26 you are splitting the atomName by __ but as I mentioned above that is not how these atoms are currently being written to Local Storage.

Looking at the event that is reaching https://github.com/polemius/recoil-persist/blob/master/index.js#L24, I've noticed something weight about the modifiedAtoms value:

image

Notice the double quotes in what I believe should be riderinfo2__height.

Aside from that, even by changing the persistState to something like this:

function persistState(event) {
    console.log('Event:', event);
    const toStore = {};
    event.atomValues.forEach((value, atomName) => {
      const name = atomName.split('__')[0];
      if (paths.length === 0 || paths.includes(name)) {
        toStore[atomName.replace(/['"]+/g, '')] = value;
      }
    });
    try {
      storage.setItem(key, JSON.stringify(toStore));
    } catch (e) {}
  }

We still bump into a problem when trying to restore from localStorage, and that may be related to the note here:
https://recoiljs.org/docs/guides/persistence#restoring-state

The set call in https://github.com/polemius/recoil-persist/blob/master/index.js#L50 will need logic to lookup the adequate atom to update, being that a simple atom or an atom family entry.

@lmartins Thank you for describing this issues! 👍 Are you interesting to send PR with fix or only with test that will show the problem?

@lmartins Please check out the new 2.0.0 release 🚀

@rhys-saldanha made a great job and fix this issue.

Please let me know if everything is working as expected.

@polemius Just had chance to play with the new version and it does work beautifully! Thank you both for the help.