17

In React router, I have to and onClick attributes as shown below

<li key={i}><Link to="/about" onClick={() => props.selectName(name)}>{name}</Link></li>

state = {
    selectedName: ''
};

selectName = (name) => {
   setTimeout(function(){this.setState({selectedName:name});}.bind(this),1000);
   // this.setState({selectedName: name});
}
  • to attribute navigates to about Route
  • onClick assigns value to state variable selectedName which will be displayed when navigated to About page.

When I give timeout insided function called on click, its navigating to new page and after sometime state is getting updated resulting in displaying previous name until state is updated with new name.

Is there a way where it will navigate to the new route only after the code in onClick function gets executed.

You can get the entire code [here].(https://github.com/pushkalb123/basic-react-router/blob/master/src/App.js)

0

2 Answers 2

16

One possible way is, Instead of using Link, use history.push to change the route dynamically. To achieve that remove the Link component and define the onClick event on li. Now first perform all the task inside onClick function and at the end use history.push to change the route means to navigate on other page.

In your case change the router inside setState callback function to ensure that it will happen only after state change.

Write it like this:

<li key={i} onClick={() => props.selectName(name)}> {name} </li>

selectName = (name) => {
    this.setState({ selectedName:name }, () => {
        this.props.history.push('about');
    });
}

Check this answers for:

When to use setState callback

How to navigate dynamically using react router dom

Sign up to request clarification or add additional context in comments.

7 Comments

With the new changes, its showing the error 'Cannot read property 'push' of undefined'. how to pass history as prop. I am using render inside <Route> as shown below. <Route exact path="/" render={() => <Home names={names} selectName={this.selectName} />} />
use this: <Route exact path="/" render={(props) => <Home {...props} names={names} selectName={this.selectName} />} />, it will work, notice {...props} part :)
check this answer for more details about {...props}: React react-router-dom pass props to component
wrap your component by withRouter, it will provide access to history, like this: export default withRouter(ComponentName). Check DOC
Thanks for the solution. Its working fine. Since the export statement was outside withRouter, as discussed I moved the Router to index.js file and it worked. Complete solution is updated here
|
3

Alternatively, I would recommend using URL Params in order to capture the name of the person that the about page is about. Thus, instead of the url being /about and the name being behind the scenes, it would be /about/tom or /about/pushkal. The way that you do this is by defining params in the URL router as such in your index.js:

<Route path="/about/:name" component={AboutPage}>

Now, when you link to the about page, you would do it as such:

<Link to={"/about/" + name}>{name}</Link>

Now, in your AboutPage component, you can access the name param as a prop in this.props.params.name. You can look at more examples here.

This method is a bit different than your current approach but I suspect it will lead to easier design later on

1 Comment

This approach is solves the above purpose. The only change required is usage of {match} in About function. const About = ({ match }) => ( <h2>About {match.params.id}</h2> There is one limitation in this apporach if we need to store huge data and display huge data in the About page, passing all the data in URL is cumbersome.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.