nanostores/query

$store.set() not triggering the fetcher store

hemandev opened this issue · 8 comments

I have a fetcher that has a dependent value on another store.

const [createFetcherStore, createMutatorStore] = nanoquery({
    fetcher: async (...keys: (string | number)[]) => {
      const methodName = keys[0] as keyof Instance['notification'];
      if (methodName === 'get') {
        console.log('page no is...', keys[1]);
        return instance.notification.get({
          pageNo: keys[1] as number,
          limit: 3,
        });
      }
    },
  });
  
  const $currentPage = atom(1);
  const $notificationStore = createFetcherStore<Notification>([
    'get',
    $currentPage,
  ]);

I have a function in vanilla js loadMore()

    const loadMore = async () => {
     $currentPage.set($currentPage.get() + 1);
    };

I am trying to use these in vanilla js using the listen().

But calling loadMore() is not triggering the $notificationStore. Why?
Shouldn't the $currentPage store change trigger the $notificationStore ?

Hey there, @hemandev!

The reactivity on the library side works (and it's pretty thoroughly tested as well!). Vanilla or not, all framework libraries essentially wrap .listen with framework-specific memoization, like in @nanostores/react.
And, most probably, it's not a reactivity issue in nanostores as well, as the code that sets the Promise result value is extremely straightforward.

The issue with your code, as I think, lies in what instance.notification.get function returns, but without the actual implementation details I can't point to an exact issue.
Can you try to come up with an isolated reproduction case on Stackblitz?

Thanks for the quick response @dkzlv.
I was able to spin up a basic repro sandbox here. Would you mind taking a look?
https://codesandbox.io/p/sandbox/silly-chandrasekhar-ng2tkg

My expectation is that the subscribe() will get called with the new todo values on calling loadMore()

@hemandev Hm, yeah, the issue is in onNotify hook (if you comment it out and change $todo?.data for $todo.value?.data, all works as expected), but I don't know exactly why. I'll keep the issue open and see what my cause it either in query or in core.

Yeah, that did fix it.
Unfortunately, I was using onNotify to keep appending all the fetched todos to another store.
Let me see if I can figure another way to do it. Thanks again.

@hemandev onSet definitely works.

I tried with onSet first. But it was not getting triggered always. You can try in the same sandbox.
It calls twice, {loading: false}, {loading: true, data: }` and stops.
It never called the 3rd time with the resolved value.

@hemandev Ok, I managed to pinpoint the issue, but I don't know why that happens.

Both onNotify and onSet work, but you need to either use $todo.value in onNotify or destructure newValue from payload in onSet like in this example. For some reason using .get() breaks all of this thing, even though it's basically calling .value.

Yep, that worked 🎉