You could either:
1. Use the 2 routes to render the same component
both root/items and root/items/:itemId render the same ProductList component, you should check in the render function if the id in the route exists, and render conditionally the modal with the info. You have to check for the info in your server in componentDidMount() or shouldComponentUpdate(), have a look at how to implement those in the official docs.
- root/items: will display items
- root/items/:itemId: same component, but renders a modal with the info.
OR
2. Don't use routes, conditional render of another component
You can have a custom component (ProductInfo) that receives the id of the product as props and renders the info of the product. In the componentDidMount() function of ProductInfo you can query your server to get the info and display it. Now, in your product list component (ProductList) you can do conditional rendering of ProductInfo with the id passed in the props.
ProductInfo
// your imports here
class ProductInfo as Component {
constructor(){
this.state = {info:{}}
}
componentDidMount(){
// load info and set info in state using this.props.id
}
render(){
// check if info is set and render all the info however you like
return(){
<div>{JSON.stringify( this.state.info )}</div>
}
}
}
ProductList
//imports here
//import a Modal, or implement however you like, with bootstrap for example
import ProductInfo from './ProductInfo';
class ProductList as Component {
constructor(){
this.state = {infoId: -1}
}
changeId(e){
// get the id from the pressed button (or link or whatever component you are using)
// set the id in the state, remember to clean the state after the modal has been closed: set it back to -1.
}
render(){
// check if id is set
let {infoId} = this.state;
let renderModal = infoId > -1;
return(){
<div>
{renderModal &&
<Modal>
<ProductInfo id={infoId}/>
</Modal>
}
<ul>
<li>
<button
type={'button'}
name={'id1'}
onChange={(e) => this.changeId(e)}>
Info 1
</button>
</li>
<li>
<button
type={'button'}
name={'id2'}
onChange={(e) => this.changeId(e)}>
Info 2
</button>
</li>
<li>
<button
type={'button'}
name={'id3'}
onChange={(e) => this.changeId(e)}>
Info 3
</button>
</li>
</ul>
</div>
}
}
}
This is a simple example, there are many ways of doing this in better ways but I think this answers your question.
Prevent re-renders of components
If you are still having re rendering after these suggestions, you might be rendering every time the info is loaded. To prevent this, keep the info in the state and do a conditional rendering only when the info is loaded.
import api from './api'; // your custom api component to get data
class ProductList as Component {
constructor(){
this.state = {list:[], dataLoaded: false, infoId:-1}
}
...
componentDidMount(){
let myList = api.getList(); // basically call any function that gets your data
this.setState({
list:myList , dataLoaded: true
});
}
changeId(e){
// same as previous example
}
render(){
// only render list if data is loaded using conditional rendering
//
let {dataLoaded, list, infoId} = this.state;
let renderModal = infoId> -1;
return(
<div>
{renderModal &&
<Modal>
<ProductInfo id={infoId}/>
</Modal>
}
{dataLoaded &&
<ul>
<li>
// render your list data here using the variable list from the state
<li>
</ul>
}
</div>
);
}
}
This will prevent React on re-rendering the list even if you show the modal.