43

I am trying to have separate routes but same component for add/edit forms in my react app like the below:

<Switch>
        <Route exact path="/dashboard" component={Dashboard}></Route>
        <Route exact path="/clients" component={Clients}></Route>
        <Route exact path="/add-client" component={manageClient}></Route>
        <Route exact path="/edit-client" component={manageClient}></Route>        
        <Route component={ NotFound } />        
</Switch>

Now in the manageClient component, I parse the query params (I pass in a query string with client id in edit route), I render conditionally based on the query param passed.

The problem is that this doesn't remount the whole component again. Say an edit page is opened, and the user clicks on add component, the URL changes, but the component doesn't reload and hence remains on the edit page.

Is there a way to handle this?

1
  • 1
    In the root DOM element of manageClient's render() method, try to add a key, whose value is based on whatever querystring you give it. For example, try having it be key="add" for /add-client and key="edit" for /edit-client. (I actually don't know if this will work, which is why I'm not submitting it as an answer) Commented Feb 27, 2018 at 4:18

5 Answers 5

84

Using different key for each route should force components to rebuild:

    <Route 
      key="add-client"
      exact path="/add-client"
      component={manageClient} 
    />

    <Route 
      key="edit-client"
      exact path="/edit-client"
      component={manageClient} 
    />
Sign up to request clarification or add additional context in comments.

4 Comments

Is it possible to catch the key/path from the component itself?
It's possible. You can get route props from components by this.props.route.key
This worked for me until I had a dynamic route (with an ID property in the route a la /blog/post/:id)... the key was unique to the URL and ANY ID, but navigating between two IDs maps to the same route and key twice, failing to re-render the route when navigating between two routes mapped to the same router entry... e.g. nav'ing between /blog/post/1 and /blog/post/2 does not re-render either...
To clarify more, the "key" is to trigger diffing in react reconciliation. FYI github.com/ReactTraining/react-router/issues/5972 and reactjs.org/docs/reconciliation.html
11
<Route exact path={["/add-client", "/edit-client"]}>
  <manageClient />
</Route>

Reference

Version 5.2.0

https://reacttraining.com/react-router/web/api/Route/path-string-string

Comments

9

One solution is use inline function with component, that will render a new component each time, But this is not a good idea.

Like this:

<Route exact path="/add-client" component={props => <ManageClient {...props} />}></Route>
<Route exact path="/edit-client" component={props => <ManageClient {...props} />}></Route> 

Better solution would be, use componentWillReceiveProps lifecycle method in ManageClient component. Idea is whenever we render same component for two routes and switching between them, then react will not unmount-mount component, it will basically update the component only. So if you are making any api call or require some data do all in this method on route change.

To check, use this code and see it will get called on route change.

componentWillReceiveProps(nextProps){
   console.log('route chnaged')
}

Note: Put the condition and make the api call only when route changes.

2 Comments

I believe this is the better answer. Suggesting the use of componentWillReceiveProps as the location to make an API call was what I needed without unmounting/mounting the same component.
componentWillReceiveProps is deprecated now as of React 16.3
1

You can simply provide an array of paths in a single route tag as follows -

<Route exact path={["/add-client", "/edit-client"]} component={manageClient}></Route>

Comments

0

My problem was we used an common path in-between, which causes dynamic path to not working

      <Switch>
        <Route key="Home" path="/home" component={Home} />
        <Route key="PolicyPlan-create"  path="/PolicyPlan/create" component={PolicyPlanCreatePage} />
        {/* <Route key="PolicyPlan-list" path="/PolicyPlan" component={PolicyPlanListPage} /> */}
        <Route key="PolicyPlan-list" path="/PolicyPlan/list" component={PolicyPlanListPage} />            
        <Route key="PolicyPlan-edit"  path="/PolicyPlan/edit/:id" component={PolicyPlanCreatePage} />   
        <Route key="cardDesign" path="/cardDesign" component={cardDesign} />
        <Route key="Admin-create" path="/admin/create" component={RegisterPage} />
      </Switch>

So don't use the path like the commented one, now the code is working

.................
          this.props.history.push("/PolicyPlan/edit/" + row.PolicyPlanId);
.............    

Comments

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.