You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中Promise阻塞致状态未更新返回null的问题求助

解决方案

你的问题核心是React状态更新的异步特性导致的——setDetails和setString都是异步操作,当组件因details更新触发重渲染时,string状态可能还未完成更新,此时访问data.currencies[string]就会因string为null而抛出错误。

优化方案:移除冗余的string状态

string是从接口返回的data.currencies派生出来的临时值,不需要单独存入状态。直接在渲染阶段根据当前循环的data计算即可,完全避免异步状态更新带来的不一致问题,同时简化代码逻辑:

import React, { useState, useEffect } from 'react'
import { useParams } from 'react-router-dom'
import Header from '../components/header.js'
import { BsArrowLeft } from 'react-icons/bs'

const Country = () => {
    const { countryName } = useParams();
    const [country, setCountry] = useState(countryName);
    const [details, setDetails] = useState(null);
    // 移除冗余的string状态

    useEffect(() => {
        async function fetchData() {
            const res = await fetch(`https://restcountries.com/v3.1/name/${country}`)
            const data = await res.json()
            setDetails(data)  
            // 移除setString操作
        }
        fetchData() 
    }, [country])

    return (
        <main className='h-screen flex flex-col items-center w-full overflow-x-hidden bg-verylightgrey dark:bg-verydarkblue overflow-scroll'>
            <div className='flex flex-col items-center w-full'>
                <Header/>
                <section className='flex justify-items-start w-full'>
                    <button className='border-2 ml-7 mt-10 mb-16 rounded shadow-md hover:shadow-inner cursor-pointer w-3/12 flex flex-row items-center justify-center text-sm font-light'><span className='mr-2 text-lg'><BsArrowLeft/></span>Back</button>
                </section>
                {details && details.map((data, index) => 
                <div className='w-full flex flex-col items-center' key={index}>
                    <img className='rounded mb-11 w-10/12 h-6/6' alt={data.name.common} src={data.flags.png}/>
                    <section className='flex flex-col w-full '>
                        <h1 className='font-extrabold text-xl ml-7'>{data.name.common}</h1>
                        <p className='ml-7 mt-4 text-sm font-light'><span className='text-sm font-semibold'>Official Name: </span>{data.name.official}</p>
                        <p className='ml-7 mt-2 text-sm font-light'><span className='text-sm font-semibold'>Population: </span>{data.population.toLocaleString()}</p>
                        <p className='ml-7 mt-2 text-sm font-light'><span className='text-sm font-semibold'>Region: </span>{data.region}</p>
                        <p className='ml-7 mt-2 text-sm font-light'><span className='text-sm font-semibold'>Sub Region: </span>{data.subregion}</p>
                        <p className='ml-7 mt-2 text-sm font-light'><span className='text-sm font-semibold'>Capital: </span>{data.capital?.join(', ')}</p>
                        <p className='ml-7 mt-8 text-sm font-light'><span className='text-sm font-semibold'>Top Level Domain: </span>{data.tld.join(', ')}</p>
                        {/* 直接从当前data中提取货币名称,支持多货币情况 */}
                        <p className='ml-7 mt-2 text-sm font-light'><span className='text-sm font-semibold'>Currencies: </span>
                            {Object.values(data.currencies).map(curr => curr.name).join(', ')}
                        </p>
                        {/* 处理语言数组 */}
                        <p className='ml-7 mt-2 text-sm font-light'><span className='text-sm font-semibold'>Languages: </span>
                            {Object.values(data.languages).join(', ')}
                        </p>
                        <h2 className='font-semibold text-base ml-7 mt-8'>Border Countries:</h2>
                        {/* 遍历边境国家数组,渲染多个按钮 */}
                        <div className='flex flex-wrap ml-7 mt-4 gap-2'>
                            {data.borders?.map(border => (
                                <button key={border} className='border-2 shadow-md rounded cursor-pointer w-24 h-6 text-xs font-light'>{border}</button>
                            ))}
                        </div>
                    </section>
                </div>)}
            </div>
        </main>
    );
}

export default Country;

额外优化点说明

  1. 对population使用toLocaleString()格式化数字,提升可读性
  2. 对capital、borders等可能为数组的字段,使用可选链?.避免空值报错,并通过join(', ')或map渲染多个值
  3. 直接提取data.currencies和data.languages的value值,无需依赖额外状态,逻辑更直接

内容的提问来源于stack exchange,提问作者Curtis Sanderson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 03:15:36