girtri
girtri

Reputation: 777

React router 4, path with parameter

I'm trying to learn react-router-dom (react router version 4.x).
I don't understand the behavior of a route with a parameter and I show a simple example.
I have a list of links of defined routes like this:

<li>Link to='/'>Home</Link></li>
<li>Link to='/product/1'>Product 1 details</Link></li>
<li><Link to='/product/2'>Product 2 details</Link></li>

and I have a route definition like this:

<Switch>
    <Route exact path='/' component={Home}/>
    <Route path='/product/:number' component={Product}/>
</Switch>

now if run my web page and click on link "Product 1 details" I show a test "Product" component where I return "Product number 1" (composing text reading from props.match.params.number).
Then if I click on link "Product 2 details" it still show me "Product number 1"!

It seems that route doesn't change anymore if it starts with "product": if I click on "home" link and then on "Product 2 details" then it refresh and works.
I would like to be able to force the product page refresh, is it possible?
Thanks in advance

Upvotes: 2

Views: 2014

Answers (3)

girtri
girtri

Reputation: 777

product component here:

import * as React from 'react';

export default class Product extends React.Component<any, any>
{
    render() {
        return (
            <div>
                Product number { this.props.match.params.number}
            </div>
        );
    }
}

Upvotes: 0

Jo&#227;o Cunha
Jo&#227;o Cunha

Reputation: 10307

As you can see in the snippet below it works as you wish.

Have you encapsulated the Switch component in a Router? (HashRouter or BrowserRouter) That seems to be the issue.

Even if I repeat the Home component on Product and click the same links the app behaves as it is supposed to. (btw don't repeat the Home component on the Product component it was a way to examplify stuff)

const Home = () => (
  <ul>
    <li><ReactRouterDOM.Link to='/'>Home</ReactRouterDOM.Link></li>
    <li><ReactRouterDOM.Link to='/product/1'>Product 1 details</ReactRouterDOM.Link></li>
    <li><ReactRouterDOM.Link to='/product/2'>Product 2 details</ReactRouterDOM.Link></li>
  </ul>  
);

const Product = props => (
  <div>
    <Home />
    <p>{props.match.params.number}</p>
  </div>
);

const App = () => (
  <ReactRouterDOM.HashRouter>
    <ReactRouterDOM.Switch>
      <ReactRouterDOM.Route exact path='/' component={Home}/>
      <ReactRouterDOM.Route path='/product/:number' component={Product}/>
    </ReactRouterDOM.Switch>
  </ReactRouterDOM.HashRouter>
);

ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://unpkg.com/react-router/umd/react-router.min.js"></script>
<script src="https://unpkg.com/react-router-dom/umd/react-router-dom.min.js"></script>

<div id="root"></div>

Upvotes: 1

ferronsays
ferronsays

Reputation: 134

Without seeing your Product component this is difficult to answer -- if you are accessing and storing the number parameter in the constructor or componentWillMount lifecycle method, those will not execute again when the route changes since you are not loading a new component despite the "new" route. React is simply updating the props being sent to the current instance of the Product component.

Try rendering the Product number X directly in your Product component render function, like this:

<span>Product number { this.props.match.params.number }</span>

If you would like to store this in your component state or as an instance property, look for it to update in one of the other lifecycle methods like componentWillReceiveProps.

Upvotes: 0

Related Questions