1

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;
Max Wolfen
  • 1,523
  • 5
  • 15
  • 38

2 Answers2

12

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.

Lyubomir
  • 17,533
  • 4
  • 51
  • 65
  • 1
    you're on the right track - declarative first is React's philosophy, will be happy if you accept my answer then!:-) – Lyubomir Apr 10 '18 at 13:19
2

Redirect needs to be rendered for it to work, if you want to redirect from an api call, you can use history.push to programmatically navigate. Also you would rather use setState callback instead of timeout

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

Check Programmatically Navigate using react-router for more details

Even if you add Redirect within setTimeout in render it won't work because it will not render it, rather just be a part of the return in setTimeout

Shubham Khatri
  • 211,155
  • 45
  • 305
  • 318