简体   繁体   English

卡在 promise 并返回 null

[英]stuck in a promise and returns null

Hi im trying so set String to data i have fetched.嗨,我正在尝试将String设置为我获取的数据。 The problem is it is stuck in a promise and returns null before the state can be updated.问题是它卡在 promise 中并在 state 可以更新之前返回 null。 I am lost as to how I can make sure the data is there before it accesses the data.我不知道如何在数据访问数据之前确保数据存在。 Any help would be much appreciated.任何帮助将非常感激。 thanks谢谢

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);
    const [string,setString] = useState(null);


    

    useEffect( () => {
        async function fetchData(){
        const res = await fetch(`https://restcountries.com/v3.1/name/${country}`)
        const data = await res.json()
        setDetails(data)  
        setString(Object.keys(data.currencies).toString())
    }
        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}</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}</p>
                        <p className='ml-7 mt-8 text-sm font-light'><span className='text-sm font-semibold'>Top Level Domain: </span>{data.tld}</p>
                        <p className='ml-7 mt-2 text-sm font-light'><span className='text-sm font-semibold'>Currencies: </span>{data.currencies[string].name}</p>
                        <p className='ml-7 mt-2 text-sm font-light'><span className='text-sm font-semibold'>Languages: </span></p>
                        <h2 className='font-semibold text-base ml-7 mt-8'>Border Countries:</h2>
                        <button className='border-2 shadow-md rounded cursor-pointer w-24 h-6 ml-7 mt-4 text-xs font-light'>{data.borders}</button>

                    </section>
                </div>)}
            </div>
        </main>
        
    );
}

export default Country;

Your two set states run independently so you have no guarantee about which finished first, adding in a check for both will make sure you have no nulls.您的两个设置状态独立运行,因此您无法保证哪个先完成,添加对两者的检查将确保您没有空值。

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);
    const [string,setString] = useState(null);


    

    useEffect( () => {
        async function fetchData(){
        const res = await fetch(`https://restcountries.com/v3.1/name/${country}`)
        const data = await res.json()
        setDetails(data)  
        setString(Object.keys(data.currencies).toString())
    }
        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 && string && 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}</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}</p>
                        <p className='ml-7 mt-8 text-sm font-light'><span className='text-sm font-semibold'>Top Level Domain: </span>{data.tld}</p>
                        <p className='ml-7 mt-2 text-sm font-light'><span className='text-sm font-semibold'>Currencies: </span>{data.currencies[string].name}</p>
                        <p className='ml-7 mt-2 text-sm font-light'><span className='text-sm font-semibold'>Languages: </span></p>
                        <h2 className='font-semibold text-base ml-7 mt-8'>Border Countries:</h2>
                        <button className='border-2 shadow-md rounded cursor-pointer w-24 h-6 ml-7 mt-4 text-xs font-light'>{data.borders}</button>

                    </section>
                </div>)}
            </div>
        </main>
        
    );
}

The problem seems to be with the currency key string accessing code in useEffect().问题似乎与货币密钥字符串访问 useEffect() 中的代码有关。 Based on the data returned from the API, the currencies information can be accessed with below code.根据从 API 返回的数据,可以使用以下代码访问货币信息。 This works good when only single currency is returned for a country.当一个国家只返回单一货币时,这很有效。

    // setString(Object.keys(data.currencies).toString());
    setString(Object.keys(data[0] && data[0].currencies || {}).toString());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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