簡體   English   中英

我想知道為什么當我使用 useEffect 在第一次渲染時填充它時,我的 useEffect 數據在第一次渲染時是空的

[英]I am wondering why my useEffect data is empty on first render when I populate it on first render using useEffect

我正在使用 REST 國家/地區 API 創建一個應用程序,我使用 useEffect 掛鈎在第一次渲染上調用 API 並使用我需要的數據填充我的 useState 數組。 當我嘗試在組件的返回語句中訪問此數據時,它讀取為未定義。 我什至嘗試添加一個三元運算符來首先檢查數據是否為空,如果不是 output 它,但它仍然讀取未定義但如果我注釋掉代碼並刷新頁面,數據將被填充,然后可以取消注釋代碼以顯示如果我再次刷新頁面,數據讀取為未定義。 我對為什么會發生這種情況感到非常困惑,因此非常感謝任何幫助。

我的.js文件:

const CountryInfo = () => {
    const [data, setData] = useState([{}])
    let countryName = window.location.pathname;

    countryName = countryName.replace('/', '');
    countryName = countryName.split('%20');
    countryName = countryName.join(' ');
    console.log(countryName)

    useEffect(() => {
       axios.get(`https://restcountries.com/v3.1/name/${countryName}`).then(response => {
        console.log(response);
        setData([{
            name: countryName,
            image: response.data[0].flags.png,
            nativeName: response.data[0].name.nativeName.nld,
            population: response.data[0].population,
            region: response.data[0].region,
            subRegion: response.data[0].subregion,
            capital: response.data[0].capital[0],
            borderCountries: response.data[0].borders,
            topLevelDomain: response.data[0].tld[0],
            currencies: response.data[0].currencies,
            languages: response.data[0].languages,
        }])
       }) 
    },[])

    console.log(data)

    return(
        <div className='country-info-content'>
            <Link to='/' className='info-button'>
                <button className='button-info'>BACK</button>
            </Link>
            <div className='data-info'>
                <img src={data[0].image} className='flag-img'/>
                <div className='country-name'>
                    <span className='name'>{data[0].name}</span>
                    <div className='info-description'>
                        <div>
                            <div>
                                <span>Native Name:</span> {data[0].nativeName.common}
                            </div>
                        {/* {data?
                            <div>
                                <div>
                                <span className='title'>Native Name:</span> {data.nativeName.common}
                                </div>
                                <div>
                                    <span className='title'>Population:</span> {data.population.toLocaleString(undefined)}
                                </div>
                                <div>
                                    <span className='title'>Region:</span> {data.region}
                                </div>
                                <div>
                                    <span className='title'>Sub Region:</span> {data.subRegion}
                                </div>
                                <div>
                                    <span className='title'>Capital:</span> {data.capital}
                                </div> 
                            </div>:null} */}
                            {/* {data ?
                                <div>
                                    <span>Native Name: </span>{data[0].nativeName.common}
                                </div>: null
                            } */}
                        </div>
                        <div className='right-info'>
                            <div>
                                <span className='title'>Top Level Domain:</span> {data.topLevelDomain}
                            </div>
                            <div>
                                <span className='title'>Currency:</span> {data.topLevelDomain}
                            </div>
                            <div>
                                <span className='title'>Languages:</span> {data.topLevelDomain}
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    )
}

export default CountryInfo;

輸出到網絡

useEffect將在您的頁面第一次呈現后觸發,這就是組件第一次呈現時未定義數據的原因。

您需要處理它,並且三元運算符是一種常見做法:

return data ? <div>...</div> : null;

或者

return data ? <div>...</div> : <div>Loading...</div>;

更新:錯誤消息是通過讀取未定義的common屬性觸發的。 你這樣做的唯一地方是

data[0].nativeName.common

這意味着data[0]存在,但nativeName未定義。 nativeName存儲response.data[0].name.nativeName.nld,的值。 您應該仔細檢查從 API 返回的數據是否具有預期的格式並且是否設置了response.data[0].name.nativeName.nld

UPDATE2 :就像 Zeno 在評論中注意到的那樣, data的默認值是[{}] ,並且在三元運算符中始終評估為true

為什么在獲取數據之前不設置默認undefined

還要確保將結果稱為data[0] ,因為這是您存儲響應的位置。 或者通過執行以下操作來簡化您的代碼:

setData({
            name: countryName,
            image: response.data[0].flags.png,
            nativeName: response.data[0].name.nativeName.nld,
            population: response.data[0].population,
            region: response.data[0].region,
            subRegion: response.data[0].subregion,
            capital: response.data[0].capital[0],
            borderCountries: response.data[0].borders,
            topLevelDomain: response.data[0].tld[0],
            currencies: response.data[0].currencies,
            languages: response.data[0].languages,
        })

無需在其中存儲數組

您有數據映射錯誤。 嘗試在數據數組中設置本機名稱時,您的數據設置不正確。

你有:

setData([
{
    ...
    nativeName: response.data[0].name.nativeName.nld,
    ...
  }
]);

並返回

                            <div>
                            <span className='title'>Native Name:</span> {data.nativeName.common}
                            </div>

但是 api 返回的數據結構看起來不同,例如:

data: Array(12)
  0: Object
    name: Object
      common: "Eswatini"
      official: "Kingdom of Eswatini"
      nativeName: Object
        eng: Object
        ssw: Object

改為:

setData([
{
    ...
    nativeName: response.data[0].name.common,
    ...
  }
]);

              <div>
                <span>Native Name:</span> {data[0].nativeName}
              </div>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM