hyper-fetch icon indicating copy to clipboard operation
hyper-fetch copied to clipboard

[Core] 7.0.0 Add effect

Open lobor opened this issue 6 months ago • 5 comments

Is your feature request related to a problem? Please describe. In V6, in my code i used RequestEffect for update cache when POST request success

client.addEffect(
  new RequestEffect({
    effectKey: createTodo.effectKey,
    onSuccess: (response) => {
      if (!response?.data) return;
      client.cache.update(
        getTodos,
        (prev) => {
          if (!prev?.data) return {};
          return { ...prev, data: [...prev.data, response.data] };
        }
      );
    },
  })
);

does not have similar mechanics on V7

lobor avatar Jun 26 '25 07:06 lobor

Hey, @lobor I will work on the detailed migration guide this week - we introduced the Plugin instead of Effect. https://hyperfetch.bettertyped.com/docs/core/plugin

Plugin was made from the RequestEffect, but as a more "general" utility. You will be able to create let's say CachePlugin which will update caches for the requests of your choice. 👍🏻

https://hyperfetch.bettertyped.com/docs/api/core/Classes/Plugin#onrequestsuccess

export const CachePlugin = () => new Plugin({ name: "cache-plugin" }).onRequestSuccess(({ request, response }) => {
  if(request.queryKey === createTodo.queryKey) {
      client.cache.update(
        getTodos,
        (prev) => {
          if (!prev?.data) return {};
          return { ...prev, data: [...prev.data, response.data] };
        }
      );
  }
})

// In the directory with client
client.addPlugin(CachePlugin());

prc5 avatar Jun 26 '25 07:06 prc5

Thanks for the update and example!

However, this new approach feels a bit too generic for my use case. In V6, RequestEffect allowed me to directly attach cache updates to specific requests in a very targeted way.

With the new Plugin system, I’m concerned that:

I’ll end up writing a single plugin with many if/else statements to differentiate between routes/models, or

I’ll need to create many small plugins — one per request — which can be hard to scale and maintain.

It would be great to have a more granular API again, something like:

createTodo.lifecycle.onSuccess((response) => {
  if (!response?.data) return;
  client.cache.update(
    getTodos,
    (prev) => {
      if (!prev?.data) return {};
      return { ...prev, data: [...prev.data, response.data] };
    }
  );
});

This would allow request-specific logic without needing to manage multiple plugins or complex conditional logic inside one.

Is something like this planned or possible with the current architecture?

lobor avatar Jun 26 '25 07:06 lobor

This is very interesting use case, thank you for the example and explanations. I will make some way to handle side-effects in more atomic approach. 👍🏻 💯

prc5 avatar Jun 26 '25 09:06 prc5

Hi, any idea when the feature will be deployed? This is what we need to upgrade to v7

lobor avatar Aug 25 '25 08:08 lobor

@lobor We're still discussing how to revive this functionality, but unfortunately the previous version (even in your example) was used in a way that was quite problematic – we're talking about circular dependencies. I think we'll eventually drop the option to support Flux-like approach in effects. This will significantly simplify the experience, and the previous functionality we wanted to preserve will be available through plugins.

I think we will start developing it really soon after finalizing tests and development of our "fetch" adapter - I guess plus-minus month, since the team will leave for vacations on September 🌞

prc5 avatar Aug 25 '25 09:08 prc5