英文:
I've created an infinite loop trying to use a switch statement in react
问题
以下是您要翻译的内容:
我不知道为什么下面的代码在控制台上出现错误,错误信息是
“react-dom.development.js:16317 Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.”
真的很困惑,因为我不知道为什么会出现这个错误。我试图创建一个图像滑块,所以我有一个方法,根据开关语句添加不同的图像到列表中,然后将该列表传递给子组件进行渲染。
```javascript
import { useEffect, useState } from "react";
import BikeDisplayImages from "./BikeDisplayImages";
import BikeDisplayTable from "./BikeDisplayTable";
import fixie_frame from "../../images/fixie-frame.png";
import tour_frame from "../../images/tour-frame.png";
import road_disc from "../../images/road-disc-frame_2.png";
import gravel_disc from "../../images/gravel-disc-frame.png";
import tumbleweed from "../../gifs/tumbleweed.gif";
import flared_bars from "../../images/Flared_Bars.png";
import drop_bars from "../../images/Drop_Bars.png";
import bullhorn_bars from "../../images/Bullhorn_Bars.png";
import flat_bars from "../../images/Flat_Bars.png";
const BikeDisplayWorker = ({ changedBike, bike }) => {
const [listOfImages, setListOfImages] = useState([]);
useEffect(() => {
if (changedBike) {
chooseImages();
}
});
function chooseImages() {
let tempList;
tempList.concat(chooseFrame(bike.frame.frameStyle));
tempList.concat(chooseBars(bike.handleBarType));
setListOfImages(tempList);
}
function chooseBars(barType) {
switch (barType) {
case "FLARE":
console.log("Flare Bars");
return <img src={flared_bars} alt="Flared Bars" />;
case "DROPS":
console.log("Drop Bars");
return <img src={drop_bars} alt="Drop Bars" />;
case "BULLHORNS":
console.log("Bull Bars");
return <img src={bullhorn_bars} alt="Bullhorn Bars" />;
case "FLAT":
console.log("Flat Bars");
return <img src={flat_bars} alt="Flat Bars" />;
case "NONE_SELECTED":
console.log("No Bars");
return <img src={tumbleweed} alt="No Bars Chosen" />;
default:
console.log("No Bars");
return <img src={tumbleweed} alt="No Bars Chosen" />;
}
}
function chooseFrame(frameStyle) {
switch (frameStyle) {
case "TOUR":
console.log("Tour Frame");
return <img src={tour_frame} alt="Touring frame" />;
case "CITY":
console.log("FIXIE!!");
return <img src={fixie_frame} alt="Single-speed frame" />;
case "ROAD":
console.log("Road Disc Frame");
return <img src={road_disc} alt="Road Frame, Disc Brakes" />;
case "GRAVEL":
console.log("Gravel Disc Frame");
return <img src={gravel_disc} alt="Gravel Frame, Disc Brakes" />;
case "NONE_SELECTED":
console.log("No Frame");
return <img src={tumbleweed} alt="No Frame Chosen" />;
default:
console.log("No Frame");
return <img src={tumbleweed} alt="No Frame Chosen" />;
}
}
return (
<div>
<BikeDisplayImages bike={bike} images={listOfImages} />
<BikeDisplayTable bike={bike} />
</div>
);
};
export default BikeDisplayWorker;
我不认为这是问题,但是concat是在这种方式中向列表添加项目的正确方法吗??
我尝试将useEffect放在不同位置,以查看是否有更好的调用方式。但我认为错误发生在方法运行之前。
在只需要显示单个图像时,这是有效的,但现在我有一个滑块并想要多个图像,它出现了问题。
<details>
<summary>英文:</summary>
I don't know how but the following code is getting an erro on the console saying
"react-dom.development.js:16317 Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop."
Really puzzled as I don't know why this is happening. I am trying to create an image slider so I have a method that adds different images to a list based on a switch statement, then passes that list down to the child to be rendered.
import { useEffect, useState } from "react";
import BikeDisplayImages from "./BikeDisplayImages";
import BikeDisplayTable from "./BikeDisplayTable";
import fixie_frame from "../../images/fixie-frame.png";
import tour_frame from "../../images/tour-frame.png";
import road_disc from "../../images/road-disc-frame_2.png";
import gravel_disc from "../../images/gravel-disc-frame.png";
import tumbleweed from "../../gifs/tumbleweed.gif";
import flared_bars from "../../images/Flared_Bars.png";
import drop_bars from "../../images/Drop_Bars.png";
import bullhorn_bars from "../../images/Bullhorn_Bars.png";
import flat_bars from "../../images/Flat_Bars.png";
const BikeDisplayWorker = ({ changedBike, bike }) => {
const [listOfImages, setListOfImages] = useState([]);
useEffect(() => {
if (changedBike) {
chooseImages();
}
});
function chooseImages() {
let tempList;
tempList.concat(chooseFrame(bike.frame.frameStyle));
tempList.concat(chooseBars(bike.handleBarType));
setListOfImages(tempList);
}
function chooseBars(barType) {
switch (barType) {
case "FLARE":
console.log("Flare Bars");
return <img src={flared_bars} alt="Flared Bars" />;
case "DROPS":
console.log("Drop Bars");
return <img src={drop_bars} alt="Drop Bars" />;
case "BULLHORNS":
console.log("Bull Bars");
return <img src={bullhorn_bars} alt="Bullhorn Bars" />;
case "FLAT":
console.log("Flat Bars");
return <img src={flat_bars} alt="Flat Bars" />;
case "NONE_SELECTED":
console.log("No Bars");
return <img src={tumbleweed} alt="No Bars Chosen" />;
default:
console.log("No Bars");
return <img src={tumbleweed} alt="No Bars Chosen" />;
}
}
function chooseFrame(frameStyle) {
switch (frameStyle) {
case "TOUR":
console.log("Tour Frame");
return <img src={tour_frame} alt="Touring frame" />;
case "CITY":
console.log("FIXIE!!");
return <img src={fixie_frame} alt="Single-speed frame" />;
case "ROAD":
console.log("Road Disc Frame");
return <img src={road_disc} alt="Road Frame, Disc Brakes" />;
case "GRAVEL":
console.log("Gravel Disc Frame");
return <img src={gravel_disc} alt="Gravel Frame, Disc Brakes" />;
case "NONE_SELECTED":
console.log("No Frame");
return <img src={tumbleweed} alt="No Frame Chosen" />;
default:
console.log("No Frame");
return <img src={tumbleweed} alt="No Frame Chosen" />;
}
}
return (
<div>
<BikeDisplayImages bike={bike} images={listOfImages}
/>
<BikeDisplayTable bike={bike} />
</div>
);
};
export default BikeDisplayWorker;
I don't think this is the problem, but is concat the correct method call to add an item to a list in this way??
I have tried putting the useEffect is different locations to see if there is a better way of calling it. But I think the error is occuring before the method is run.
This was working when I only needs to display a single image, but now that I have a slider and want multiple images, it has fallen over.
</details>
# 答案1
**得分**: 1
问题出在您的`useEffect`上,它没有依赖项数组,并且更改了状态。因此,您正在调用`useEffect`,它会更改状态,从而触发重新渲染,然后调用`useEffect`,它再次更改状态...
所以请在您的`useEffect`中添加一个依赖项数组 :)
<details>
<summary>英文:</summary>
Your problem comes from your `useEffect` with no dependency array, and which changes the state. So you're calling your `useEffect`, which change the state, which triggers a re-render, which calls your `useEffect`, which change the state,...
So add a dependency array to your useEffect :)
</details>
# 答案2
**得分**: 0
你的问题可能出在`useEffect`中。`useEffect`需要另一个参数,即依赖数组(dependency array),没有它的话,它会在每次渲染时都运行。这就是你遇到无限循环的原因,你的`useEffect`会运行 -> 设置状态 -> 导致重新渲染 -> 重新渲染又会运行你的`useEffect`,如此循环。
[从 React 文档中][1](旧版本):
> 如果你想要只在挂载和卸载时运行一次效果并清理它,可以将一个空数组([])作为第二个参数传递。这告诉 React,你的效果不依赖于任何来自 props 或 state 的值,因此它永远不需要重新运行。这不会被视为特殊情况 - 它直接遵循依赖数组的工作原理。
另一个潜在问题的来源是你如何使用`concat`方法。
在下面的图片中,我希望更清楚,`concat`函数返回了什么。
[1]: https://reactjs.org/docs/hooks-reference.html#useeffect
请注意,我只翻译了你提供的内容中的文本部分,不包括代码部分。
<details>
<summary>英文:</summary>
Your problem probably lies in the useEffect. useEffect takes another argument, the dependency array,without it, it runs on every render. That's why you have an infinite loop, your useEffect runs->sets the state which causes a rerender->the rerender will run again your useEffect and so on.
[From the react docs][1](old):
> If you want to run an effect and clean it up only once (on mount and unmount), you can pass an empty array ([]) as a second argument. This tells React that your effect doesn’t depend on any values from props or state, so it never needs to re-run. This isn’t handled as a special case — it follows directly from how the dependencies array always works.
Also another potential source of problems is how you are using the concat method.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-html -->
<script>
function chooseImages() {
let tempList;
tempList.concat(["hello"]);
tempList.concat(["world"]);
console.log("Concatenating arrays",tempList);
}
function chooseImages2(){
let tempList = "";
tempList.concat("hello");
tempList.concat("world");
console.log("Concatenating strings",tempList)
}
//chooseImages();
chooseImages2();
</script>
<!-- end snippet -->
[![][2]][2]
In the picture below i hope it is more clear, that the concat function returns something
[![][3]][3]
[1]: https://reactjs.org/docs/hooks-reference.html#useeffect
[2]: https://i.stack.imgur.com/zpa3L.png
[3]: https://i.stack.imgur.com/LqK5E.png
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论