Store axios (JSON) response in array - reactjs

I have an array which is being used by another file to map out the contents. I originally hard coded values into this array, but now I'd like to integrate an axios get call to retrieve data, and then store the info from the response into the array. I can successfully get the JSON response with the correct data, but I am stuck on getting the JSON response data into the array. Any help would be greatly appreciated
let theArray = [
{
id: '',
name: '',
},]
useEffect(() => {
axios
.get(`/api/data`)
.then(res => {
//? need to store res.data.id to theArray.id, and res.data.name to theArray.name
})
}, [])

You can simply push the response to the array, but you'd have to begin with an empty array, otherwise, the first element you have hardcoded will not have any data.
let theArray = []
useEffect(() => {
axios
.get(`/api/data`)
.then(res => {
const newItem = {
id: res.data.id,
name: res.data.name,
};
theArray.push(newItem);
})
}, [])

Here another solution, I think #Sylens solution is a good one, this is just a matter of structuring your code as you want
let theArray = []
useEffect(() => {
axios
.get(`/api/data`)
.then(res => {
// object destructuring
const { id, name } = res.data;
theArray.push({ id, name })
})
}, [])

If your data is in json format you should wait for the info to get parsed, something like this:
let theArray = [
{
id: '',
name: '',
},
];
useEffect(() => {
axios
.get(`/api/data`)
.then(res => res.json())
.then((result) => {
theArray[0].id = result.id;
theArray[0].name = result.name;
})
}, []);
Edit: if you want to add the new data just push it to the array
theArray.push({
id: result.id,
name: result.name,
})

If it's only modifying first element:
let theArray = [{ id: '', name: '',},]
useEffect(() => {
axios
.get(`/api/data`)
.then(res => {
theArray[0].id = res.data.id
theArray[0].name = res.data.name
})
}, [])

Related

React does not rerender on updated state of nested array

I have an array of objects like so:
const [categories, setCategories] = React.useState([
{
id: 1,
title: 'Top Picks',
subTitle: "Today's hottest stuff",
images: [],
searchQuery: 'shoes',
},
...]);
Which I update with values in useEffect once like so:
React.useEffect(() => {
const newCategories = categories.map(category => {
fetch(`https://api.pexels.com/v1/search?query=${category.searchQuery}&per_page=10`, {
headers: {
'Authorization': apiKey,
},
}).then(r => {
r.json().then(convertedJson => {
category.images = convertedJson.photos;
});
});
return category;
});
setCategories(newCategories);
}, []);
however the child components here never rerender and I cannot figure out why. My understanding is that .map creates a new array anyhow, so the spread syntax isn't necessary in setCategories() but regardless it does not work.
{categories.map((category, i) => (
<CategorySlider {...category} key={i}/>
))}
There's a few issues but the primary issue I see is you're returning the category before the fetch can complete - so even when those fetch calls inside your map complete, you already returned the category below before the fetch completes.
Try using the .finally() block:
React.useEffect(() => {
const newCategories = categories.map(category => {
const c = {...category}; // <--- good practice
fetch(`https://api.pexels.com/v1/search?query=${category.searchQuery}&per_page=10`, {
headers: {
'Authorization': apiKey,
},
}).then(r => {
r.json().then(convertedJson => {
category.images = convertedJson.photos;
});
}).catch((err) => {
console.error(err);
}).finally(() => {
return category;
});
});
setCategories(newCategories);
}, []);
Thanks! Using setState before the promises resolved was indeed the problem. The solution looks like this now:
React.useEffect(() => {
async function fetchImages() {
const promises = categories.map(async category => {
const response = await fetch(
`https://api.pexels.com/v1/search?query=${category.searchQuery}&per_page=10`,
{
headers: {
Authorization: apiKey,
},
}
);
const convertedJson = await response.json();
category.images = convertedJson.photos;
return category;
});
setCategories(await Promise.all(promises));
}
fetchImages();
}, []);

Read Data from Firebase and save it into an Array - React

