developit / unistore

🌶 350b / 650b state container with component actions for Preact & React
https://npm.im/unistore
2.86k stars 139 forks source link

Stale state seems to be written to store when using a recursive object structure #190

Closed chrisandrewca closed 4 years ago

chrisandrewca commented 4 years ago

Hello! Thanks for sharing unistore. Its a nice way to break into the redux-like world.

I'm having a problem where new state is being rendered and logs say its written to the store, yet when checking local storage mostly old state is there.

I have an object like

{
  customization: {
    ...fields,
    options: [{
      id,
      fields,
      menuState,
      options: [{...}],
      parent
    }]
  }
}

When I update options. I copy the array, copy each element, and copy its children, and so on. The code looks like:

const toJsonable = (optionTree) => {

  const { items } = optionTree;

  const options = [];
  for (const ref of items) {

    const option = { ...ref };

    /* mutations on copy */

    if (option.options.length) {
      option.options = toJsonable({ items: option.options });
    }

    /* deletes */
    options.push(option);
  }

  return options;
};

I'm using unissist to persist to local storage. When I fire off the work with useEffect the component renders the updated state and the logs inside subscribe read that its been persisted to local storage. Then when I check local storage the old state is there.

I read the equality comparison in unistore and when logging here mapped holds the correct state...

let update = () => {
  let mapped = mapStateToProps(store ? store.getState() : {}, props);
  for (let i in mapped) if (mapped[i]!==state[i]) {
    state = mapped;
    return this.setState({});
  }
  for (let i in state) if (!(i in mapped)) {
    state = mapped;
    return this.setState({});
  }
};

When I don't use the nested options array; and submit a flat array [...options] the new state is found in storage. Then when using a nested options array [{option: { options: [...] }] the old state is found.

It really sounds like a copy issue.... but with all the logs saying all good all the way down, I'm not sure what to do. Do you think I'm missing a copy? Or maybe some type of async issue? I tried indexdb and had even worse results...

chrisandrewca commented 4 years ago

Figured it out! Of course it was nothing to do with unistore :D

Issues I had:

Thanks again for the lib.

Cheers, Chris