useState and if statement causing Error: Too many re-renders. React limits the number of renders to prevent an infinite loop
useState and if statement causing Error: Too many re-renders. React limits the number of renders to prevent an infinite loop
我试图创建的是一个 React 组件,它在 boxToggle 的值为 true 时有条件地呈现,并且在用户单击退出按钮时 returns null。我为实现这一点所做的是创建一个名为 displayUI 的本地 useState,并使用 if 语句将 displayUI 分配给 true 或 false(这可能是问题所在,但我无法确定原因)取决于 boxToggle 道具和 onClick 的内部退出按钮。
但是我在组件内部收到这个错误:
Uncaught Error: Too many re-renders. React limits the number of
renders to prevent an infinite loop.
这里是父组件(我用的是react-three-fiber)
import React, { useRef, useState } from 'react';
import './App.css';
//Packages
import * as THREE from 'three';
import { Canvas, useFrame } from 'react-three-fiber'
import {Box, OrbitControls} from 'drei';
//Components
import Header from './components/Header';
import Homepage from './components/Homepage';
import { Light } from 'three';
//Functions
//Main App Function
function App() {
const [boxToggle, setboxToggle] = useState(false);
return (
<div className="App">
<Header/>
<Homepage boxToggle={boxToggle}/>
<Canvas
colorManagement
camera={{position: [0, 5, 10], fov: 60}}
shadowMap
>
<Lights/>
<RotatingBox
onClick={()=> setboxToggle(true)}
/>
<Floor/>
{/* <OrbitControls/> OrbitControls causes problems with the Raycasting (onClick)*/}
</Canvas>
</div>
);
}
//Scene Lights
const Lights = () => {
return (
<>
<directionalLight
intensity={1.5}
position={[0, 10, 5]}
castShadow
shadow-mapSize-width={1024}
shadow-mapSize-height={1024}
shadow-camera-far={50}
shadow-camera-left={-10}
shadow-camera-right={10}
shadow-camera-top={10}
shadow-camera-bottom={-10}
/>
<ambientLight
intensity={0.3}
/>
</>
)
}
//Meshes
const RotatingBox = ({onClick})=> {
const box = useRef();
const [boxSize, setBoxSize] = useState(false);
useFrame(()=>(
box.current.rotation.y = box.current.rotation.x += 0.01,
console.log(boxSize)
)
)
return (
<>
<Box
args={ boxSize ? [1, 1, 1]: [2, 2, 2]}
ref={box}
castShadow
onClick={onClick}//cant get onClick Working at all, drei or R3F
onPointerOver={onClick= ()=> setBoxSize(true)}
>
<meshStandardMaterial
cast
attach="material"
color='yellow'
/>
</Box>
</>
)
}
const Floor = () => {
return (
<>
<mesh
onClick={()=> console.log("click")}
receiveShadow
rotation={[-Math.PI / 2, 0, 0]}
position={[0, -3, 0]}
>
<planeBufferGeometry attach='geometry' args={[100, 100]}/>
<meshStandardMaterial opacity={1} attach='material'/>
</mesh>
</>
)
}
export default App;
和子主页组件
import React, { useState } from 'react';
import styles from './Homepage.module.css'
const Homepage = ({boxToggle}) => {
const [displayUI, setDisplayUI] = useState(false);
if (boxToggle) {
setDisplayUI(true);
}
if (displayUI === true) {
return (
<div className={styles.container}>
<button onClick={() => setDisplayUI(false)} className="exit">X</button>
<div className={styles.title}>
<h1>Homepage</h1>
</div>
<div className={styles.menu}>
<h3>Option 1</h3>
<h3>Option 2</h3>
<h3>Option 3</h3>
</div>
</div>
)
} else return null
}
export default Homepage
我尝试过其他 Whosebug 答案,但我无法将它们应用到我的答案中。其中大部分与 useEffect 有关,或者缺少箭头函数。这让我感到困惑,我什至不知道从哪里开始,因为我不熟悉 Hooks。谢谢
我认为问题是由您的主页组件引起的。
const Homepage = ({boxToggle}) => {
const [displayUI, setDisplayUI] = useState(false);
//this generate error because it update the state directly when render
/*if (boxToggle) {
setDisplayUI(true);
}*/
//we can fix it by wrap it with a useEffect hook so this effect only trigger when the boxToggle value change
React.useEffect(()=>{
if (boxToggle) {
setDisplayUI(true);
}
}, [boxToggle]) // <--- dependency that trigger the function call
if (displayUI === true) {
return (
<div className={styles.container}>
<button onClick={() => setDisplayUI(false)} className="exit">X</button>
<div className={styles.title}>
<h1>Homepage</h1>
</div>
<div className={styles.menu}>
<h3>Option 1</h3>
<h3>Option 2</h3>
<h3>Option 3</h3>
</div>
</div>
)
} else return null
}
我试图创建的是一个 React 组件,它在 boxToggle 的值为 true 时有条件地呈现,并且在用户单击退出按钮时 returns null。我为实现这一点所做的是创建一个名为 displayUI 的本地 useState,并使用 if 语句将 displayUI 分配给 true 或 false(这可能是问题所在,但我无法确定原因)取决于 boxToggle 道具和 onClick 的内部退出按钮。
但是我在组件内部收到这个错误:
Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
这里是父组件(我用的是react-three-fiber)
import React, { useRef, useState } from 'react';
import './App.css';
//Packages
import * as THREE from 'three';
import { Canvas, useFrame } from 'react-three-fiber'
import {Box, OrbitControls} from 'drei';
//Components
import Header from './components/Header';
import Homepage from './components/Homepage';
import { Light } from 'three';
//Functions
//Main App Function
function App() {
const [boxToggle, setboxToggle] = useState(false);
return (
<div className="App">
<Header/>
<Homepage boxToggle={boxToggle}/>
<Canvas
colorManagement
camera={{position: [0, 5, 10], fov: 60}}
shadowMap
>
<Lights/>
<RotatingBox
onClick={()=> setboxToggle(true)}
/>
<Floor/>
{/* <OrbitControls/> OrbitControls causes problems with the Raycasting (onClick)*/}
</Canvas>
</div>
);
}
//Scene Lights
const Lights = () => {
return (
<>
<directionalLight
intensity={1.5}
position={[0, 10, 5]}
castShadow
shadow-mapSize-width={1024}
shadow-mapSize-height={1024}
shadow-camera-far={50}
shadow-camera-left={-10}
shadow-camera-right={10}
shadow-camera-top={10}
shadow-camera-bottom={-10}
/>
<ambientLight
intensity={0.3}
/>
</>
)
}
//Meshes
const RotatingBox = ({onClick})=> {
const box = useRef();
const [boxSize, setBoxSize] = useState(false);
useFrame(()=>(
box.current.rotation.y = box.current.rotation.x += 0.01,
console.log(boxSize)
)
)
return (
<>
<Box
args={ boxSize ? [1, 1, 1]: [2, 2, 2]}
ref={box}
castShadow
onClick={onClick}//cant get onClick Working at all, drei or R3F
onPointerOver={onClick= ()=> setBoxSize(true)}
>
<meshStandardMaterial
cast
attach="material"
color='yellow'
/>
</Box>
</>
)
}
const Floor = () => {
return (
<>
<mesh
onClick={()=> console.log("click")}
receiveShadow
rotation={[-Math.PI / 2, 0, 0]}
position={[0, -3, 0]}
>
<planeBufferGeometry attach='geometry' args={[100, 100]}/>
<meshStandardMaterial opacity={1} attach='material'/>
</mesh>
</>
)
}
export default App;
和子主页组件
import React, { useState } from 'react';
import styles from './Homepage.module.css'
const Homepage = ({boxToggle}) => {
const [displayUI, setDisplayUI] = useState(false);
if (boxToggle) {
setDisplayUI(true);
}
if (displayUI === true) {
return (
<div className={styles.container}>
<button onClick={() => setDisplayUI(false)} className="exit">X</button>
<div className={styles.title}>
<h1>Homepage</h1>
</div>
<div className={styles.menu}>
<h3>Option 1</h3>
<h3>Option 2</h3>
<h3>Option 3</h3>
</div>
</div>
)
} else return null
}
export default Homepage
我尝试过其他 Whosebug 答案,但我无法将它们应用到我的答案中。其中大部分与 useEffect 有关,或者缺少箭头函数。这让我感到困惑,我什至不知道从哪里开始,因为我不熟悉 Hooks。谢谢
我认为问题是由您的主页组件引起的。
const Homepage = ({boxToggle}) => {
const [displayUI, setDisplayUI] = useState(false);
//this generate error because it update the state directly when render
/*if (boxToggle) {
setDisplayUI(true);
}*/
//we can fix it by wrap it with a useEffect hook so this effect only trigger when the boxToggle value change
React.useEffect(()=>{
if (boxToggle) {
setDisplayUI(true);
}
}, [boxToggle]) // <--- dependency that trigger the function call
if (displayUI === true) {
return (
<div className={styles.container}>
<button onClick={() => setDisplayUI(false)} className="exit">X</button>
<div className={styles.title}>
<h1>Homepage</h1>
</div>
<div className={styles.menu}>
<h3>Option 1</h3>
<h3>Option 2</h3>
<h3>Option 3</h3>
</div>
</div>
)
} else return null
}