i just can't figure out why i can't save my loaded data into an array.
i`m trying to push the data to the array once the data is fully loaded (Within then())
Any idea why it's not working?
Many thanks :)
useEffect(() => {
fetchData = async () => {
let tempArray = [];
await firebase.firestore().collection('users').get().then((querySnapshot) => {
querySnapshot.forEach((doc) => {
firebase.firestore().collection('users').doc(doc.id).collection('posts').get().then((snapShot) => {
snapShot.forEach((newDoc) => {
tempArray.push({
id: doc.id,
data: newDoc.data()
})
})
})
})
})
console.log(tempArray) // Output: Array []
}
fetchData();
}, [])
.forEach IS NOT ASYNCHRONOUS - it WILL NOT wait for your inner-loop .get()s. You need to do something like:
await firebase.firestore().collection('users').get().then((querySnapshot) => {
Promise.all(querySnapshot.map((doc) => {
firebase.firestore().collection('users').doc(doc.id).collection('posts').get().then((snapShot) => {
snapShot.forEach((newDoc) => {
tempArray.push({
id: doc.id,
data: newDoc.data()
})
})
})
})
)
})
In addition - this seems pretty dang inefficient - since you're fetching ALL your users, and ALL their posts, you could just use a collectionGroup is a SINGLE round-trip, then sort by .parent if you need sorting (you don't show any such need in the example presented)
await firebase.firestore()..collectionGroup('posts').get().then((querySnapShot) => {
querySnapShot.forEach((newDoc) => {
tempArray.push({
id: doc.id,
data: newDoc.data()
})
})
})
Finally, you're mixing async/await with .then() syntax, which is generally not recommended:
// .get() is asynchronous
const querySnapShot = await firebase.firestore()..collectionGroup('posts').get();
// push() is synchronous, so need for await
querySnapShot.forEach((newDoc) => {
tempArray.push({
id: doc.id,
data: newDoc.data()
})
})

Set State erasing previous object value React

I'm trying to make subsequent API calls to get infos about some financial indexes.. After each call, I want to update de indexObject so it has all the data from all the indexes I stored on the indexes array. The problem is, each time setIndexObject is called it overwrites the object, loosing the previous value even when i use the spread operator.
const [indexObject, setIndexObject] = useState({});
const indexes = [
"^GDAXI",
"^BVSP",
"^NDX",
"^DJI",
"^GSPC",
"^IBEX",
"^HSI",
"^BSESN",
"^FTSE",
];
useEffect(() => {
indexes.forEach((index) => {
const options = {
method: "GET",
url:
"https://apidojo-yahoo-finance-v1.p.rapidapi.com/stock/v2/get-summary",
params: { symbol: `${index}`, region: "US" },
headers: {
"x-rapidapi-key":
"----",
"x-rapidapi-host": "apidojo-yahoo-finance-v1.p.rapidapi.com",
},
};
axios
.request(options)
.then(function (response) {
setIndexObject({
...indexObject,
[index]: {
value: response.data.price.regularMarketPrice.fmt,
variation: response.data.price.regularMarketChangePercent.fmt,
},
});
})
.catch(function (error) {
console.error(error);
});
});
}, []);
This is what I am trying to achieve:
{
A:{
value:,
variation:,
},
B:{
value:,
variation,
}
}
Thanks for the help!
The problem here is you're looping the request, while the setState is not synchronous. It is better to populate all the data first, then set the state after that.
const [indexObject, setIndexObject] = useState({});
const handleFetchData = async () => {
const indexes = [
"^GDAXI",
"^BVSP",
"^NDX",
"^DJI",
"^GSPC",
"^IBEX",
"^HSI",
"^BSESN",
"^FTSE",
];
const resultData = {};
for(const index of index) {
const response = await axios.request(); // add your own request here
resultData[index] = response;
}
return resultData;
}
useEffect(() => {
handleFetchData().then(data => setIndexObject(data));
}, []);
why i use for of? because forEach or .map cannot await asynchronous loop.
Or if you want to fetch all the data simultaneously, you can consider using Promise.all

How to post constant and dynamic data in axios?

const insertProductInfoToDatabase = () => {
products.map((product, index) => {
axios
.post(
ProductPostAPI,
{
orderNo: orderId,
customerId: "CD1",
itemId: product.prd_ID,
itemQnty: product.length,
itemRate: product.prd_Rate,
itemPrice: product.prd_Rate,
},
config
)
.then((response) => {
return response;
})
.catch((err) => {
console.log(err);
});
});
};
I have two constant data and four dynamic data and I want to post all these six data into my database through Axios. I'm a little bit confused about how to send data?

react Invalid attempt to spread non-iterable instance

I keep getting this error:
TypeError: Invalid attempt to spread non-iterable instance
while I'm trying to fetch some data in here :
export const genres = () => {
const apiUrl = "http://localhost:3000/api";
return fetch(apiUrl + "/genres")
.then(response => response.json())
.then(data => {
const res = Array.from(data.results);
return res;
});
};
console.log(genres)
export function getGenres() {
return genres().then(res => res.filter(g => g));
}
and updating the state of my component in here :
componentDidMount() {
const genres = [{ _id: "", name: "All Genres" }, ...getGenres()];
this.setState({ genres});
}
I'm aware that probleme comes from the fact that genres returns an object while the state should be an array but I'm not sure how to fixe it.
Thanks
getGenres returns a promise, so you need to wait for it to resolve before you try to put what is returned from it in state.
componentDidMount() {
getGenres().then(res => {
const genres = [{ _id: "", name: "All Genres" }, ...res];
this.setState({ genres });
})
}

Resources