Home > Enterprise >  React Hook - useEffect same code but severals behaviors
React Hook - useEffect same code but severals behaviors

Time:05-06

I'm new to React Hook and I follow severals tutorials but I'm afraid I'm not understand everything.

I have two components with pretty much the same code but two differents behaviors and I don't understand why.

First component code :

function SO5Fixture(props) {

    const [gameweek, setGameWeek] = useState(0)

    const previousGWClick = () => {
        console.log("previousGW from "   gameweek)
        setGameWeek(gameweek - 1)        
    }

    const nextGWClick = () => {
        console.log("nextGW from "   gameweek)
        setGameWeek(gameweek   1)
    }

    useEffect(() => {
        console.log("so5fixture useEffect")
        getGameWeekInfos()
      }, [gameweek])

    const getGameWeekInfos = async() => {
        console.log("getGameWeekInfos")
        var so5Fixture = await APISorare.getSo5Fixture(gameweek)
        setGameWeek(so5Fixture['data']['so5fixture_game_week'])
    }

    return (
        <div>
            <Container>
            ...
            </Container>
        </div>
    );
}
export default SO5Fixture;

Second component :

import React, { useEffect, useState } from "react";
import { Container, Row, Col, Button, ButtonGroup, Card, Alert } from "react-bootstrap";
import { LinkContainer } from 'react-router-bootstrap'
import APISorare from "../../utils/APISorare";


function SO5Games(props) {

    const [games, setGames] = useState([])

    useEffect(() => {
        console.log("so5Games useEffect")
        getGames()
      }, [games]) 

    const getGames = async() => {
        console.log("getGames : "   props.gameWeek)
        var so5Games = await APISorare.getSo5Games(props.gameWeek)
        setGames(so5Games['data'])
    }

    return (
        <div>
            {
                games.map( (game, idx) => (
                    <Alert key={idx} variant="secondary">
                        <Row>
                            <Col md={4}>{game['game_date']}</Col>
                            <Col md={8}>{game['home_team_name']} {game['home_team_score']}-{game['away_team_score']} {game['away_team_name']}</Col>
                        </Row>
                    </Alert>
                ))
            }
        </div>
    );
}

export default SO5Games;

In my console log, I find this :

so5fixture useEffect
SO5Fixture.js:28 getGameWeekInfos
APISorare.js:24 APISorare : getSo5Fixture
SO5Games.js:12 so5Games useEffect
SO5Games.js:17 getGames : 262
APISorare.js:33 APISorare : getSo5Games
SO5Fixture.js:23 so5fixture useEffect
SO5Fixture.js:28 getGameWeekInfos
APISorare.js:24 APISorare : getSo5Fixture
SO5Games.js:12 so5Games useEffect
SO5Games.js:17 getGames : 262
APISorare.js:33 APISorare : getSo5Games
SO5Games.js:12 so5Games useEffect
SO5Games.js:17 getGames : 262
APISorare.js:33 APISorare : getSo5Games
SO5Games.js:12 so5Games useEffect
SO5Games.js:17 getGames : 262
.........

I don't understand why my component "so5Games" re-render over and over whereas the so5Fixture component update just 2 twice (which is what I attempt because first call API with 0 and then with a real parameter) ?

Could you please help me to understand ?

Thanks a lot !

CodePudding user response:

SO5Games re-renders indefinitely because the state variable is an array, remember that [0, 1] === [0, 1] will return false (because there are two distincts objects), whereas 0 === 0 will return true

Basically I would rewrite your components like this :

function SO5Fixture(props) {
    const [gameweek, setGameWeek] = useState(0)

    const previousGWClick = () => fetchGameWeekInfos(gameweek - 1)        
    const nextGWClick = () => fetchGameWeekInfos(gameweek   1)

    // fetch game week infos on initial render
    useEffect(() => fetchGameWeekInfos(gameweek), [])

    const fetchGameWeekInfos = async (week) => {
        console.log("fetchGameWeekInfos")
        var so5Fixture = await APISorare.getSo5Fixture(week)
        setGameWeek(so5Fixture['data']['so5fixture_game_week'])
    }

    return (
        <div>
            <Container>
            ...
            </Container>
        </div>
    );
}
export default SO5Fixture;
function SO5Games(props) {
    const [games, setGames] = useState([])

    // load the games each time props.gameWeek is updated
    useEffect(() => {
        console.log("so5Games useEffect")
        fetchGames()
    }, [props.gameWeek]) 

    const fetchGames = async () => {
        console.log("getGames : "   props.gameWeek)
        var so5Games = await APISorare.getSo5Games(props.gameWeek)
        setGames(so5Games['data'])
    }

    return (...);
}

export default SO5Games;
  • Related