龍が如く
龍が如く

Reputation: 309

VUE cannot update variable when API response

I want to update {{info}} value when the API is response.
But I don't know why there could be console log the response but cannot update the variable.
Any mistake I have make?

<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://unpkg.com/vue@next"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>

<body>
    <div id="app">
        <p>{{info}}</p>
    </div>
</body>

</html>
<script>
    const { reactive,createApp, ref } = Vue;
    const app = {
         setup(){
            info="waiting......";
            axios
            .get('https://api.coindesk.com/v1/bpi/currentprice.json')
                    .then(response => (this.info = response))
                    .then(response => (console.log(response)));
            return {info};
        }
    }
    const myVue = Vue.createApp(app).mount("#app");

</script>

Upvotes: 4

Views: 1698

Answers (4)

wittgenstein
wittgenstein

Reputation: 4472

here is a working example. If you want to use the composition API you have to make info a reactive variable with ref or reactive.

in this case you have to assign the new data to your reactive variable with the .value notation: info.value = data

composition API

const { createApp, onMounted, ref } = Vue;
const app = createApp({
  setup() {
    let info = ref('warning...')
    
    onMounted(() => {
      fetch('https://api.coindesk.com/v1/bpi/currentprice.json')
        .then(response => response.json())
        .then(data => {
          info.value = data
        });
    })

    return {
      info
    }
  }
});
app.mount("#app");
<script src="https://unpkg.com/vue@next"></script>
<div id="app">
  <p>{{info}}</p>
</div>

options API

Vue.createApp({
  data() {
    return {
      info: 'warning...'
    }
  },
  mounted() {
   fetch('https://api.coindesk.com/v1/bpi/currentprice.json')
    .then(response => response.json())
    .then(data => {
      this.info = data
    });
  }
}).mount('#options-api')
<script src="https://unpkg.com/vue@next"></script>
<div id="options-api">
  <p>{{ info }}</p>
</div>

console log the response but cannot update the variable

you have mixed the style from the composition API with the options API.

your code this.info = response will work with the options API (see my second example.) if you want to use the composition API you have to write info.value = response (see my first example).

note: I use the mounted hook only for demonstration purposes.

Upvotes: 1

FrankPl
FrankPl

Reputation: 929

As described in the composition API documentation, you need to use ref.

I.e. your code should be

const info=ref("waiting......");

Otherwise, it is just a normal JavaScript variable, and the "reactive magic" of Vue which re-renders the view does not kick in when you change the value. Please note that in some contexts, Vue does automatically make objects reactive, e. g. for data and props when you use the normal components syntax. But for teh composition API, you have to take care of that yourself.

Upvotes: 0

gangdaner
gangdaner

Reputation: 61

I think you need to declare a reactive variable via "reactive" in Vue3. such as:

enter code hereconst app = {
     setup(){
        // if your request return a value. otherwise, use as below
        // let info = reactive({});
        let info = ref("waiting......");
        axios
        .get('https://api.coindesk.com/v1/bpi/currentprice.json')
                .then(response => (this.info = response))
                .then(response => (console.log(response)));
        return {info};
    }
}

Upvotes: 0

龍が如く
龍が如く

Reputation: 309

one of workaround, using vue 2........

<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>

<body>
    <div id="app">
        <p>{{info}}</p>
    </div>
</body>

</html>
<script>
new Vue({
  el: '#app',
  data () {
    return {
      info: null
    }
  },
  mounted () {
    axios
      .get('https://api.coindesk.com/v1/bpi/currentprice.json')
      .then(response => (this.info = response))
  }
})

    </script>

Upvotes: 0

Related Questions