My problem is with using an Axios response in Vue.js; it seems that the data is not saved to the array (newBox).
I want to save API-returned values to an array for use with v-for in the component.
<script setup>
import {
RouterLink,
RouterView
} from 'vue-router';
import {
onMounted,
onUnmounted
} from 'vue'
import Box from './components/Box.vue';
import axios from "axios"
import {
propsToAttrMap
} from '@vue/shared';
var newBox = new Array();
onMounted(() => {
getPosts();
})
async function getPosts() {
try {
const url = `https://someurl.ir/api/v1/api.php`
const response = await axios.get(url)
this.newBox = response.data
}))
} catch (err) {
if (err.response) {
// client received an error response (5xx, 4xx)
console.log("Server Error:", err)
}
}
}
</script>
<template>
<div >
<Box v-for="title in newBox" :msg="title" />
</div>
<RouterView />
</template>
<style scoped>
.NewBoxRibbon{
scrollbar-width: 0px;
width: 100%;
height: 450px;
background-color: aquamarine;
overflow-x: auto;
white-space: nowrap;
}
::-webkit-scrollbar {
width: 0;
/* Remove scrollbar space */
background: transparent;
/* Optional: just make scrollbar invisible */
}
</style>
I used fetch and it too seems that in function getPosts it couldn't modify the array newBox...
Even when I define a variable and try to modify it in the function getPosts, can't do!!
CodePudding user response:
Define newBox as a ref property then update by reponse newBox.value = response.data:
import {
onMounted,
onUnmounted,
ref
} from 'vue'
// ....
var newBox = ref([]);
//....
const response = await axios.get(url)
newBox.value = response.data
CodePudding user response:
I agree with the previous answer. If you do not wrap the variable in a ref(), you are not using the reactivity part of the Composition API and thus the DOM is not updating.
It also appears you have extra closing parens in your try block, and note the 'this' keyword is not applicable in setup() functions. See VueJS docs regarding moving from Options API to Composition API and handling 'this'.
Finally, double-check that the response dot notation is correct. Are you certain that response.data is sufficient for traversing the JSON response or should it be response.data.posts perhaps? Console log the response to be sure.
<script setup>
import { RouterLink, RouterView } from "vue-router";
import { onMounted, ref } from "vue";
import Box from "./components/Box.vue";
import axios from "axios";
var newBox = ref([]);
onMounted(() => {
getPosts();
});
async function getPosts() {
try {
const url = "https://someurl.ir/api/v1/api.php";
const response = await axios.get(url);
this.newBox.value = response.data.posts;
} catch (err) {
if (err.response) {
// client received an error response (5xx, 4xx)
console.log("Server Error:", err);
}
}
}
</script>
<template>
<div >
<Box v-for="title in newBox" :msg="title" :key="title" />
</div>
<RouterView />
</template>
CodePudding user response:
Summary
- Import
reffrom'vue' - Define
newBoxasconst newBox = ref([]) - Use
newBoxasnewBox.valueinstead ofthis.newBox
import { ref } from 'vue'
// ...
const newBox = ref([])
// ...
newBox.value = response.data
Full story
The reason why newBox is not being updated is that you are creating it as a plain array. In Vue, things that require reactivity (like v-for, computed properties, watchers, etc.) require you to use a ref of reactive object.
For example:
import { ref } from 'vue'
const newBox = ref([])
The value of the ref is then accessed on the .value property:
newBox.value = response.data
You do not need to use .value in the template in most cases, as it is automatically unwrapped (only a single level, so objects of refs will still require you to use .value, but that's probably more than you need to know right now).
Notes:
- You do not need to use
thisinscript setup, you can pretty much act as if it is a regular JS script. - Prefer
letandconstovervar. Forrefs useconst, as they are never reassigned. - Prefer array literals over the
new Array()syntax. - I'm not sure what you are using
propsToAttrMapfor (I have never even heard of it), but if you really need it, at least import it from'vue'not'@vue/shared'.
I have incorporated these notes into the following code, and left out the parts that are not directly relevant (HTML, onUnmounted, etc.).
I have also removed the })) in the try block in getPosts, as they should not be there.
So your JS code would then look like this:
import { onMounted, ref } from "vue";
import axios from "axios";
const newBox = ref([]);
onMounted(() => {
getPosts();
});
async function getPosts() {
try {
const url = `https://someurl.ir/api/v1/api.php`;
const response = await axios.get(url);
newBox.value = response.data;
} catch (err) {
if (err.response) {
// client received an error response (5xx, 4xx)
console.log("Server Error:", err);
}
}
}
Extra advice: you should almost always use the key attribute on the v-for element (List Rendering - Maintaining State with key).
Also, the Vue docs are excellent! Most questions can be answered just by reading the relevant section.
Useful doc links:
Hope this helps!
CodePudding user response:
Thanks for all my mistake was ref and way of using it v-for...
