Kong / swrv

Stale-while-revalidate data fetching for Vue

Home Page:https://docs-swrv.netlify.app

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[Feature request] Allow use of useSWRV outside of setup()

matthew-dean opened this issue · comments

Right now, I'm trying to refactor a page that has cascading fetch calls. That is, based on the results of one call, it kicks of a different one using those as parameters.

To do that, it uses computed properties to set the value, which prompts a reactive response to kick of the second.

However, I discovered when using SWRV that this scenario is not supported at all, mostly because of these lines.

I understand that the instance is not retrievable outside of setup, but could you add the ability to pass the instance somehow, or some other method so that fetch calls can occur anywhere? Or alternatively, some way to set up the reactive object and defer fetching until later?

Note also that the use of getCurrentInstance() is not supported by Vue.

We exposed getCurrentInstance mostly for official libraries that need additional internal access, not for userland application code. It was mistakenly documented in WIP v3 docs but is no longer considered a public API.

This solved my problem for me.

diff --git a/node_modules/swrv/dist/use-swrv.js b/node_modules/swrv/dist/use-swrv.js
index 3b38f2a..494b664 100644
--- a/node_modules/swrv/dist/use-swrv.js
+++ b/node_modules/swrv/dist/use-swrv.js
@@ -216,10 +216,10 @@ function useSWRV() {
     var isHydrated = false;
     var instance = (0, vue_1.getCurrentInstance)();
     var vm = (instance === null || instance === void 0 ? void 0 : instance.proxy) || instance; // https://github.com/vuejs/composition-api/pull/520
-    if (!vm) {
-        console.error('Could not get current instance, check to make sure that `useSwrv` is declared in the top level of the setup function.');
-        return null;
-    }
+    // if (!vm) {
+    //     console.error('Could not get current instance, check to make sure that `useSwrv` is declared in the top level of the setup function.');
+    //     return null;
+    // }
     var IS_SERVER = (vm === null || vm === void 0 ? void 0 : vm.$isServer) || false;
     // #region ssr
     /**
diff --git a/node_modules/swrv/esm/use-swrv.js b/node_modules/swrv/esm/use-swrv.js
index 2921590..ea0c312 100644
--- a/node_modules/swrv/esm/use-swrv.js
+++ b/node_modules/swrv/esm/use-swrv.js
@@ -211,10 +211,10 @@ function useSWRV() {
     var isHydrated = false;
     var instance = getCurrentInstance();
     var vm = (instance === null || instance === void 0 ? void 0 : instance.proxy) || instance; // https://github.com/vuejs/composition-api/pull/520
-    if (!vm) {
-        console.error('Could not get current instance, check to make sure that `useSwrv` is declared in the top level of the setup function.');
-        return null;
-    }
+    // if (!vm) {
+    //     console.error('Could not get current instance, check to make sure that `useSwrv` is declared in the top level of the setup function.');
+    //     return null;
+    // }
     var IS_SERVER = (vm === null || vm === void 0 ? void 0 : vm.$isServer) || false;
     // #region ssr
     /**

This issue body was partially generated by patch-package.

Tried it with computed properties and got the same issue as you show. I think just using function evaluation and Vue reactivity could solve the issue for you. This is how I solved it:

const { data, error, isValidating, mutate } = useSWRV<Type[]>(
    () => {
        if (!condition) return undefined;
        return '/some/path/to/resource';
    }
);

As long as the inner function returns undefined, Swrv will not fetch anything. As soon as the condition becomes true, the function will be reevaluated due to Vue reactivity and will return the path. At least that is my understanding of it! Hope it helps.

Edit: It is still defined during setup, but the fetching will be later based on reactivity.

Or we should support usage like app.use(SWRV), so that swr doesn't need to get vm when make requests

I believe the suggestion by @memen45 here is what I would suggest as well.

Separately, the use of getCurrentInstance is essentially no longer necessary since SSR support was removed with the release of version 0.10.0. I think the existing check is still technically fine as it causes use-swrv to exit if the instance cannot be found, meaning it is being called outside of the setup function.

There are better ways to make this check, but since the method is still available, I lean on the side of doing nothing in order to prevent changes that are "under the hood" and do not impact anything functional.

Or we should support usage like app.use(SWRV), so that swr doesn't need to get vm when make requests

I personally don't like this option; I'm not sure I see the value in registering the function globally on app init...?

@memen45

As long as the inner function returns undefined, Swrv will not fetch anything.

Oh! That's good to know. I'd prefer to not patch the package if I don't have to. I'll try that, thanks. I'd still like to see this restriction to setup() removed though.

@memen45 I'm looking at this a little more deeply. Can you tell me how changing the condition will cause a re-fetch? I thought only a reactive key could. Is the function a type of Vue reactive observer?

See the section on "Dependent Fetching" here: https://docs-swrv.netlify.app/features.html#dependent-fetching

I'd still like to see this restriction to setup() removed though.

This restriction must remain in place due to the setup/teardown in the onMounted and onUnmounted hooks.

@adamdehaven

See the section on "Dependent Fetching" here

Oh! Somehow I missed this! Thanks so much! That's exactly what I was struggling with

Hi @adamdehaven, I see you replied about the setup() limitation, would you mind expanding on that please?

We are evaluating the patch proposed here since with that we'd have a much cleaner/easier flow in our app by using it outside of setup().

Functionality-wise everything seems to work correctly with that patch, even the localStorage usage, but it would be great to have a feedback from your side.

Thank you!

Or we should support usage like app.use(SWRV), so that swr doesn't need to get vm when make requests

I personally don't like this option; I'm not sure I see the value in registering the function globally on app init...?

That's not for registering the function globally, just for swrv to get the app context app._context

@vpitorri the setup() function requirement must remain in place since swrv initiates calls in both the onMounted and onUnmounted hooks here.

These calls must be made from within the setup() function.

@vpitorri the setup() function requirement must remain in place since swrv initiates calls in both the onMounted and onUnmounted hooks here.

These calls must be made from within the setup() function.

@matthew-dean thank you for the reply and I'm sorry if this question might sound dumb, but what I'm not getting are the consequences of an usage outside of setup().
I'm asking this only because it seems to be working correctly even if used outside of it (with the patch), so I'd love to understand what could be missing.

@vpitorri ? Not sure you're asking the right person. Should be asked of the library author. In any case, I was able to figure out how to use dependent fetching to revert the patching method.

commented

@matthew-dean Might you be able to share a snippet of how you solved the use outside of setup using dependent fetching without the patch? I'm trying to useSWRV in a composable and running into the same issue.

@dsolanorush It's just this: https://docs-swrv.netlify.app/features.html#dependent-fetching

If useSWRV is passed a function instead of a static key, and if that function references a reactive value, then it will re-compute when the reactive value changes. If the function returns a falsey value, it won't fetch. So, you can set up both in setup, but have the second useSWRV passed a function that depends on reactive value set by the first.

Yep, exactly this ^^

Thanks for the detailed example

commented

@matthew-dean - Thanks for the clarification. I overlooked the reactive value part of dependency fetching. Much appreciated.