繁体   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