无限循环重新渲染反应
Infinite loop rerender react
我遇到checkColor为true后无限重渲染的问题
我在重置时钟后将 setIsCorrect 设置为 true 并让子组件调用 handleCorrectAnswer 将 setIsCorrect 设置为 false 为什么我得到一个无限循环?
这是主要成分
在更新功能上,我从 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>
);
}
这是我想在 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>
);
}
移动这个使用效果:
if (checkColor(colorFromUser, gameColor)) {
setIsCorrect(true);
}
应该是
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>
);
}
我遇到checkColor为true后无限重渲染的问题 我在重置时钟后将 setIsCorrect 设置为 true 并让子组件调用 handleCorrectAnswer 将 setIsCorrect 设置为 false 为什么我得到一个无限循环?
这是主要成分 在更新功能上,我从 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>
);
}
这是我想在 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>
);
}
移动这个使用效果:
if (checkColor(colorFromUser, gameColor)) {
setIsCorrect(true);
}
应该是
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>
);
}