javascriptreactjsvitemonorepozustand

Zustand store doesn't work in monorepo (external package)


We have a set of different webViews they are all independent react apps that can have a shared codebase, but run in an isolated manner (not a microfrontend). We started to build a lerna monorepo repository and split the codebase into different reusable packages. We have multiple reusable infra zustand stores that will be placed in the shared package and be imported from different applications. Here, we encounter issues. After moving the store into the package, the app stopped loading. I built a test repo to reproduce the issue from the clean repository. https://github.com/roman-rookout/zustand-package-test

Very basic - a package with a store:

const useTestStore = create<Store>((set) => ({
      count: 0,
    increment: () => set((state) => ({ count: state.count + 1 })),
    decrement: () => set((state) => ({ count: state.count - 1 })),
}));

And usage in the main component

function App() {
     const { count, increment, decrement } = useTestStore();
     ...
     <p>{count}</p>
      <button onClick={() => increment()}>
    ...

What I see, is a warning about "InvalidHooks usage outside of react component" which is weird and "TypeError: Cannot read properties of null (reading 'useRef')". It points to the row - const { count, increment, decrement } = useTestStore();

Error in console

So any usage of hook will fail also useTestStore((state) => state.count). Only "non hook" method like useTestStore.getState().count will work.

I would appreciate any input. Maybe we should reconsider the way we bundle the library in Vite.

Things I tried so far:

From research it points out what it could be a duplicate React issue:

I bet what I am missing is something simple, but literally being stuck for now and it prevents us from moving forward with monorepo. I couldn't find much information on the internet as well of people using zustand in monorepo which should be a pretty common and trivial thing.


Solution

  • Eventually, the only issue was that the Vite configuration section I added was in the wrong place.

    So now I had at lib vite.config:

    rollupOptions: {
            external: ['react', 'react-dom'],
    }
    

    and in app layer vite.config:

    
     resolve: {
          dedupe: ['react', 'react-dom', '@emotion/react', '@emotion/styled', '@mui/material', '@mui/system'],
     },
    

    That's a working configuration for me