I am working on an application where I need to change the url of the page without causing a re-render.
I am making a call to fetch all the pages inside componentDidMount like this
componentDidMount() {
axios.get('/pages')
.then(response => {
this.setState({
pages: response.data,
slugs: response.data.pages.map(item => Slug(item.title))
})
})
Once I have all the pages then I want to show the individual pages.
For eg. in the url it has to be like /page/1/slug-for-page-1
and /page/2/slug-for-page-2
based on a state variable activePageNumber
and the active page content will be displayed. Also the corresponding slug should be there on the url.
I tried adding a callback after setState like below, but it didn't work.
() => this.props.history.push({
pathName: '/page',
state: {activePageNumber : activePageNumber},
})
I thought of adding a child component to manage the activePageNumber state, but I am not sure if its the best way to do it and whether it'll prevent the re-render.
I can implement it such that each page make a separate request to the backend, but I wish to call it only once, and then update the url based on the active page number.
I am not sure how to implement this in react.
I have the following versions
"react-router-dom": "^5.0.0"
"react": "^16.8.6"
If you define your /page
route like this:
<Route
path="/page/:number"
component={({ match }) => (
<Pages activePageNumber={match.params.number} />
)}
/>
The Pages
component method componentDidMount
will be called when you switch from, for example, /home
to /page/1
, but will not be called when you switch from /page/1
to /page/2
, because the DOM elements inside the /page/:number
Route remain of the same type. I suggest you read React's documentation on reconciliation for a better explaination.
So you can safely put the call to your /pages
service inside of the Pages
component, and then in its render method display the page you need based on the activePageNumber
prop.
class Pages extends React.Component {
constructor(props) {
super(props);
this.state = {
pages: null,
};
}
componentDidMount() {
axios.get('/pages')
.then(response => {
this.setState({
pages: response.data
})
});
}
render() {
const { pages } = this.state;
const { activePageNumber } = this.props;
return pages ? (
<Page page={pages[activePageNumber]} />
) : (
<div>loading...</div>
);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With