React JS 交通灯模拟器中的模式错误

问题描述 投票:0回答:3

我正在尝试使用 ReactJS 构建一个交通灯。我需要交通灯按照红色、黄色、绿色、红色、黄色、绿色等的顺序运行。我当前的代码给了我一个不同的模式。我不太清楚如何使用 setInterval 来处理这个问题,我确实需要一些帮助。我在 CodePen 上查看了 CarterTsai 对同一问题的解决方案,但我既无法理解他的大部分代码,也无法将其转换为 stackblitz 友好的格式以适应我的代码。有人有答案吗?任何帮助表示赞赏!如果任何人都可以提供一个包含两个组件的解决方案,那就太好了 - 一个组件改变交通灯状态,另一个利用该状态显示实际的交通灯(这是我作业的要求)。

这里是在 stackblitz 上查看我的项目的链接:https://stackblitz.com/edit/react-eqkhd7?file=src/style.css

我在 App.js 中的代码:

import React from 'react';
import './style.css';

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      color1: '',
      color2: '',
      color3: ''
    };

    setInterval(this.changeColor1.bind(this), 2000);
    setInterval(this.changeColor2.bind(this), 4000);
    setInterval(this.changeColor3.bind(this), 6000);
  }

  changeColor1 = () => {
    this.setState({ color1: 'red', color2: '', color3: '' });
  };

  changeColor2 = () => {
    this.setState({ color1: '', color2: 'yellow', color3: '' });
  };

  changeColor3 = () => {
    this.setState({ color1: '', color2: '', color3: 'green' });
  };

  render() {
    return (
      <div>
        <span style={{ backgroundColor: this.state.color1 }} class="circle" />
        <p />
        <span style={{ backgroundColor: this.state.color2 }} class="circle" />
        <p />
        <span style={{ backgroundColor: this.state.color3 }} class="circle" />
      </div>
    );
  }
}

样式.css:

h1,
p {
  font-family: Lato;
}

.circle {
  margin: auto;
  height: 100px;
  width: 100px;
  border: 5px black solid;
  border-radius: 50%;
  display: block;
}

index.js :

import React from "react";
import ReactDOM from "react-dom";

import App from "./App";

ReactDOM.render(<App />, document.getElementById("root"));
javascript reactjs state setinterval stackblitz
3个回答
0
投票

您可以使用

setTimeout
执行此操作,并在当前交通灯执行后调用其他交通灯函数。

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      color1: '',
      color2: '',
      color3: ''
    };

    setTimeout(this.changeColor1, 2000);
  }

  changeColor1 = () => {
    this.setState({ color1: 'red', color2: '', color3: '' });
    setTimeout(this.changeColor2, 2000);
  };

  changeColor2 = () => {
    this.setState({ color1: '', color2: 'yellow', color3: '' });
    setTimeout(this.changeColor3, 2000);
  };

  changeColor3 = () => {
    this.setState({ color1: '', color2: '', color3: 'green' });
    setTimeout(this.changeColor1, 2000);
  };

这是工作小提琴


0
投票

您的问题是您设置了 3 个不同的时间间隔,因此所有 3 个状态更改函数都以不同的时间间隔连续调用。特别是,第一个使其变为红色的事件每 2 秒发生一次 - 这将包括尝试将其变为黄色的每 4 秒一次,以及尝试将其变为绿色的每 6 秒一次。这将导致不可预测的结果,因为没有真正的方法知道每次都会首先触发哪个函数 - 它可能取决于“随机”因素,或者可能取决于您正在使用的浏览器。

我假设您的意图是每 2 秒定期更改一次,按照红色、黄色、绿色等的顺序。为此,请创建一个 single 函数来检查当前状态并适当更新 - 并安排每 2 秒进行一次更改秒。

这是实现这一目标的多种方法之一。保留

render
不变,但用以下方法替换其他方法:

  constructor(props) {
    super(props);
    this.state = {
      color1: 'red',
      color2: '',
      color3: ''
    };

    setInterval(this.changeColor, 2000);
  }

  changeColor1 = () => {
    this.setState({ color1: 'red', color2: '', color3: '' });
  };

  changeColor2 = () => {
    this.setState({ color1: '', color2: 'yellow', color3: '' });
  };

  changeColor3 = () => {
    this.setState({ color1: '', color2: '', color3: 'green' });
  };

  changeColor = () => {
    if (this.state.color1) {
      this.changeColor2();
    } else if (this.state.color2) {
      this.changeColor3();
    } else {
      this.changeColor1();
    }
  };

(实际上,拥有一个保存当前颜色的单一状态属性会更整洁,但这也意味着重写

render
。我会让你考虑这是否适合你。)

PS:这里实际上不需要

bind
,因为你的方法是使用箭头函数定义为属性的。您可以使用其中之一 -
bind
或箭头功能 - 但同时使用两者是没有意义的。


0
投票
    **Code for with different time for each color light**

     ***Build a traffic light where the lights switch from green to yellow to red after predetermined intervals and loop indefinitely. Each light should be lit for the following durations:
Red light: 4000ms
Yellow light: 500ms
Green light: 3000ms
You are free to exercise your creativity to style the appearance of the traffic light.***
    
    import React, {useState, useEffect} from 'react'
    export default function TrafficLight() {
     
     const [color, setColor] = useState("")
     const [count, setCount] = useState(0)
     const [delayTime, setDelayTime] = useState(0)
    
     useEffect(()=>{                
           setTimeout(()=>{    
              if(count == 0){
                setColor("red");
                setDelayTime(4000)            
              }  
              if(count == 1){
                setColor("yellow");
                 setDelayTime(5000) 
              }  
              if(count == 2){
                setColor("green");
                 setDelayTime(3000) 
              } 
              if(count>2){
                 setCount(0)
              } else {
                setCount(count+1)
              }
              
        }, delayTime)
     }, [count])
    
    
    
      return <div>
          <div> 
              <div class={color == "red" ? "red" : ""}> Red </div>
              <div class={color == "yellow" ? "yellow" : ""}> Yellow </div>
              <div class={color == "green" ? "green" : ""}> Green </div>
          </div>
      </div>;
    }
© www.soinside.com 2019 - 2024. All rights reserved.