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

Zustand testing throws an error "TypeError: store.getState is not a function" #905

Closed
Boniqx opened this issue Apr 11, 2022 · 12 comments · Fixed by #1739
Closed

Zustand testing throws an error "TypeError: store.getState is not a function" #905

Boniqx opened this issue Apr 11, 2022 · 12 comments · Fixed by #1739

Comments

@Boniqx
Copy link

Boniqx commented Apr 11, 2022

In the documentation it states that adding this in JEST would enable testing for ZUSTAND state.

const create = createState => {
  const store = actualCreate(createState);
  const initialState = store.getState();
  storeResetFns.add(() => store.setState(initialState, true));
  return store;
};

But it seems to throw an error "TypeError: store.getState is not a function"

I am using typescript not sure if this causes some issues. Also, it is not well documented on how to use this test in jest. Just want to have values on my states so that they can be used on my componentes during rendering of test components.

@dai-shi
Copy link
Member

dai-shi commented Apr 11, 2022

Is it possible to reproduce it with codesandbox?

Hope someone can help this. Also, there are some open issues for testing that needs help.

@Boniqx
Copy link
Author

Boniqx commented Apr 12, 2022

Sorry Not really familiar how to create components and jest test in sandbox that is why I can't reproduce it. It looks like a typescript issue. Similar issues has been submitted in zustand. https://stackoverflow.com/questions/68896812/using-a-zustand-function-mock-with-jest-results-in-typeerror-create-is-not-a

@dai-shi
Copy link
Member

dai-shi commented Apr 12, 2022

The SO one's error is TypeError: create is not a function. It's a different one.

TypeError: store.getState is not a function seems a JS error, not TS.

@Boniqx
Copy link
Author

Boniqx commented Apr 12, 2022

Ohh nevermind I got it:

To do this you should use the actual store of your app


    const initialStoreState = useStore.getState()
     
     beforeEach(() => {
        useStore.setState(initialStoreState, true)
      })

    useStore.setState({ me: memberMockData, isAdmin: true })

@dai-shi
Copy link
Member

dai-shi commented Apr 12, 2022

Can close now??

@dai-shi dai-shi closed this as completed Apr 15, 2022
@grigoll
Copy link

grigoll commented Mar 31, 2023

I came across the same issue. I am using TypeScript and followed the setup guide.

Turns out the error is caused by currying the create function:
The difference when using TypeScript is that instead of writing create(...), you have to write create<T>()(...)

Hence, when mocking the create you need to make it a curried as well so that it matches your usage.

               👇
const create = () => <S>(createState: StateCreator<S>) => {
  const store = actualCreate(createState);
  const initialState = store.getState();
  storeResetFns.add(() => store.setState(initialState, true));
  return store;
};

@dai-shi it would be great to update the test guide. I've been banging my head for hours before I discovered the cause.

@dai-shi
Copy link
Member

dai-shi commented Mar 31, 2023

Can you open a PR?
Someone should be able to review.
cc: @dbritto-dev @sewera @chrisk-7777

@dbritto-dev
Copy link
Collaborator

@dai-shi sure I can take care of that

@FancyVase
Copy link

Just a heads up, the currying fix on the mock create works for a "standard" create call, but errors if you're using the immer middleware with the same "TypeError: store.getState is not a function".

A little hacky, but to support both types of create calls, I added a wrapper that returns another function if no state is passed in (similar to what Zustand does internally):

export const create = <S>(createState: StateCreator<S>) => {
  return typeof createState === 'function'
      ? createInternalFn(createState)
      : createInternalFn;
};

const createInternalFn = <S>(createState: StateCreator<S>) => {
  const store = actualCreate(createState);
  const initialState = store.getState();
  storeResetFns.add(() => store.setState(initialState, true));
  return store;
};

@dbritto-dev
Copy link
Collaborator

dbritto-dev commented Apr 7, 2023

@grigoll @FancyVase @dai-shi here's the PR #1739

@cam-shaw
Copy link

cam-shaw commented Jun 27, 2023

@FancyVase that solutions works great when using the example here
https://github.com/pmndrs/zustand/blob/3584d5075af278b674693193acde1aa03a7cd53b/docs/guides/how-to-reset-state.md

Appreciate it 🙏

@shahbazshueb
Copy link

Just a heads up, the currying fix on the mock create works for a "standard" create call, but errors if you're using the immer middleware with the same "TypeError: store.getState is not a function".

A little hacky, but to support both types of create calls, I added a wrapper that returns another function if no state is passed in (similar to what Zustand does internally):

export const create = <S>(createState: StateCreator<S>) => {
  return typeof createState === 'function'
      ? createInternalFn(createState)
      : createInternalFn;
};

const createInternalFn = <S>(createState: StateCreator<S>) => {
  const store = actualCreate(createState);
  const initialState = store.getState();
  storeResetFns.add(() => store.setState(initialState, true));
  return store;
};

Thanks @FancyVase Your solutions worked like a charm. I had been hitting my head for a long time as one of my tests were not passing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
7 participants