Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

State does not properly update components with multilevel object state #52

Closed
ghost opened this issue Nov 22, 2019 · 5 comments
Closed
Labels
question Further information is requested

Comments

@ghost
Copy link

ghost commented Nov 22, 2019

  • Having deep objects causes state to not update properly sometimes being null in the components.
  • After reading the documentation I noticed there is a line about using immerjs for setState. How does one replace the built in setState with immerjs?
@albertogasparin
Copy link
Collaborator

Thanks for reporting the issue. Would you mind reproducing the bug in codesandbox.io, so it is much easier for us to understand what is happening?

On replacing the default setState implementation with immer, that could be done by overriding the default mutator:

// somewhere in your top/config import
import { defaults } from 'react-sweet-state'
import { produce } from 'immer';

defaults.mutator = (...args) => produce(...args);

The you call setState with a function instead of passing an object:

const actions = {
  increment: () => ({ setState }) => {
    setState(draft => {
      draft.count += 1;
    });
  },
};

@albertogasparin albertogasparin added the question Further information is requested label Nov 23, 2019
@ghost
Copy link
Author

ghost commented Nov 23, 2019

So the issue happened when using setState and only returning a partial state. This was fixed when using immerjs to return the entire state. However I was unable to use your suggested mutator because the TypeScript check fails. I was able to do:

const actions = {
  increment: () => ({ getState, setState }) => {
    const newState = produce(getState(), draft => {
      draft.count += 1;
    });
    setState(newState);
  },
};

@albertogasparin
Copy link
Collaborator

Yeah, not sure how you can make TS happy as the signature of setState is different.
Wonder if you can override the type SetState of the library, as by doing so TS should pick up the different setState implementation

@ghost
Copy link
Author

ghost commented Nov 25, 2019

The typing issue seems to lie in index.d.ts with:

const defaults: {
  devtools: boolean;
  middlewares: any;
  mutator: <TState>(
    prevState: TState,
    partialState: Partial<TState> // I believe this second argument could be more flexible, but haven't been able to get the typing right yet
  ) => TState;
};

I tried with no luck:

partialState: Partial<TState> | (<TState>(draftState: TState) => TState)

@albertogasparin
Copy link
Collaborator

I think I've found a solution to properly allow custom mutator types to be correct. Would you mind checking #53, try following the docs that I added and see if that works?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

1 participant