React Hook - useEffect 相同的代码但有多种行为

React Hook - useEffect same code but severals behaviors

我是 React Hook 的新手,我遵循了几个教程,但恐怕我并不了解所有内容。

我有两个代码几乎相同但行为不同的组件,我不明白为什么。

第一个组件代码:

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;

第二部分:

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;

在我的控制台日志中,我发现了这个:

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
.........

我不明白为什么我的组件“so5Games”一遍又一遍地重新渲染,而 so5Fixture 组件只更新 2 两次(这是我尝试的,因为首先用 0 调用 API,然后用实际参数) ?

你能帮我理解一下吗?

非常感谢!

SO5Games re-renders 无限期因为状态变量是一个数组,记住 [0, 1] === [0, 1] 会 return false (因为有两个不同的对象) ,而 0 === 0 将 return true

基本上我会像这样重写你的组件:

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;