Xxtreem
Xxtreem

Reputation: 193

React-router doesn't remount component on different paths

I have a component in my react app which is a form. The form is used to create new licenses OR edit existing licenses. Either way it is only one component and it checks on componentDidMount() which "pageType" (add/update) it is. Now to my problem, when I'm using the form to edit a license (licensee/:id/edit) and I’m clicking the button which is bidet to create a new license (licensee/add), it will not remount the component. It will change the URL but all the preloaded data is still in the form.

  LicenseeForm = Loadable({
    loader: () => import('./license/LicenseeForm'),
    loading: 'Loading..'
  });

render() {
    return (
      <Router>
        <Switch>
          <LoginRoute exact path="/" component={this.LoginView}/>
          <LoginRoute exact path="/login" component={this.LoginView}/>
          <PrivateRoute exact path="/licensees/add" component={this.LicenseeForm}/>
          <PrivateRoute exact path="/licensees/:id/update" component={this.LicenseeForm}/>
          <Route path="*" component={this.NotFoundPage}/>
        </Switch>
      </Router>
    )
  }

const PrivateRoute = ({component: Component, ...rest}) => (
  <Route
    {...rest}
    render={props =>
      authService.checkIfAuthenticated() ? (<Component {...props} />) :
        (<Redirect
            to={{
              pathname: "/login",
              state: {from: props.location}
            }}/>
        )
    }
  />
);

Component:

componentDidMount() {
    const locationParts = this.props.location.pathname.split('/');
    if (locationParts[locationParts.length-1] === 'add') {
      this.setState({pageType: 'add'});
    } else if (locationParts[locationParts.length-1] === 'update') {
      this.setState({pageType: 'update'});
...
}}

EDIT

This is how it works now:

          <PrivateRoute exact path="/licensees/add" key="add" component={this.LicenseeForm}/>
      <PrivateRoute exact path="/licensees/:Id/update" key="update" component={this.LicenseeForm}/>

Upvotes: 6

Views: 6168

Answers (3)

Vipul Nema
Vipul Nema

Reputation: 21

Use props 'render' instead component.

As per Doc Component props remount while parent state changes but render props update.

https://reacttraining.com/react-router/web/api/Route/route-render-methods

Upvotes: 0

Vikas
Vikas

Reputation: 531

When the route is same and only path variable changes which in your case is "id", then the component at the top level of your route receives the change in componentWillReceiveProps.

componentWillReceiveProps(nextProps) {
  // In this case cdm is not called and only cwrp know
  // that id has been changed so we have to updated our page as well
  const newLicenseId = nextProps.match.params.id;

  // Check id changed or not
  if(currentLicenseId != newLicenseId) {
    updateState(); // update state or reset state to initial state
  }
}

I am pasting code which enables you to detect that page is changed and update the state or re-assign it to initial state. Also, suppose you come on license page first time then save current Id in a variable. That only you will use in componentWillReceiveProps to detect change.

Upvotes: 1

Piyush Zalani
Piyush Zalani

Reputation: 3934

If you do need a component remount when route changes, you can pass a unique key to your component's key attribute (the key is associated with your path/route). So every time the route changes, the key will also change which triggers React component to unmount/remount.

Upvotes: 15

Related Questions