Subscriptions

Basic Usage

You can add subscriptions to a module, and call listeners when state changes.

The parameter of subscribe could be a simple listener function or a config object.

The most commonly used config is selector, by adding selector, you can subscribe to part of the module.

const module = defineModule({ pokemonIndex: 0, input: '' })
  .subscribe((state, prevState) => console.log(state)) // subscribe to the whole store
  .subscribe({
    selector: (state) => state.pokemonIndex, // only subscribe to some property
    listener: (pokemonIndex) => {
      console.log(pokemonIndex);
    },
  })
  .build();

Also you can config your customized compare function, or set fireImmediately to false, to prevent the first listener callback.

Async effect cleanup

For async functions, there could be need to clean the previous effect, for example, abort the previous network request.

You can use addCleanup , this is a common pattern in react useEffect

const module = defineModule({ pokemonIndex: 0, input: '' })
  .subscribe({
    selector: (state) => state.pokemonIndex, // only subscribe to some property
    listener: async (pokemonIndex, prev, { addCleanup }) => {
      let isCleaned = false;
      // we can use such bool flag, or we can use the abortSignal
      // which is better, and can abort network request
      addCleanup(() => (isCleaned = true));
      await someAsyncJob()
      if (isCleaned) return
      // dosomething
    },
    fireImmediately: false,
    equalityFn: () => ...
  })
  .build();

Other ways for subscription

Since zoov module won't get destroyed or cleaned up, all the listeners will last forever.

If you want to get better control of the subscription lifecycle, you may use the zustand subscribe, and you can add the listener when component is mounted, and unsubscribe it when component is unmounted.

const store = useModule(Module);
useEffect(() => {
    const unsub = store.subscribe(...);
    return unsub;
}, []);

Tips: the TypeDef of subscribeWithSelector middleware is not working now in TypeScript, this is an known issue. But for JS project, it could be fine. I'm working for a way to add type for middleware

Last updated