reactjs - setState 的问题和太多的重新渲染

标签 reactjs

我在react中使用功能组件。

我有一个游戏组件,它是显示父组件。它有一个名为 Main 的父级,其中包含 Game 的所有函数和变量。当我尝试设置特定变量的状态时,我遇到了太多重新渲染错误。它由 startGame() 方法触发,该方法调用 API,然后使用数据调用另一个函数来设置 4-6 个变量。我可以毫无问题地在 6 个变量上使用 setState,但每当我尝试“setPlayers”时,它都会产生太多的重新渲染错误。

我不明白为什么这个变量很特殊。我通过将 Players 切换到常规变量来暂时解决了这个问题,此时我可以毫无问题地为其赋值,但我想了解发生了什么。

Main.jsx

    let [isBet, setIsBet] = useState(false);
    let [betOptions, setBetOptions] = useState();
    let [hasStarted, setHasStarted] = useState(false);
    let [id, setId] = useState(0);
    const [players, setPlayers] = useState([]) ////The variable that causes the issue
        // let players = []; //doesn't cause issue
    const [cards, setCards] = useState([])
    const [hand, setHand] = useState([])
    const [betLog, setBetLog] = useState([])
    const [showModal, setShowModal] = useState(false)
    const [errorMessage, setErrorMessage] = useState("")

    const setVariables= data => {
        setHasStarted(true)
        setId(data.gameId)
        setPlayers(data.users) ///// !!!!! causes too many re-renders bug
        // players = data.users // if I use this line instead of the above, the function works
        // setPlayers([...data.users])
        setHand(data.hand)
        console.log("BET OPTIONS", data.betOptions)
        if (data.betOptions.name === username){
            setBet(data.betOptions)
        } 
    }

    const setBet = betOptions => {
        setBetOptions(betOptions)
        console.log("Your Bet Options are", betOptions)
        console.log(betOptions.betAmount)
        setIsBet(true)
    }

    const startGame = async (state) => {
        let body = { username, 
            displayName : state.displayName,
            numberOfPlayers : state.numberOfPlayers,
            fillWithComputerPlayers: state.fillWithComputerPlayers,
            isCustom: state.isCustom,
            bigBlind: state.bigBlind
         }
        try {
            const data = await Service.startGame(body);
            console.log("response body", data.data)
            setVariables(data.data);
        } catch (err){
            console.error(err)
            setErrorMessage(err.message)
            setShowModal(true)
            setTimeout(function(){
                setShowModal(false)
            }, (2500))
        }
    }

所有变量都被子组件 Game 使用。我没有在“玩家”上使用任何 UseEffect,但它是我使用 .map() 的唯一相关变量之一(注意-我也在映射“卡片”并以完全相同的方式设置它,但在不同的功能)。这是“players”变量的唯一用途。

游戏.jsx

    let id = props.id;
    // let [players] = useState(props.players)
    let players = props.players
    let hand = props.hand;
    let betOptions = props.betOptions;
    let cards = props.cards
    const [money, setMoney] = useState(0)
    const username = props.username;

return ( 
        <div id="background">

         /// Lots of other components not relevant to the question
                {props.hasStarted ? 
                    <div> 
                        {players.map((v, i) => {    /////// !! only use of players
                            if (v.username !== username){
                                return (
                                    <PlayerInfo name={v.username} money={v.money} key={i} class="info" />

                                )
                            } else {
                                setMoney(v.money)
                            }                           
                        })}
                        {cards.length > 0 && cards.map((v, i) => {
                            return (
                                <img className="cards" key={i} src={process.env.PUBLIC_URL + '/pics/PNG/' + v.image} alt={v.image} />
                            )
                        })}
                         <div id="my">
                            <MyInfo name={username} money={money} hand={hand} class="info" /> 
                        </div>      
                    </div>                   
                :
                    <SettingsForm startGame={props.startGame} username={username} />
                }
            
            </div>

            
            <Log betLog={props.betLog} />

        </div>

PlayerInfo.jsx

import "./Info.css"

const PlayerInfo = props => {

    return ( 
        <div className="info">
           <h4>{props.name}</h4> {props.money}$
            <div>          
               <img className="cards" src={process.env.PUBLIC_URL + '/pics/PNG/red_back.png'} alt="card" />
               <img className="cards" src={process.env.PUBLIC_URL + '/pics/PNG/red_back.png'} alt="card" />
            </div>                    
        </div>
     );
}
 
export default PlayerInfo;

最佳答案

为什么不将尽可能多的有意义的对象转变为 1 个或多个对象?
setState 不同,它会导致 5 次单独的重新渲染,
将状态设置为包含所有这 5 个部分的 1 个对象只会导致 1 次重新渲染。

关于reactjs - setState 的问题和太多的重新渲染,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69065541/

相关文章:

javascript - 关于 webapp 架构和 ReactJs 的建议

javascript - 在 ReactJs 中使用 GoJs

javascript - 有多个模块的名称仅在外壳 React 上不同

javascript - 无法删除 react 数据表组件中的白色标题

javascript - 如何重置列表中选定的项目?

Javascript检查对象数组中是否存在字符串

node.js - apollo useLazyQuery 绕过缓存

javascript - 引用错误: document is not defined Jest React Testing Library

javascript - 有没有办法遍历 React 构建的树?

javascript - 如何通过javascript插入对象?