Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to unmount a component on route change

I have a component at a given route, say app.com/cars/1

I have a sidebar with links to different cars, eg /cars/2, /cars/3 etc.

The issue I'm having is when you change links, say go from cars/1 to cars/2, the component doesn't unmount, and I get componentWillReceiveProps fired. If I go to another page with a different component, say /trucks, the component is unmounted and all is well.

How can I unmount my component when the route changes? I have all kinds of state and flux stuff that I want cleared for this next car. Or if not unmount, is there a typical way people handle this kind of issue? I can't imagine this isn't very common.

(note I'm using react-router)

like image 781
Ben Avatar asked Oct 06 '15 02:10

Ben


People also ask

How do you unmount a component?

Unmount a React Node React has a top-level API called unmountComponentAtNode() that removes a component from a specific container. The function unmountComponentAtNode() takes an argument as a container from which the specific component should be removed.

Does history push unmount component?

Calling history. push() inside of a component seems to cause the entire react component to unmount and remount; causing pointless remote service calls.

What does it mean to unmount a component?

Unmounting. This method is called when a component is being removed from the DOM: componentWillUnmount()

Can I pass Props to route component?

Since new release, it's possible to pass props directly via the Route component, without using a Wrapper.


1 Answers

I think the normal way to handle this is just to unregister and reregister your listeners, reset your state, and so on in componentWillReceiveProps. It's normal to create abstractions around this behavior:

componentWillMount: function() {
  this.setupStuff(this.props);
}

componentWillUnmount: function() {
  this.tearDownStuff();
}

componentWillReceiveProps: function(nextProps) {
  this.tearDownStuff();
  this.setupStuff(nextProps);
}

setupStuff: function(props) {
  this.setState(this.getDataFromStore(props.store));
  props.store.listen(this.handler); // or whatever
}

tearDownStuff: function(props) {
  props.store.unlisten(this.handler); // or whatever
}

However, if you really wanted to remount your components, there are a couple options you can use.

If you don't want any of your components to remain mounted across route changes, you can utilize the createElement option of the router to add a unique key to the components:

function createElement(Component, props) {
  var key = ...; // some key that changes across route changes
  return <Component key={key} {...props} />;
}

// ...

<Router createElement={createElement}>
  ...

However, I don't recommend this. Not only does it make your app slower because every route component is remounting each time, but it also completely disables things like animations between subsequent renders of the same route handler with different props.

If you only want a certain route to always rerender, you can give it a key in the parent via React.cloneElement:

render: function() {
  var key = ...; // some key that changes across route changes
  return React.cloneElement(
    React.Children.only(this.props.children),
    {key: key}
  );
}
like image 110
Michelle Tilley Avatar answered Sep 17 '22 18:09

Michelle Tilley