I'm running into a problem that I've been working on for days and unfortunately I can't figure it out by myself. I'm trying to create a View which shows some information from an API. But every time I map this item, I want to do another API call which checks the live price of that product.
So I have for example some JSON data what I get from an API.
{
"id": 1,
"name": "test product",
"productid": "73827duf"
},
{
"id": 2,
"name": "test product2",
"productid": "734437dde"
}
So I show this data with the following code inside my application:
{item.products.map((products) => {
return (
<View
key={products.id}
>
<Text
style={{
fontSize: FONTS.body3,
paddingLeft: 10,
}}
>
{products.name}
{getProductPriceJumbo(
products.productid
)}
</Text>
</View>
);
})}
So I want to run every time a function which fetches data from another API. I'm sending the productID because that's the only information I need to call this API. You can see this function down below:
function getProductPriceJumbo(id) {
fetch("https://---/test.php?id=" id "/", {
method: "GET",
})
.then((response) => response.json())
.then((data) => {
return data[0].price;
});
}
So this fetch returns a big list with information about the product from a third party API. I only want to return the price, that's the reason why I only return the price value and I want to print this out on the view above. I can't really figure out how to do this. I get undefined from the function every time I run it. Hope someone can help me with this.
CodePudding user response:
Create a new Price
Component to display the price
function Price({ id }) {
const [price, setPrice] = useState(0);
useEffect(() => {
function getProductPriceJumbo(id) {
fetch("https://---/test.php?id=" id "/", {
method: "GET"
})
.then((response) => response.json())
.then((data) => {
setPrice(data[0].price);
});
}
getProductPriceJumbo(id);
},[]);
return <Text>{price}</Text>;
}
And your .map
will become
{
item.products.map((products) => {
return (
<View key={products.id}>
<Text
style={{
fontSize: FONTS.body3,
paddingLeft: 10
}}
>
{products.name}
<Price id={products.productid} />
</Text>
</View>
);
});
}
CodePudding user response:
The reason you are getting undefined is because the window is rendering before the function finishes running. You will have define an asynchronous function before you return your view.
const [data, setData] = useState([])
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchData = async () =>{
setLoading(true);
try {
const {data: response} = await axios.get('API URL');
setData(response);
} catch (error) {
console.error(error.message);
}
setLoading(false);
}
fetchData();
}, []);
Then you can use data[0].price;
CodePudding user response:
You'll probably want to make your individual product into its own component that handles the fetching, and setting the price to a state value that's local to that product view. Here's a full example of how you could do that:
import { useState, useEffect } from "react";
const Product = ({ product }) => {
const [price, setPrice] = useState("Price loading...");
useEffect(() => {
fetch("https://---/test.php?id=" product.productid "/", {
method: "GET"
})
.then((response) => response.json())
.then((data) => {
setPrice(data[0].price);
});
}, [product]);
return (
<View>
<Text
style={{
fontSize: FONTS.body3,
paddingLeft: 10
}}
>
{product.name}
{price}
</Text>
</View>
);
};
const App = () => {
const item = {
products: [
{
id: 1,
name: "test product",
productid: "73827duf"
},
{
id: 2,
name: "test product2",
productid: "734437dde"
}
]
};
return (
<div>
{item.products.map((product) => (
<Product key={product.id} product={product} />
))}
</div>
);
};
Alternatively, you could use Promise.all
to get all of the price values before mapping your products:
import { useState, useEffect } from "react";
const App = () => {
const [item] = useState({
products: [
{
id: 1,
name: "test product",
productid: "73827duf"
},
{
id: 2,
name: "test product2",
productid: "734437dde"
}
]
});
const [products, setProducts] = useState([]);
useEffect(() => {
Promise.all(
item.products.map(async (product) => {
const response = await fetch(
`https://---/test.php?id=${product.productid}/`
);
const data = await response.json();
return {
...product,
price: data[0].price
};
})
).then((products) => setProducts(products));
}, [item]);
return (
<div>
{products.map((product) => {
return (
<View key={product.id}>
<Text
style={{
fontSize: FONTS.body3,
paddingLeft: 10
}}
>
{product.name}
{product.price}
</Text>
</View>
);
})}
</div>
);
};