【问题标题】:How to return a value from async function used inside .map function in React?如何从 React 中 .map 函数内部使用的异步函数返回一个值?
【发布时间】:2021-07-11 15:20:36
【问题描述】:

所以我用谷歌搜索了一下,我发现异步函数返回承诺,在这个异步函数之后使用 .then() 可以访问结果值。这就是它无法正确渲染的原因。我的问题是:如何从 .map 中的这个 Promise 呈现实际值?

const storageRef = firebase.storage().ref("/assets")

const [productList, setProductList] = useState([])

useEffect(() => {
    Axios.get("http://localhost:3001/product/get").then((response) => {
        setProductList(response.data)
    })  
}, [])

const getImage = async (bannerImage) => {
    const url = await storageRef.child(bannerImage).getDownloadURL();
    return url;   
}

映射函数(返回Error: Objects are not valid as a React child (found: [object Promise])):

{productList.map((val) => {
    return (
        <div key={val.id} className="product">
            <div className="item">
                <h1>Product title: {val.title}</h1>
                <h2>Price: {val.price}</h2>
                <h2>Quantity: {val.quantity}</h2>
                <h2>IMG: {getImage(val.bannerImage)}</h2>
            </div>
        </div>
    ) 
})}

【问题讨论】:

  • 渲染productList的方式相同。它也是异步的。但是......我建议找到一种比在循环中发送 ajax 请求更好的方法来获取数据。理想情况下将其作为产品数据的一部分返回,或者一次请求所有图像。
  • 问题出在你的getImage 函数上。它返回一个 Promise,而您正在尝试渲染它。解决方案是在加载后对productList 执行相同的操作。比如:const images = await Promise.all(response.data.map(val =&gt; storageRef.child(val.bannerImage).getDownloadURL()));
  • 您是否有理由不想在.then 回调中为Axios.get 调用useEffect 调用getImage
  • 因为我想为 productList 中的每个产品对象渲染每个图像。每个产品都有 bannerImage 属性,并且该属性必须与 url 匹配。对不起,如果这是一个愚蠢的问题。这是一个学校项目,所以我必须这样做,尽管我是新手。而且我只有 3 个月的时间来学习 React 并创建这个电子商务网站项目。
  • Because I want to render each image for each product object from productList 这并不意味着你不能按照 Jared 的建议去做。你仍然必须这样做。再说一遍:这样做的方法是在加载产品列表并将它们放入状态数组后立即从数据库加载图像 URL。现在您可以使用该数组来显示图像。

标签: javascript mysql reactjs firebase-storage


【解决方案1】:

因此,正如@Chris-G 所建议的那样,您可以在.then 中映射response.data,并链接在Axios.get 上以继续获取图像 URL,并构建渲染所需的对象.示例:

const storageRef = firebase.storage().ref("/assets");
const getImage = async (bannerImage) => {
    const url = await storageRef.child(bannerImage).getDownloadURL();
    return url;   
}

const [productList, setProductList] = useState([])

useEffect(() => {
    Axios.get("http://localhost:3001/product/get").then((response) => {
        Promise.all(response.data.map(async (rawProduct) => {
            const renderReadyProduct = {
                title: rawProduct.title,
                price: rawProduct.price,
                quantity: rawProduct.quantity
            };
            renderReadyProduct.img = await getImage(rawProduct.bannerImage);
            return renderReadyProduct;
        })).then((newProductList) => setProductList(newProductList));
    });
}, [])

【讨论】:

  • 谢谢!我无法访问val.bannerImage,因为在所有这些代码之后,我正在 return() 中初始化 val 变量。更具体地说:我有功能组件,然后我将您的代码包装在其中,然后在您的代码之后,我有 return(),在这个 return 中,我有上面提到的地图,它在 div 中呈现产品。
  • 非常感谢。你解决了我八小时的难题:D
猜你喜欢
  • 2020-12-08
  • 1970-01-01
  • 2018-01-03
  • 2016-08-08
  • 1970-01-01
  • 2014-05-27
  • 2018-07-09
相关资源
最近更新 更多