简体   繁体   English

无限循环重新渲染反应

[英]Infinite loop rerender react

I have faced the problem of infinite rerender after checkColor is true I setIsCorrect to true and let the child component call handleCorrectAnswer to setIsCorrect to false after resetting the Clock Why I got an infinite loop? checkColor为true后我遇到了无限重新渲染的问题我将setIsCorrect设置为true并让子组件在重置时钟后调用handleCorrectAnswer将setIsCorrect设置为false 为什么我得到一个无限循环?

This is main component on update function I receive data from firebase and when the data in firebase match the current color that I generated I want to reset clock这是更新功能的主要组件我从firebase接收数据,当firebase中的数据与我生成的当前颜色匹配时,我想重置时钟

import { Typography } from '@mui/material';
import React, { useEffect, useState } from 'react';
import CountdownTimer from './CountdownTimer';
import ColorBox from './ColorBox';
import app from '../utils/firebase';
import { getDatabase, ref, onValue } from 'firebase/database';

function genColor() {
    const r = Math.floor(Math.random() * 256);
    const g = Math.floor(Math.random() * 256);
    const b = Math.floor(Math.random() * 256);

    return { r, g, b };
}

function checkColor(color1, color2) {
    const { r: r1, g: g1, b: b1 } = color1;
    const { r: r2, g: g2, b: b2 } = color2;
    const diffR = Math.abs(r1 - r2);
    const diffG = Math.abs(g1 - g2);
    const diffB = Math.abs(b1 - b2);
    return diffR < 25 && diffG < 25 && diffB < 25;
}

export default function Game() {
    const [isCorrect, setIsCorrect] = useState(false);
    const [colorFromUser, setColorFromUser] = useState({ r: 0, g: 0, b: 0 });
    const [gameColor, setGameColor] = useState({ r: 300, g: 300, b: 300 });
    const [timestamp, setTimestamp] = useState(0);

    if (checkColor(colorFromUser, gameColor)) {
        setIsCorrect(true);
    }

    function handleCorrectAnswer() {
        setIsCorrect(false);
        console.log('correct');
        const newColor = genColor();
        setGameColor((prevState) => {
            return { ...prevState, ...newColor };
        });
    }

    function update() {
        var userId = 'XJI27hbv5eVmvEXTaCJTQnhZ33C2';
        const dbRef = ref(getDatabase(app));

        onValue(dbRef, function(snapshot) {
            const data = snapshot.val().UsersData[userId].readings;

            const dataColor = data.data.split(' ');
            console.log(dataColor);
            setColorFromUser((prevState) => ({
                ...prevState,
                r: Number(dataColor[0]),
                g: Number(dataColor[1]),
                b: Number(dataColor[2]),
            }));
            setTimestamp(data.timestamp);
        });
    }

    useEffect(() => {
        update();
        handleCorrectAnswer();
    }, []);

    return (
        <div className="main-container">
            <div className="main">
                <div className="current-color">
                    <ColorBox
                        color={`rgb(${gameColor.r}, ${gameColor.g}, ${gameColor.b})`}
                    />
                    <CountdownTimer
                        isCorrect={isCorrect}
                        handleCorrectAnswer={handleCorrectAnswer}
                        setIsCorrect={setIsCorrect}
                    />
                </div>
            </div>
        </div>
    );
}

This is clock component that I want to reset in onComplete method这是我想在 onComplete 方法中重置的时钟组件

export default function CountdownTimer(props) {
    const [key, setKey] = useState(0);
    return (
        <div className="timer">
            <CountdownCircleTimer
                key={key}
                onComplete={() => {
                    console.log('done');
                    return { shouldRepeat: true, delay: 2 };
                }}
                onUpdate={(remainingTime) => {
                    if (props.isCorrect) {
                        setKey((prevKey) => prevKey + 1);
                        console.log('update');
                        props.handleCorrectAnswer();
                    }
                    console.log(remainingTime);
                }}
                size={130}
                isPlaying
                duration={60}
                colors="#C18FEE"
            >
                {({ remainingTime, color }) => (
                    <Typography sx={{ color, fontSize: 40 }}>
                        {remainingTime}
                    </Typography>
                )}
            </CountdownCircleTimer>

        </div>
    );
}

Move this to useEffect:将此移动到 useEffect:

if (checkColor(colorFromUser, gameColor)) {
        setIsCorrect(true);
    }

It should be它应该是

import { Typography } from '@mui/material';
import React, { useEffect, useState } from 'react';
import CountdownTimer from './CountdownTimer';
import ColorBox from './ColorBox';
import app from '../utils/firebase';
import { getDatabase, ref, onValue } from 'firebase/database';

function genColor() {
    const r = Math.floor(Math.random() * 256);
    const g = Math.floor(Math.random() * 256);
    const b = Math.floor(Math.random() * 256);

    return { r, g, b };
}

function checkColor(color1, color2) {
    const { r: r1, g: g1, b: b1 } = color1;
    const { r: r2, g: g2, b: b2 } = color2;
    const diffR = Math.abs(r1 - r2);
    const diffG = Math.abs(g1 - g2);
    const diffB = Math.abs(b1 - b2);
    return diffR < 25 && diffG < 25 && diffB < 25;
}

export default function Game() {
    const [isCorrect, setIsCorrect] = useState(false);
    const [colorFromUser, setColorFromUser] = useState({ r: 0, g: 0, b: 0 });
    const [gameColor, setGameColor] = useState({ r: 300, g: 300, b: 300 });
    const [timestamp, setTimestamp] = useState(0);

    

    function handleCorrectAnswer() {
        setIsCorrect(false);
        console.log('correct');
        const newColor = genColor();
        setGameColor((prevState) => {
            return { ...prevState, ...newColor };
        });
    }

    function update() {
        var userId = 'XJI27hbv5eVmvEXTaCJTQnhZ33C2';
        const dbRef = ref(getDatabase(app));

        onValue(dbRef, function(snapshot) {
            const data = snapshot.val().UsersData[userId].readings;

            const dataColor = data.data.split(' ');
            console.log(dataColor);
            setColorFromUser((prevState) => ({
                ...prevState,
                r: Number(dataColor[0]),
                g: Number(dataColor[1]),
                b: Number(dataColor[2]),
            }));
            setTimestamp(data.timestamp);
        });
    }

    useEffect(() => {

         if (checkColor(colorFromUser, gameColor)) {
        setIsCorrect(true);
    }
        update();
        handleCorrectAnswer();
    }, []);

    return (
        <div className="main-container">
            <div className="main">
                <div className="current-color">
                    <ColorBox
                        color={`rgb(${gameColor.r}, ${gameColor.g}, ${gameColor.b})`}
                    />
                    <CountdownTimer
                        isCorrect={isCorrect}
                        handleCorrectAnswer={handleCorrectAnswer}
                        setIsCorrect={setIsCorrect}
                    />
                </div>
            </div>
        </div>
    );
}

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

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