我在React中使用switch语句创建了一个无限循环。

huangapple go评论72阅读模式
英文:

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&#39;t know how but the following code is getting an erro on the console saying 
&quot;react-dom.development.js:16317 Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.&quot;

Really puzzled as I don&#39;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&#39;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&#39;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&#39;s why you have an infinite loop, your useEffect runs-&gt;sets the state which causes a rerender-&gt;the rerender will run again your useEffect and so on. 

[From the react docs][1](old):
&gt; 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. 

&lt;!-- begin snippet: js hide: false console: true babel: false --&gt;

&lt;!-- language: lang-html --&gt;

    &lt;script&gt;
     function chooseImages() {
        let tempList;
        tempList.concat([&quot;hello&quot;]);
        tempList.concat([&quot;world&quot;]);
        console.log(&quot;Concatenating arrays&quot;,tempList);
      }
      function chooseImages2(){
        let tempList = &quot;&quot;;
        tempList.concat(&quot;hello&quot;);
        tempList.concat(&quot;world&quot;);
        console.log(&quot;Concatenating strings&quot;,tempList)
      }
      //chooseImages();
      chooseImages2();
    &lt;/script&gt;

&lt;!-- end snippet --&gt;

[![][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>



huangapple
  • 本文由 发表于 2023年1月9日 06:23:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/75051677.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定