简体   繁体   中英

React How to solve the problem of undefined return value of async await function

If you run the following code {i('salon-id')} becomes undefined.

I think the reason is that jsx is loaded before getting the information from the i function of async await, but I don't know how to solve it.

I would like to know how to display the information in jsx after reading the information from async await.

I am using firebase v9.

import React, { useState, useEffect } from "react"
import { Link } from 'react-router-dom';
// firebase関連
import { db } from "../../../firebaseConfig"
import {
    collection,
    orderBy,
    query,
    getDocs,
    limit,
    where
} from 'firebase/firestore'
import 'firebase/compat/auth'
// 画像
import MainTopImg from '../../../images/imecon-personal-color.jpeg'
import '../../../styles/Top.scss'

const MobileContents = () => {   
    const [newSalonList, setNewSalonList] = useState([])

    useEffect(() => {        
        (async () => {
            const salons = query(collection(db, "salon"), orderBy("createAt", "desc"), limit(5));
            const querySnapshot = await getDocs(salons);
            let salonList = [];
            await querySnapshot.forEach((doc) => {
                salonList = [...salonList, {
                    salonId: doc._document.data.value.mapValue.fields.salonId.stringValue,
                    salonName: doc._document.data.value.mapValue.fields.salonName.stringValue,
                    salonNameKana: Boolean(doc._document.data.value.mapValue.fields.salonNameKana) ? '【' + doc._document.data.value.mapValue.fields.salonNameKana.stringValue  + '】': '',
                    address: Boolean(doc._document.data.value.mapValue.fields.access) ? doc._document.data.value.mapValue.fields.access.stringValue: '',
                    mainImageUrl: doc._document.data.value.mapValue.fields.mainImageUrl.stringValue,
                    menuTitle: doc._document.data.value.mapValue.fields.mainImageUrl.stringValue,
                    price: ''
                }]
            })
            setNewSalonList(salonList)
        })();
    }, [])

    function i (salonId) {
        (async () => {
            try {
                const q = query(collection(db, "salon", salonId, "menu"), where("top", "==", true));
                const querySnapshot2 = await getDocs(q);
                await querySnapshot2.forEach((doc) => {
                    // doc.data() is never undefined for query doc snapshots
                    console.log(doc.data().menuTitle);
                    return(doc.data().menuTitle)
                });
            } catch(err) {
                console.log(err)
                return 'err'
            }
        })()
    }

    return (
        <div>
            <img src={MainTopImg} alt="mainTopImg" className="mainImg"/>
            <Link to="/mypage">マイページ</Link>
            <div className="form">
                <form action="/search" method="GET" className="search_container">
                    <input type="text" name="query1" placeholder="サロン名・エリア・メニューなどから検索" />
                    <input type="submit" /> 
                </form>
            </div>
            <div>
                <div className="newSalonTitleParent">
                    <p className="newSalonTitle">| 新着のサロン</p>
                </div>
                {newSalonList.map((data) => {
                    console.log(i('salon-id'))
                    return (
                        <li key={data.salonId}>
                            <img src={data.mainImageUrl} alt="" />
                            <Link to={'/salon/' + data.salonId}>
                                <p>{data.salonName}{data.salonNameKana}</p>
                            </Link>
                            <p>{data.address}</p>
                            <div>{}</div>
                        </li>
                    )
                })}
                <div>{i('salon-id')}</div>
            </div>
        </div>
    );
}

export default MobileContents;

I would suggest go through the react-query library, you can use useQuery hook to fetch the data from db, while rendering you have to only look for loading flag, once the data is fetched form db, it will get render in ui

You get undefined from {i('salon-id')} because the forEach function returns undefined and not what you expects to return.

forEach() executes the callbackFn function once for each array element; unlike map() or reduce() it always returns the value undefined and is not chainable. The typical use case is to execute side effects at the end of a chain.

as explained in official MDN docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM