Search code examples
javascriptreactjsreact-router-v4react-router-domreact-dom

Why in the new react-router-dom <Redirect/> does not fire inside the setTimout?


So, I tried to make a little delay between the logout page and redirecting to the main website page. But I fall into the problem, that the react-router-dom <Redirect/> method does not want fire when we put it inside the setTimeout() of setInterval().

So, if we unwrapped it from timer, the <Redirect/> will work normally.

What is the problem is, any suggestions?

My code:

import React, { Component } from 'react';
import { Redirect } from 'react-router-dom';
import axios from 'axios';

class LogoutPage extends Component {
    constructor(props) {
        super(props);
        this.state = {
            navigate: false
        }
    }

    componentDidMount(e) {
        axios.get('http://localhost:3016/logout')
        .then(
            this.setState({
                navigate: true
            }),
        )
        .catch(err => {
            console.error(err);
        });

        if (this.state.navigate) {
            setTimeout(() => {
                return <Redirect to="/employers" />
            }, 2000);
        }
    };

    render() {
        if (this.state.navigate) {
            setTimeout(() => {
                 return <Redirect to="/employers" />
            }, 2000);
        }
        return (
            <div>You successfully logouted</div>
        )
    }
}

export default LogoutPage;

Solution

  • You want the render() method to return <Redirect /> in order for the redirect to take place. Currently the setTimeout function returns a <Redirect />, but this does not affect the outcome of the render() itself.

    So instead, the render() should simply return <Redirect /> if this.state.navigate is true and you delay the setState({ navigate: true }) method with 2 seconds.

    Here's a corrected, declarative way of doing it:

    class LogoutPage extends Component {
        constructor(props) {
            super(props);
            this.state = {
                navigate: false
            }
        }
    
        componentDidMount(e) {
            axios.get('http://localhost:3016/logout')
            .then(() => setTimeout(() => this.setState({ navigate: true }), 2000))
            .catch(err => {
                console.error(err);
            });
    
        };
    
        render() {
            if (this.state.navigate) {
              return <Redirect to="/employers" />
            }
    
            return (
              <div>You successfully logouted</div>
            );
        }
    }
    

    For the imperative version, see @Shubham Khatri's answer.