Morton
Morton

Reputation: 5782

clearTimeout is not working in React Native

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?

Upvotes: 6

Views: 17287

Answers (2)

Hend El-Sahli
Hend El-Sahli

Reputation: 6752

Using 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);
      }
    };
  }, []);

Upvotes: 10

Chad Nehemiah
Chad Nehemiah

Reputation: 881

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;
}

Upvotes: 7

Related Questions