0

Use Case

I want to make async() call whenver user will try to visit private route. Generally synchronous methods are used while redirecting to private routes.

Here is my code I have used but not understanding how can I use asynchronous method with it.

class PrivateRoute extends Component {
  constructor(props) {
    super(props);

    this.state = {
      isAdmin: null
    };
  }

  componentDidMount() {
    console.log("PrivateRoute");
    verifyUser().then(res => {
      this.setState({
        isAdmin: res
      });
    });
  }

  render() {
    const { component: Component, ...rest } = this.props;
    return (
      <Route
        {...rest}
        render={props =>
          this.state.isAdmin === true ? (
            <InnerLayout>
              <Component {...props} />
            </InnerLayout>
          ) : this.state.isAdmin === null ? (
            <div>Loading...</div>
          ) : (
            <Redirect
              to={{ pathname: "/Login", state: { from: this.props.location } }}
            />
          )
        }
      />
    );
  }
}

export default PrivateRoute;

Problem with above code is componentDidMount() calls once. I have checked React routing and private routes Question and also checked Authenticate async with react-router-v4 question but both answers didn't work for me.

If I try to resolve promise in render then it shows following error:

Error - Failed to Compile

How can I achieve this use case?

Clarity
  • 10,730
  • 2
  • 25
  • 35
Rohit Sawai
  • 739
  • 1
  • 11
  • 28

3 Answers3

1

You can use withRouter (https://reacttraining.com/react-router/web/api/withRouter)

class PrivateRoute extends Component {
    constructor(props) {
        super(props);

        this.state = {
            isAdmin: null
        }
    }

    componentDidMount() {
        console.log('PrivateRoute');
        verifyUser().then(res => {
            if(!res){
             this.props.history.push('/Login')
           }else
            this.setState({
                isAdmin: res
            })
        });
    }

    render() {
        const { component: Component, ...rest } = this.props;
       if(this.state.isAdmin === null) return <div>Loading ...</div>
       return <Route {...rest} render={props => <InnerLayout><Component/></InnerLayout>}
    }
}

export default withRouter(PrivateRoute);
san
  • 1,515
  • 11
  • 18
  • `componentDidMount()` method calls only once. After that whenever user click on other private routes, that method will not call. – Rohit Sawai Dec 03 '19 at 06:47
0

I think you wrap routes with components then wrap routes again, try to make statements and make different methods for your code, don't render methods.

<Route {...rest} render={props =>
                this.state.isAdmin === true ? (<InnerLayout><Component {...props} /></InnerLayout>) :
                    (this.state.isAdmin === null ? (<div>Loading...</div>) : 
                        (<Redirect to={{ pathname: '/Login', state: { from: this.props.location } }} />)) }/>
            );

make method :

verify = () => {

 ... your statement
}

and then call in render method

render () {
return {this.verify()}
}

Because sometimes statement on render not work fine.

zidniryi
  • 1,212
  • 3
  • 15
  • 36
0

For my use case componentWillReceiveProps() method worked perfectly. Following code I have added and which is worked for me.

componentWillReceiveProps() {
        verifyReceivedSign().then((res) => {
            this.setState({
                isAdmin: res
            })
        });
    }

You know more about componentWillReceiveProps() in the given link.

Rohit Sawai
  • 739
  • 1
  • 11
  • 28