Home > database >  State in React component not setting data when the browser (tab) is refreshed
State in React component not setting data when the browser (tab) is refreshed

Time:01-11

I have this simple react component that gets data from an API (fetch called in UseEffect), and displays it using HTML. When I refresh the page, all html disappears from the page and it goes blank. What's peculiar is that when I instead make some changes in the code editor and let react autoupdate the page after saving, it displays everything just fine.

Here's the code snippet for the component:

export function AgentCard(props){
    console.log("agentcard function");
    const [agentData,setAgentData] = useState({});

    useEffect(()=> {
        console.log('running useEffect')
        axios.get('https://valorant-api.com/v1/agents/').then(res=>{
            var agentRes;

            for (const agent of res.data['data']){
                if (agent['displayName'] === props.agentName){ agentRes = agent}
            }

            setAgentData(agentRes);

            console.log(agentData)
        })
    },[])

    return(
        <div className='AgentCard'>
            <h2>{agentData['displayName']}</h2> 
            <img src={agentData['displayIcon']}></img>
            <div className='AgentCardBody'>
                <div className='AbilitiesBar'>
                   <img src={agentData['abilities'][0]['displayIcon']} className='AbilitiesIcon'></img>
                    <img src={agentData['abilities'][1]['displayIcon']} className='AbilitiesIcon'></img>
                    <img src={agentData['abilities'][2]['displayIcon']} className='AbilitiesIcon'></img>
                    <img src={agentData['abilities'][3]['displayIcon']} className='AbilitiesIcon'></img>
                </div>
            </div>
        </div>
    )

After some digging and logging, what I found is that when I refresh the page, the state (agentData), is saved to this:

https://imgur.com/a/QzfIdpm

and get the following error in the console:

https://imgur.com/a/H7gLiTQ

But once I make any change to the editor and let react autorefresh, the logs show that the state agentData has the right data object pulled from the API.

Also, this only happens when I have the following part of the code running

<img src={agentData['abilities'][0]['displayIcon']} className='AbilitiesIcon'></img>
<img src={agentData['abilities'][1]['displayIcon']} className='AbilitiesIcon'></img>
<img src={agentData['abilities'][2]['displayIcon']} className='AbilitiesIcon'></img>
<img src={agentData['abilities'][3]['displayIcon']} className='AbilitiesIcon'></img>

Once I comment this out, everything displays correctly even after a browser refresh

I know the way I've posed the question is confusing, but I'm new to front end development and don't really know what I'm supposed to look for here.

CodePudding user response:

Probably because agentData.abilities returns undefined (remember that you have an empty object that is asynchronously populated), but you're trying to access it in your template as if an array is present.

You can solve this easily if you conditionally render those <img> elements when agentData.abilities is not undefined, i.e.:

return(
    <div className='AgentCard'>
        <h2>{agentData['displayName']}</h2> 
        <img src={agentData['displayIcon']}></img>
        <div className='AgentCardBody'>
            {agentData.abilities && (
                <div className='AbilitiesBar'>
                    <img src={agentData.abilities[0].displayIcon} className='AbilitiesIcon' />
                    <img src={agentData.abilities[1].displayIcon} className='AbilitiesIcon' />
                    <img src={agentData.abilities[2].displayIcon} className='AbilitiesIcon' />
                    <img src={agentData.abilities[3].displayIcon} className='AbilitiesIcon' />
                </div>
            )}
        </div>
    </div>
)

Even better: you can simply iterate through the first 4 entries in agentData.abilities to keep your DOM a bit simpler:

return(
    <div className='AgentCard'>
        <h2>{agentData['displayName']}</h2> 
        <img src={agentData['displayIcon']}></img>
        <div className='AgentCardBody'>
            <div className='AbilitiesBar'>
                {agentData.abilities && agentData.abilities.slice(0,4).forEach(ability => (
                    <img src={ability.displayIcon} className='AbilitiesIcon' />
                )}
            </div>
        </div>
    </div>
)

CodePudding user response:

It seems are you missing array brackets.

Try the following:

<img src={agentData[['abilities'][0]['displayIcon']]} className='AbilitiesIcon'></img>

Alternatively (Assuming both abilities and displayIcon are both keys inside an obj), you can target the display icon like such:

<img src={agentData.abilities[0].displayIcon} className='AbilitiesIcon' />
  •  Tags:  
  • Related