MartinMalinda / vue-concurrency

A library for encapsulating asynchronous operations and managing concurrency for Vue and Composition API.
https://vue-concurrency.netlify.app/
MIT License
352 stars 15 forks source link

Vue Warn onDestroyed is called when there is no active component instance to be associated with. #32

Closed snakemastr closed 3 years ago

snakemastr commented 3 years ago

Hi,

First time trying composition API and this package suits my needs. I was trying to combine the examples for useApiTask (using the store to provide a caching mechanism) with the AsyncContent (Loading states example) but as this is my first time stepping out to functional components and using composition API, I got this warning and don't know how to fix this:

Vue Warn: onDestroyed is called when there is no active component instance to be associated with. Lifecycle injection APIs can only be used during execution of setup().

This is my code (stripped unrelated stuff) Implementation (Inventory.vue):

<template>
    <AsyncContent :task="getProductsTask" v-slot="{ inventoryProducts }">
        <div v-if="inventoryProducts">...</div>
    </AsyncContent>
</template>

<script>
import { getProducts } from '../../data/inventory';
import AsyncContent from '~/components/AsyncContent';

export default {
    components: {
        AsyncContent
    },
    data() {
        return {
            getProductsTask: getProducts(this.$store.inventory)
        }
    },
}
</script>

data/inventory.js

import axios from "axios";
import { useApiTask } from "./utils";

export const endpoints = {
    getProducts(signal) {
        return axios("/products", {
            cancelToken: new axios.CancelToken((cancel) => {
                signal.pr.catch((reason) => {
                    if (reason === 'cancel') {
                        cancel();
                    }
                })
            })
        });
    }
};

export function getProducts(store, useCache = true ) {
    return useApiTask(endpoints.getProducts, store, 'Products', useCache);
}

the useApiTask is the same as in the example so I'll omit that for the sake of this post's length :)

MartinMalinda commented 3 years ago

Hey thanks for the report. I think I experienced this too at some point, unfortunately I'm not 100% sure how I got rid of it 😅

the first thing to double check is that any useTask, or in this case useApiTask, is called only in the root of the setup, not in in any kind of callback or after await, etc.

but perhaps there's also other factors at play - I'll check later when I have more time.

This is Vue 3 I suppose?

MartinMalinda commented 3 years ago

Hm -

data() {
        return {
            getProductsTask: getProducts(this.$store.inventory)
        }
    },

This doesn't seem right. I'm afraid you'll have to go with Composition API in this component. data: {} on component, is Options API.

so:

setup() {
 const store = useStore(); // this needs to come from VueX somehow!
 const getProducsTask = useApiTask(edpoints.getProducts, store, 'Products', { useCache: true });

return { getProductsTask };
}

written quickly, may contain typos Hope this helps!

snakemastr commented 3 years ago

Thank you for your quick reply!

No this is still Vue2 but I have the composition-api module. Like I said, first timer so still figuring out how its different from the Options API

It looks like I have to go in the Composition API as you said. I forgot to enable TS support in my Nuxt build and moving the code to setup removed all the warnings. Not sure how I would resolve the store but this helped me alot!

Great work on this package and thank you for your fast help!