React doesn't reload component data on route param change or query change

react hooks
react setstate
react tutorial
react native
react router
react, ( usestate)
react setstate callback
create-react app

I have a "home" component with links, and when you click a link the product component is loaded with the product. I also have another component which is always visible, showing links to the "recently visited products".

These links don't work when on a product page. The url updates when I click the link, and a render occurs, but the product component doesn't update with the new product.

See this example: Codesandbox example

Here are the routes in index.js:

<BrowserRouter>
  <div>
    <Route
      exact
      path="/"
      render={props => <Home products={this.state.products} />}
    />

    <Route path="/products/:product" render={props => <Product {...props} />} />

    <Route path="/" render={() => <ProductHistory />} />

    <Link to="/">to Home</Link>
  </div>
</BrowserRouter>;

The links in ProductHistory look like this:

<Link to={`/products/${product.product_id}`}> {product.name}</Link>

So they match the Route path="/products/:product".

When I am on a product page and try to follow a ProductHistory link, the URL updates and a render occurs, but the component data doesn't change. In the Codesandbox example you can uncomment the alert in Product components render function to see that it renders when you follow the link, but nothing happens.

I don't know what the problem is...Can you explain the problem and find a solution? That would be great!

Along with componentDidMount, You also need to implement the componentWillReceiveProps or use getDerivedStateFromProps(from v16.3.0 onwards) in Products page since the same component is re-rendered with updated params and not re-mounted when you change the route params, this is because params are passed as props to the component and on props change, React components re-render and not re-mounted.

EDIT: from v16.3.0 use getDerivedStateFromProps to set/update state based on props(no need to specify it in two different lifecyle methods)

static getDerivedStateFromProps(nextProps, prevState) {
   if (nextProps.match.params.product !== prevState.currentProductId){
      const currentProductId = nextProps.match.params.product
      const result = productlist.products.filter(obj => {

        return obj.id === currentProductId;

      })
     return {

        product: result[0],
        currentId: currentProductId,
        result

      }
  }
  return null;
}

Prior v16.3.0, you would use componentWillReceiveProps

componentWillReceiveProps(nextProps) {
    if (nextProps.match.params.product !== this.props.match.params.product) {
      const currentProductId = nextProps.match.params.product
      const result = productlist.products.filter(obj => {

        return obj.id === currentProductId;

      })
      this.setState({

        product: result[0],
        currentId: currentProductId,
        result

      })
    }
  }

Working codesandbox

Tutorial: Intro to React – React, This tutorial doesn't assume any existing React knowledge. Before We Start the Tutorial. We will build a small game during this tutorial. You might be tempted to� React is a declarative, efficient, and flexible JavaScript library for building user interfaces. It lets you compose complex UIs from small and isolated pieces of code called “components”. React has a few different kinds of components, but we’ll start with React.Component subclasses: class ShoppingList extends React.

As Product component is already loaded it will not reload. You have to handle new product id in the below method of component

componentWillReceiveProps(nextProps) {
if(nextProps.match.params.name.product == oldProductId){
  return;
}else {
 //fetchnewProduct and set state to reload
}

With latest version of react(16.3.0 onwards)

static getDerivedStateFromProps(nextProps, prevState){
   if(nextProps.productID !== prevState.productID){
     return { productID: nextProps.productID};
  } 
  else {
     return null;
  }
}

componentDidUpdate(prevProps, prevState) {
  if(prevProps.productID !== this.state.productID){
     //fetchnewProduct and set state to reload
  }
}

React.Component – React, React doesn't force you to use the ES6 class syntax. The render() function should be pure, meaning that it does not modify component state, it returns the� My react app is not working on Internet explorer 11. It is working fine on edge and chrome. I have already created a lot of files and i do not think I can try npx create-react-app.( As pointed out in the other answers for similar questions) I have included this in both my index.js file but it does not work. import 'react-app-polyfill/ie11';

Although all the above-mentioned ways will work, I don't see a point to use getDerivedStateFromProps. Based on React docs, "if you want to re-compute some data only when a prop changes, use a memoization helper instead".

Here, instead, I would suggest simply using componentDidUpdate along with changing the Component to PureComponenet.

With reference to React docs, PureComponenets only rerender if at least one state or prop value changes. Change is determined by doing a shallow comparison of state and prop keys.

  componentDidUpdate = (prevProps) => {
    if(this.props.match.params.id !== prevProps.match.params.id ) {
      // fetch the new product based and set it to the state of the component
   };
  };

Error Boundaries – React, React doesn't need error boundaries to recover from errors in event handlers. Unlike the render method and lifecycle methods, the event handlers don't happen � Calling render() doesn't necessarily return anything. Inside the guts of React, I'm sure it's reasonable to state that the return statement is executed every single time render() is called. But from the perspective of someone who doesn't live inside the React engine, this function usually won't return anything at all.

If you aren't maintaining state in your component, you can use componentDidUpdate without the need for getDerivedStateFromProps:

  componentDidUpdate(prevProps) {
    const { match: { params: { value } } } = this.props
    if (prevProps.match.params.value !== value){
      doSomething(this.props.match.params.value)
    }
  }

What React Does (and Doesn't Do), What React Does. React is a UI library. It draws components on a web page. You write components as JavaScript functions or classes, pass them� A reaction is based in the moment and doesn’t take into consideration long term effects of what you do or say. A reaction is survival-oriented and on some level a defense mechanism. It might turn

Use React.memo() wisely, In this case, memoization doesn't provide benefits. Even if you wrap such a volatile component in React.memo() , React does 2 jobs on every� ‘Nice Young Woman From Wisconsin’ Doesn’t React Well to Getting Arrested in Portland. Posted at 12:00 pm on July 28, 2020 by Nick Arama

What React Does (and Doesn't Do), React cares exactly zero about styling. Think of it as generating the barebones HTML. React will put elements on the page, but everything after� (React uses the Object.is comparison algorithm.) > Note that React may still need to render that specific component again before bailing out. That shouldn’t be a concern because React won’t unnecessarily go ‘deeper’ into the tree. So it doesn’t always skip the rendering. I’ll update this part of the article. Thank you so much!

How to Optimize Components to Improve React Performance, How Does React Work? Before we dive into the optimization techniques, we need to have a better understanding of how React works. At the core of React� TLDR is that if you choose to polyfill Symbol (React doesn't require it), make sure this polyfill runs before both react and react-dom. So also put it before any other imports in the entry point file.

Comments
  • componentWillReceiveProps is now deprecated. But how else can you do it?
  • @BastianVoigt : You can use integration of new lifecycle methods in react +16.3 getDerivedStateFromProps, componentDidUpdate as described in this answer.
  • I tried the getDerivedStateFromProps solution. But it didn't work. It seems that the getDerivedStateFromProps only fires once on mount.
  • @arvinsim, Not true, getDerivedStateFromPRops is fired on initial mount as well as on every other update. Also there was a change in this API in 16.4. I will update my answer to incorporate that change
  • This pointed me in the right direction, thanks for the great answer.
  • ComponentWillReceiveProps is also deprecated and considered unsafe now... is there any other way to do it?
  • @BastianVoigt it should be prevProps as componentDidUpdate will be called after props has changed which will be same nextProps which we had set in getDerivedStateFromProps.
  • Right, but I would want to reload when the current productID (this.props.productID) is different from the one in my state, don't you think?
  • @BastianVoigt. Right that is what above condition does. The current productID(this.props.producID) will be having new porductID which we have had said in state variable. If we compare that then it will be always equal
  • In my case it's working for regular components too.
  • it also works for me without PureComponent, thanks!