Zustand store not working inside custom hook

Viewed 692

I am trying to move a few stats and functions to zustand store. These functions contain graphql mutation call. So I can not call such mutation directly from zustand store. So I created a custom hook to wrap zustand store. This hook is supposed to return the store instance so that I can access it from anywhere.

useStore.ts
-----------
import create from 'zustand';

const useStore = () => {
    const [setData] = useMutation(SET_DATA);
    const setA = () => {
        //some mutation call
        store.setState({a: 10})
    }
    const store = create(set => ({
        a: 0,
        setA,
    }))
    return store();
}
export default useStore;
ComponentOne.tsx
----------------

import useStore from 'useStore';

const ComponentOne = () => {
    const { a, setA } = useStore();
    setA();
    return <div>{a}</div>
}

ComponentTwo.tsx
----------------

import useStore from 'useStore';

const ComponentTwo = () => {
    const { a } = useStore();
    return <div>{a}</div>
}

In second component, The value of a always stay 0. It should 10.

1 Answers

In my actual use, define the useStoreZu.js file as follows:

const useStoreZu = create(set => ({
  bears: 0,
  increasePopulation: () => set(state => ({ bears: state.bears + 1 })),
  removeAllBears: () => set({ bears: 0 })
}))

export {
   useStoreZu
}

The component ComponentOne.js is used as follows:

import {useStoreZu }from './usezutand';

export default function ComponentOne() {
    const { bears,increasePopulation ,removeAllBears } = useStoreZu();
    return (<div>
        <button onClick={
            (e)=>{e.preventDefault();
            increasePopulation();
        }}>
            click increasePopulation me
        </button>
        {bears}
        <hr/>
    </div>)
}

The component ComponentTwo.js is used as follows:

import {useStoreZu }from './usezutand';

export default function ComponentTwo(){
    const { bears } = useStoreZu();
    return <div>{bears}</div>
}

Update: useStoreZu.js to the following definition, use zustand/middleware to add subscribe with selector, you can define GraphQL outside the hook function query function,reference document address middleware

const useStoreZu = create(
    subscribeWithSelector(() => ({ paw: 10, snout: true, fur: 14.0 }))
);

Add: ComponentThree.js is a function component that uses the subscribe with selector function , the code is as follows, and the value of the stored state can be rewritten.

import { zustandStore }from './usezutand';
import { subscribeWithSelector } from 'zustand/middleware';

export default function ComponentThree(){
    const store =  zustandStore;
    const { getState, setState, subscribe, destroy } = store;
    var unsub = undefined;//subscribe
    let paw = store.getState().paw;
    const snout = store.getState().snout;
    const fur = store.getState().fur;
    console.log('paw_' + paw +' _' +'snout_ ' + snout + '_' + 'fur_' + fur);
    console.log('getState_' + getState +'\n' +'setState_ ' + setState + '\n' 
        + 'subscribe_' + subscribe);
    // Destroying the store (removing all listeners)
    const settingUnSubscribe = ()=>{
        if (unsub != undefined) {
            unsub();
        }
        store.destroy();
    }
    // Listening to all changes, fires synchronously on every change
    const settingSubscribe = ()=>{
        unsub= subscribe(state => state.paw, custSubcribeFunc(paw));
    }
    const custSubcribeFunc = (paw)=>{
        store.setState({ paw: store.getState().paw + 1 });
        paw = store.getState().paw;
        console.log('paw __ ' + paw);
    }
    return (<div>
            <button onClick={
                (e)=>{e.preventDefault();
                settingSubscribe();
            }}>
                click subscribe me
            </button>
            {paw}
            <hr/>
            <button onClick={
                (e)=>{e.preventDefault();
                settingUnSubscribe();
            }}>
                click unsubscribe me
            </button>
            <hr/>
        </div>)
}

hope to help you

Related