How to post constant and dynamic data in axios? - reactjs

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?

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();
}, []);

How to get the data through the map and put it in the state

I wanted to use Axios get to put the contents value of 'card' and call the data and put the value in 'wordAll', but it failed.
I want to combine and store the arrays I received as an axios in the state through the map function.
Sometimes the code I wrote comes in and sometimes it doesn't. I know my code is wrong.
Please teach me the way.
const [wordAll, setWordAll] = useState([]);
useEffect(() => {
cards.map((contents) => {
axios
.get(`https/api/words/detail_list/?contents=${contents.contents}`, {
headers: {
Authorization: cookies.token,
},
})
.then((res) => {
let indata = res.data;
for (var i = 0; i < indata.length; i++) {
wordAll.push(indata[i]);
setWordAll(wordAll);
}
console.log('wordAll0', wordAll);
})
.catch((error) => {
console.log('err==>', error);
});
});
}, []);
console.log('wordAll1', wordAll);
You can keep the cards axios request promises in an array (cardsPromises) and then use Promise.all to get the values from the resolved promises.
useEffect(() => {
const cardsPromises = cards.map((contents) =>
axios.get(`https/api/words/detail_list/?contents=${contents.contents}`, {
headers: {
Authorization: cookies.token
}
})
);
Promise.all(cardsPromises)
.then((resp) => {
//resp will be an array of resolved values
setWordAll(resp);
})
.catch((error) => {
console.log("err==>", error);
});
}, []);

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()
})
})

Using JS native fetch() api in React ComponentDidMount() results in a pending Promise

I was trying to load data into my project from the public folder in the componentDidMount() lifecycle method. However, I didn't get the desired FeatureCollection Object but a pending Promise.
componentDidMount = () => {
...
const data = fetch(`vcd/${this.state.monthFile}`)
.then(response => response.text())
.then(async data => {
return csv2geojson.csv2geojson(data, {
latfield: 'lat',
lonfield: 'lng',
delimiter: ','
}, (err, data) => {
if (err) console.log(err);
console.log(data); // correctly outputs a FeatureCollection, length 30277
return data;
// this.setState({ someAttribute: data }) => Also doesn't work.
})
})
.then(data => data); // If to use another Promise chaining, the result would be undefined.
console.log(data); // a pending Promise
}
My file contains 30277 rows * 3 columns, ~500Kb in size, which I think shouldn't be a problem with data loading, and after consulting the csv2geojson and fetch API, I still can't think of a solution to this problem. I am grateful for any helpful inputs.
EDIT: Using both async-await pattern and chaining another .then would result in undefined.
JS Fetch returns a promise so its because you're returning that promise.
So just change your code like this it will work;
import React, { useEffect, useState } from "react";
export default function ExampleHooks() {
const [data, setData] = useState(null);
var csv2geojson = require("csv2geojson");
useEffect(() => {
fetch("https://gw3xz.csb.app/sample.csv")
.then((response) => response.text())
.then(async (data) => {
csv2geojson.csv2geojson(
data,
{
latfield: "lat",
lonfield: "lng",
delimiter: ","
},
(err, data) => {
if (err) console.log(err);
setData(data);
}
);
});
}, []);
return <div onClick={() => console.log(data)}>show data</div>;
}
or as a Class Component:
import React from "react";
var csv2geojson = require("csv2geojson");
class ExampleClass extends React.Component {
state = {
data: null
};
componentDidMount() {
fetch(`vcd/${this.state.monthFile}`)
.then((response) => response.text())
.then(async (data) => {
csv2geojson.csv2geojson(
data,
{
latfield: "lat",
lonfield: "lng",
delimiter: ","
},
(err, data) => {
if (err) console.log(err);
this.setState({ data: data });
}
);
});
}
render() {
return <div onClick={() => console.log(this.state.data)}>show data</div>;
}
}
export default ExampleClass;
Working example over here
fetch returns a promise, and that is what you save to data. If you want to log the "data", then you have a couple options.
Log it IN the promise chain (you already do that)
Convert over to async/await and await the fetch to resolve/reject
code
componentDidMount = async () => {
...
const data = await fetch(`vcd/${this.state.monthFile}`)
.then(response => response.text())
.then(data => {
return csv2geojson.csv2geojson(data, {
latfield: 'lat',
lonfield: 'lng',
delimiter: ','
}, (err, data) => {
if (err) console.log(err);
console.log(data);
return data;
})
});
console.log(data); // a resolved/rejected Promise result
}

Store axios (JSON) response in array

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
})
}, [])

Resources