Neil Grogan
Neil Grogan

Reputation: 177

React router componentDidMount not executing after switching route

I'm creating a react web application using react-router to navigate between the pages. Some of these pages depend on componentDidMount running when you navigate to the page. However, it seems this doesn't run unless I refresh the page which seems very counter-intuitive to users.

Is there a way to force componentDidMount to run when the render method completes perhaps.

Sorry if this is seen as a duplicate question but nothing I've seen has helped me understand how to solve this issue.

componentDidMount = async () => {
    //initialize web3
    const web3 = await getWeb3();

    // get contract address
    const ethAddress = await storehash.options.address
    this.setState({ethAddress})

    //set account for Blockchain network
    this.setState({account: await web3.eth.getAccounts()})
    }

Upvotes: 3

Views: 3630

Answers (2)

Azhar Zaman
Azhar Zaman

Reputation: 101

You can use the componentDidUpdate lifecycle method to compare previous props with current props and rerun the logic again; like

      constructor(props) {
          super(props);
          this.componentLogic = this.componentLogic.bind(this);
      }

      componentLogic() {
        // fetch something or some other business logic
      }
    
      componentDidMount() {
        this.componentLogic();
      }
    
      componentDidUpdate(prevProps) {
        // Typical usage (don't forget to compare props):
        if (
          this.props.reactRouterDom.params.slug !==
          prevProps.reactRouterDom.params.slug
        ) {
          this.componentLogic();
        }
      }   

Here I am passing route slug as prop via Higher Order Component(HOC), and tracking change in route via componentDidUpdate lifecycle.

Upvotes: 1

Jamie - Decodefy Ltd
Jamie - Decodefy Ltd

Reputation: 1397

tl;dr - Only Components rendered by Route (and their children) will re-render on a route change.

I'm going to make a few assumptions. One is that the componentDidMount you're trying to use is on a component that is not a child of one of your Route components.

The second assumption I'll make is that you don't need to run when that component mounts, but when one of the new routes' components mounts.

The componentDidMount function in the Component that's being rendered by the Route is probably where you need to be. However, if you need to update something in this component's state when one of its children mounts, that won't help. However you can go about this a couple different ways.

Quick and Dirty Don't get in the habit of doing this

If you're just testing something, a quick and dirty method is to use a route's render property instead of component.

So for example, if your route looks like this:

<Route path="/some-route" component={NewComponent} />

You could change this (again... only for a quick test, not recommended to have this in any production code!)

<Route path="/some-route" render={(props) => {
    //do your console log or temporary testing stuff here
    return <NewComponent ...props />
}} />

Pass down a function, that will pass up vars from the child

A less dirty way, and assuming you want the code to have access to something on this parent component, would be to pass down a function to the component. Again, you'd have to use render for this:

someFunction = (passedVar) => {
    // do something with passedVar, which you'll pass from the new component
}

// ... then in the Router...

<Route path="/some-route" render={(props) => <NewComponent ...props onRouteLoaded={this.someFunction} />}} />

Then you'd have a function (this.props.onRouteLoaded(...)) that you can run on the componentDidMount of the NewComponent - NOT on this parent component. This will allow you to pass vars up to the parent component if you need to access that component's state, props etc.

Recommended if you need to do that

A much cleaner way to do it, would be to use Redux state to pass values around, but (completely respectfully) get your head around React lifecycles before you breach Redux (but you SHOULD breach Redux!)

Upvotes: 2

Related Questions