我正在试着做一个计时器组件,它会在延迟后隐藏自己。它可以工作,但当计时器消失时,我会有一个警告,我不知道如何处理它。
警告:呈现其他组件(Chronometer
)时无法更新组件(WorkoutScreen
)。若要在Chronometer
内找到错误的setState()调用
WorkoutScreen.tsx
const WorkoutScreen = ({
navigation,
route,
}: RootStackScreenProps<"Workout">) => {
const [inRest, setInRest] = useState(false)
const [restTime, setRestTime] = useState(5)
//I pass it to child
const handleEndRestTime = () => {
setInRest(false)
}
//
return (
<Layout style={styles.container}>
<Button
onPress={() => {
setInRest(!inRest)
}}
>
Trigger chronometer
</Button>
{inRest && (
<Chronometer onEnd={handleEndRestTime} seconds={restTime}></Chronometer>
)}
</Layout>
)
}
Chronometer.tsx
const Chronometer = ({ seconds, onEnd }: Props) => {
const [timer, setTimer] = useState<number>(seconds)
const [pause, setPause] = useState(false)
const [running, setRunning] = useState(true)
useEffect(() => {
let interval: NodeJS.Timer
if (pause === true || running === false) {
;() => clearInterval(interval)
} else {
interval = setInterval(() => {
setTimer((timer) => timer - 1)
}, 1000)
}
return () => {
clearInterval(interval)
}
}, [pause, running])
if (timer === 0 && running === true) {
setRunning(false)
//From parent
onEnd()
//
}
return (
<View style={styles.container}>
<View style={styles.chronometer}>
<View style={styles.controls}>
<Text>{formatHhMmSs(timer)}</Text>
</View>
<Button
onPress={() => {
setPause(!pause)
}}
>
Pause
</Button>
</View>
</View>
)
}
当我删除“{inRest &&“时,警告消失。
在未来,我希望用户可以根据自己的需要重新启动计时器
提前感谢!
Warning on my emulator (1)
Warning on my emulator (2)
Warning on my emulator (3)
Warning on my terminal
1条答案
按热度按时间9udxz4iz1#
有两个状态更新同时发生,并且与React呈现UI reconciliation冲突
1.计时器结束时,Chronometer组件内的
setRunning(false)
将重新呈现此组件。1.计时器结束时,WorkoutScreen组件内的
setInRest(false)
也将重新呈现。这两种重新呈现在同一计时器中发生,并且WorkoutScreen重新呈现由子组件触发。
解决方案是避免由子组件引起的父组件内部的状态改变。