首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何根据动态开/关时间同步显示2种不同颜色的2个组件(交通灯)

如何根据动态开/关时间同步显示2种不同颜色的2个组件(交通灯)
EN

Stack Overflow用户
提问于 2022-03-28 13:58:27
回答 1查看 123关注 0票数 0

我有两个组件,代表一个交通灯,显示红色和绿色,他们是同步的。交通灯的每一种颜色的时间都是动态的,根据我们得到的交通数据,但是它们是同步的(如果一个交通灯的绿色持续了8秒,另一个交通灯必须红色2秒(假设总数是10秒)。

下面的代码可以工作,但是如果每10秒(我将调用一个API)我想改变他们的绿色/红色时间,会怎样呢?你会怎么接近它?

代码语言:javascript
运行
复制
 const [bottomToUp, setBottomToUp] = useState({
    redLight: false,
    greenLight: true,
    greenOnTime: 6,
    redOnTime: 4,
  });

  const [rightToLeft, setRightToLeft] = useState({
    redLight: true,
    greenLight: false,
    greenOnTime: 4,
    redOnTime: 6,
  });

  useEffect(() => {
    setTimeout(
      () => {
        setBottomToUp((prevState) => ({
          ...prevState,
          redLight: !prevState.redLight,
          greenLight: !prevState.greenLight,
        }));
      },
      bottomToUp.redLight
        ? bottomToUp.greenOnTime * 1000
        : bottomToUp.redOnTime * 1000
    );
  }, [bottomToUp]);

  useEffect(() => {
    setTimeout(
      () => {
        setRightToLeft((prevState) => ({
          ...prevState,
          redLight: !prevState.redLight,
          greenLight: !prevState.greenLight,
        }));
      },
      rightToLeft.redLight
        ? rightToLeft.greenOnTime * 1000
        : rightToLeft.redOnTime * 1000
    );
  }, [rightToLeft]);


       return (<div>
          <TrafficLight
            RedOn={rightToLeft.redLight}
            GreenOn={rightToLeft.greenLight}
          />
          <TrafficLight
            RedOn={bottomToUp.redLight}
            GreenOn={bottomToUp.greenLight}
          />
      </div>)
EN

回答 1

Stack Overflow用户

发布于 2022-03-28 14:24:52

如果交通信号灯是相互依赖的,这应该反映在代码中。在不分离交通灯状态的情况下,同步可以更有效地进行。除了保持一个单一的状态,如果你想保持红灯和绿灯的同步,你应该保持一个固定,并计算另一个从总长度和固定光长度。

代码语言:javascript
运行
复制
const [bottomToUp, setBottomToUp] = useState({
  greenLight: true,
  greenOnTime: 1,
  totalSemaphoreTime: 3,
})
/** Using ref here because the state changes would cause the useEffect hook to reevaluate and clear the previous timeout before it was completed */
const bottomToUpRef = useRef(bottomToUp)
bottomToUpRef.current = bottomToUp

const fetchNewGreenOnTimeFromAPI = () => {
  const newGreenOnTime = getFromAPI()
  setBottomToUp(prev => ({ ...prev, greenOnTime: newGreenOnTime }))
}

useEffect(() => {
  let timeoutId

  const timeout = () => {
    return setTimeout(
      () => {
        setBottomToUp(prevState => ({
          ...prevState,
          greenLight: !prevState.greenLight,
          timerStarted: false,
        }))
        timeoutId = timeout()
      },
      bottomToUpRef.current.greenLight
        ? bottomToUpRef.current.greenOnTime * 1000
        : (bottomToUpRef.current.totalSemaphoreTime -
            bottomToUpRef.current.greenOnTime) *
            1000 /** Only using the greenLight as parameter since red light is dependent on green light */,
    )
  }

  timeoutId = timeout()

  return () => {
    clearTimeout(
      timeoutId,
    ) /** You should always clear timeout when component unmounts */
  }
}, [])

return (
  <div>
    {/** Switched the right to left semaphore values to be reflected from the bottomToUp state since they are dependent */}
    <TrafficLight
      RedOn={bottomToUp.greenLight}
      GreenOn={!bottomToUp.greenLight}
    />
    <TrafficLight
      RedOn={!bottomToUp.greenLight}
      GreenOn={bottomToUp.greenLight}
    />
  </div>
)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71648701

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档