I have four screens A (HomePage), B, C, D
Each of screens have a function that will be triggered when the screen onStart
or onResume
, I achieve it by react-redux.
countdownToFirstScreen = () => {
this.timeOut = setTimeout(()=> {
clearTimeout(this.timeOut); // clearTimeout before navigate next screen
this.props.leaveTheScreenTime(); // change for some redux store boolean
this.props.navigation.navigate('A');
}, 9000);
}
If user click <Button />
before countdown finish, I set the clearTimeout too.
<Button
onPress={() => {
clearTimeout(this.timeOut);
this.props.navigation.navigate('nextScreen');
}
/>
It is working when I just navigate between A and B and C.
My issue happens when I try to navigate from C to D.
C screen function countdownToFirstScreen
will be triggered eventhough I click the <Button />
on C screen.
Any one knows what happened with my setTimeout
and clearTimeout
?
I have four screens A (HomePage), B, C, D
Each of screens have a function that will be triggered when the screen onStart
or onResume
, I achieve it by react-redux.
countdownToFirstScreen = () => {
this.timeOut = setTimeout(()=> {
clearTimeout(this.timeOut); // clearTimeout before navigate next screen
this.props.leaveTheScreenTime(); // change for some redux store boolean
this.props.navigation.navigate('A');
}, 9000);
}
If user click <Button />
before countdown finish, I set the clearTimeout too.
<Button
onPress={() => {
clearTimeout(this.timeOut);
this.props.navigation.navigate('nextScreen');
}
/>
It is working when I just navigate between A and B and C.
My issue happens when I try to navigate from C to D.
C screen function countdownToFirstScreen
will be triggered eventhough I click the <Button />
on C screen.
Any one knows what happened with my setTimeout
and clearTimeout
?
2 Answers
Reset to default 10Using React-Hooks and Functional Components ... things are alot easier...
An effect with empty-deps []
simulates componentDidMount
, and its cleanUp-callback simulates componentWillUnmount
const timerRef = useRef(null);
useEffect(() => {
timerRef.current = setTimeout(() => {
/** Your logic goes here */
}, 9000);
return () => {
if (timerRef.current) {
clearTimeout(timerRef.current);
}
};
}, []);
It looks like you may run into scoping issues as this
in the setTimeout
callback may have a different context than this.timeOut
and thus the timer is not being cleared. Ideally you want a setup where you track the timer in some global component like your AppComponent
which is on every screen, with a setup like:
componentWillMount () {
// Add your listener
DeviceEventEmitter.addListener('timer', this.clearTimer.bind(this));
}
componentDidMount () {
startTimer()
}
componentWillUnMount () {
clearTimer()
}
startTimer () {
this.timer = this.setTimeout(() => {
this.props.navigation.navigate('A');
},9000);
clearTimer () {
// Handle an undefined timer rather than null
this.timer !== undefined ? this.clearTimeout(this.timer) : null;
}
this
referencing the same object? – Spencer Wieczorek Commented Jan 28, 2019 at 3:07this.timeout
in all screens. It may be this problem ? – Morton Commented Jan 28, 2019 at 3:10countdownToFirstScreen
will be triggered if I just navigate A -> B -> C -> D. It doesn't route back any screen in this case. – Morton Commented Jan 28, 2019 at 3:18