我有两个组件,代表一个交通灯,显示红色和绿色,他们是同步的。交通灯的每一种颜色的时间都是动态的,根据我们得到的交通数据,但是它们是同步的(如果一个交通灯的绿色持续了8秒,另一个交通灯必须红色2秒(假设总数是10秒)。
下面的代码可以工作,但是如果每10秒(我将调用一个API)我想改变他们的绿色/红色时间,会怎样呢?你会怎么接近它?
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>)发布于 2022-03-28 14:24:52
如果交通信号灯是相互依赖的,这应该反映在代码中。在不分离交通灯状态的情况下,同步可以更有效地进行。除了保持一个单一的状态,如果你想保持红灯和绿灯的同步,你应该保持一个固定,并计算另一个从总长度和固定光长度。
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>
)https://stackoverflow.com/questions/71648701
复制相似问题