Re-initializing class on redirect

Solution 1:

The id is passed as a prop in the form of this.props.params.id so you should use the componentWillReceiveProps lifecycle method which runs everytime the props change which is what is happening in your case.

The componentWillMount method will not run when you navigate from /parentdir/module/2 to /parentdir/module/3 as the component is already mounted. It will only run when you navigate from some other component (when you go directly for example).

In your Module component add this lifecycle method

componentWillReceiveProps(nextProps){
      if(nextProps.params.id != this.props.params.id){
          //load information etc (whatever you are doing in componentWillMount)
       }
}

What is happening is that when it receives the newer set of props it's comparing if the param id has changed (all route params live in the params object in props) and when it sees there is a change it carries out the logic. The comparison is not really necessary and you can add the logic as is in the componentWillReceiveProps method but that would be inefficient as it is called everytime the props object changes (might not be the id param at all).

Solution 2:

componentWillMount() and componentDidMount() will only be executed once!

(According to React Component Life Cycle https://facebook.github.io/react/docs/react-component.html#the-component-lifecycle)

If you want your Module to be updated every time the grandchild module updates, you need to create a function in your Module, and pass it along as Props to the child, and grandchild modules as well (in the main Module's render method)

That function (updateThisModule) and your render method will look something like this:

EDITED VERSION BELOW: (this is just a demonstration on how to trigger a callback function on parent-component from multi-level-child-component, we can actually do whatever in that callback)

import React from 'react';

class Module extends React.Component {

  constructor(props) {
    super(props);
    // ...
  }

  updateThisModule = () => {
    // We can do whatever we want here, either forceUpdate the component
    // or setState, which will also trigger this component to update itself
    // (using setState is more natural, though)
    // *** OPTION 1
    // this.forceUpdate();
    // *** OPTION 2
    // this.setState({
    //   someState: 'someValue',
    //   ..
    // });
    // *** ...
    // ...
  }

  render(){
    // ...
    <ChildModule updateParent={this.updateThisModule} />
    // ...
  }
}

Likewise, do the same thing in your child-module's render method (to pass that function down 1 more level to the grandchild-module):

class ChildModule extends React.Component {
  ...
  render(){
    // ...
    <GrandChildModule updateGrandParent={this.props.updateParent} />
    // ...
  }
}

After that, in the Grand-Child-Module, we need a trigger that call the top-level Module to be updated, I suggest you trigger this in the componentDidUpdate() function. Then, the Grand-Child-Module may look like this:

class GrandChildModule extends React.Component {
  constructor(props) {
     super(props);
     // ...
  }

  componentDidUpdate() { 
    // this will be executed every time this grand-child-module updates itself
    // we will then trigger the update function upward to the parent's level first, then the grand-parent's level (which is your main Module)
    this.props.updateGrandParent(); 
  }

  render(){
    // ...
  }
}

The above code is written in ES6, if you write yours in different way, feel free to post it here, then we can modify your code together to make it work!

PS: passing function as props along to child's component is also the main idea of pure React components. However, if your module-hierarchy is too deep (with many child, grandchild, great-grandchild etc.,) you may consider using Flux or Redux