Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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!

like image 254
Galivan Avatar asked Jan 07 '18 16:01

Galivan


People also ask

How do you force reload a component in react?

If set to true, the browser will do a complete page refresh from the server and not from the cached version of the page. import React from 'react'; function App() { function refreshPage() { window. location. reload(false); } return ( <div> <button onClick={refreshPage}>Click to reload!

How does route determine react changes?

To detect route change with React Router, we can use the useLocation hook. import { useEffect } from "react"; import { useLocation } from "react-router-dom"; const SomeComponent = () => { const location = useLocation(); useEffect(() => { console. log("Location changed"); }, [location]); //... };

Can we refresh a component in react?

React gives us two options in which we can reload a component. Either we can reload a component using the Vanilla JavaScript , or we can use the state to reload the component whenever a change is made in the state of that component.


1 Answers

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

like image 124
Shubham Khatri Avatar answered Sep 18 '22 19:09

Shubham Khatri