overbyte
overbyte

Reputation: 618

Show loaded data in curly braces using Vue 3 Composition API

Can someone explain the difference between the following, please?

Options API version

Displays loaded data in DOM as expected

export default {
    data() {
        return {
            config: {},
        };
    },
    async mounted() {
        this.config = await fetch('/path/to/file.json');
    },
    template: `<div>{{ config }}</div>`
}

Composition API version

Displays initial state of config but not the loaded data

import { onMounted, reactive } from 'vue';

export default {
    setup() {
        let config = reactive({});

        onMounted(async () => {
            config = await fetch('/path/to/file.json');
        });

        return {
            config,
        };
    },
    template: `<div>{{ config }}</div>`
}

I suspect that the reactive() is being overridden by the asynchronous data load (and I can console log the new data in the onMounted function) but I can't see anything in the docs to indicate how to mass-update a reactive object like this (especially when it works in the Options API)

Edit: final thoughts:

I've taken to using reactive objects to provide / inject data around the app and then using toRefs as a JIT way to provide the reactive data to my views. This seems to be the best of both worlds.

example:

import { onMounted, reactive, toRefs } from 'vue';

export default {
    setup() {
        const data = reactive({
            config: {},
        });

        onMounted(async () => {
            data.config = await fetch('/path/to/file.json');
        });

        return {
            ...toRefs(data),
        };
    },
    template: `<div>{{ config }}</div>`
}

Upvotes: 1

Views: 859

Answers (2)

hamid-davodi
hamid-davodi

Reputation: 1966

I think the difference between two example that you mentioned is the this keyword. According to Vue 3 documentation, Inside setup(), this won't be a reference to the current active instance. So in the second code that you mentioned (composition API), you can not set only "config" word to an output of a fetch process. It is better to set a key for your object to work. for example for me this code works correctly:

<template>
    <div>{{ config }}</div>
</template>

<script>
import { onMounted, reactive } from 'vue';

export default {
    name: "configCompo",
    setup(props) {
        let config = reactive({});

        onMounted(
            async () => {
                console.log("mounted")
                let response = await fetch('https://jsonplaceholder.typicode.com/users');
                console.log(response);
                let data = await response.json();
                console.log(data);
                config.output = data;
            }
            

        );

        return {
            config,
        };
    }
}
</script>

Upvotes: 1

Orbis
Orbis

Reputation: 475

I think if you are overriding the whole config you should use ref instead of reactive. See HERE

  setup() {
    let config = ref({});

    onMounted(async () => {
        config.value = await fetch('path/to/file.json');
    });

    return {
        config,
    };
}

Never the less its working with reactive too:

  setup() {
    let config = reactive({});

    onMounted(async () => {
        config.value = await fetch('path/to/file.json');
    });

    return {
        config,
    };
}

Upvotes: 1

Related Questions