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

Unable to reset/replace state #74

Closed
laurib opened this issue Oct 30, 2019 · 8 comments
Closed

Unable to reset/replace state #74

laurib opened this issue Oct 30, 2019 · 8 comments

Comments

@laurib
Copy link

laurib commented Oct 30, 2019

Using immer and redux middlewares.

i want to replace initial state with new state, but as zustand merges with set, then it is quite impossible.

defaultState  = {
  isLoading: false,
}

replace state with redux middleware:
From immer doc:

case "loadUsers":
            // OK: we return an entirely new state
            return action.payload

This should replace state entirely but isLoading is still present. How to replace entire state ?

or if i return {} then all old values are still in place

Tried different ways. immer middleware / using immer in redux middleware for set / added immer to reducer.. But was still unable to do it

@drcmda
Copy link
Member

drcmda commented Oct 30, 2019

you should be able to set the initialState variable

const initialState = { ... }
const [useStore, api] = create(set => initialState)
api.setState(initialState)

@JeremyRH
Copy link
Contributor

@laurib Unfortunately, Zustand's set doesn't allow this right now. I guess the best option is to store all your state in a property and overwrite that property. That's kind of messy but I think a create wrapper can abstract this for you:

import create from "zustand";

function createNoMerge(stateCreator) {
  let setState;
  let getState;

  const [useStore, api] = create((set, get) => {
    setState = newState => {
      const oldState = get().state;
      const state =
        typeof newState === "function"
          ? newState(oldState)
          : newState;
      return set({ state });
    };
    getState = () => get().state;
    return {
      state: stateCreator(setState, getState)
    };
  });

  api.setState = setState;
  api.getState = getState;

  const useStoreNoMerge = (sel = s => s, ...args) => {
    const selector = () => sel(getState());
    return useStore(selector, ...args);
  };

  return [useStoreNoMerge, api];
}

const [useStore, api] = createNoMerge(() => ({
  a: 1,
  b: 2
}));

@mikaeleli
Copy link

Are there any plans to change set to support this?
Thanks in advance!

@JeremyRH
Copy link
Contributor

@MrFungusEli I would like the default behavior of set to overwrite instead of merge. That would be a breaking change though.

@drcmda
Copy link
Member

drcmda commented Nov 26, 2019

wouldnt overwrite require full reducers though? like when you just want to change a single value.

state { a: 1, b: 2, c: 3 }
set({ a: 0 }) // ---> { a: 0 } ?

that would make set(value) quite useless except for resets, since you would always need the function form: set(state => ...).

@mikaeleli
Copy link

Is there anything I can do to help? I'm wondering if this would be a good first time contribution for me :)

@drcmda
Copy link
Member

drcmda commented Nov 27, 2019

i guess making it merge or not is a small change, but the repercussions of how it effects all purposes and use cases isn't clear to me. from my experience, resetting a set of objects is rare, i solve it via intialState. plain deletion i haven't ran into. merging, or set(value) instead of set(function) on the other hand is something i do often - i realize this could just be me.

if the change would make set(value) obsolete because it would now delete all data except the one prop that it gets, and set(function) would always have to spread, then i think it needs a bigger discussion involving more users. we should also look into what made react go for setState and useState as a merging op.

alternatives would be middleware or set(arg, merge=true)

@mikaeleli
Copy link

you should be able to set the initialState variable

const initialState = { ... }
const [useStore, api] = create(set => initialState)
api.setState(initialState)

I must have missed this, this works absolutely fine for me. Thanks!

@JeremyRH JeremyRH closed this as completed May 1, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants