hookrouter
hookrouter copied to clipboard
Children routes components remount every route change
I'm using the example in the documentation
import React, {useEffect} from 'react'
import {FocusStyleManager} from '@blueprintjs/core'
import {A, useRoutes} from 'hookrouter'
const AboutArea = () => {
const routeResult = useRoutes({
'/people': () => 'We are happy people',
'/company': () => 'Our company is nice',
})
useEffect(() => {console.log('AboutArea mounted')}, [])
return (
<div className="about">
<A href="people">About people</A>
<A href="company">About our company</A>
{routeResult}
</div>
)
}
const App = () => {
const routeResult = useRoutes({
'/': () => 'Home',
'/about*': () => <AboutArea/>,
})
useEffect(() => {console.log('App mounted')}, [])
return (
<div>
<A href="/about/people">Show about area</A>
{routeResult || 404}
</div>
)
}
export default App
If you try to change route the AboutArea component will mount on every route change. This is a problem in the moment that I want to make api calls in the AboutArea component and share results with children. am I doing something wrong or is an issue?
https://github.com/Paratron/hookrouter/issues/61#issuecomment-528069797
This has been raised before and should be seriously considered given the drawbacks
Sorry, I had responded by mail a couple of days ago already - sadly my mail response appearently did not may its way here. But here is my original response:
Without having looked deeply into your code: a huge warning sign is that you are re-creating new route objects upon each render of your components.
Always declare your route objects as constants outside of your components. Its been written that way in the example as well - and there is even a note about this in the docs.
I am 90% sure this will make your problem go away.
Hi Paratron, thanks for maintaining this project :-)
I'm having the same problem and it's not only due to re-creating new route objects.
There was a change in router.js (8f3a17868449515ea330d9d30a29561857f47845 - Do performance optimizations ). Here the resultFunc and resultProps were removed from
- the assignment to the stackObj (line 301 + 302) in process()
- construction of stackObj (line 343 + 345) in useRoutes()
As far as I can see this means that those are always null in process() now and the effect is that
- funcsDiffer is always true
- propsDiffer is always true
- setUpdate(Date.now()); will always be called by the end of process() and that will re-mount components on every route change
Please have a look at this :-)
Downgrading to 1.2.0 (which is before the mentioned change) solves the problem
Thanks for pointing this out. I'll have a look.
Having the same problem; downgrading to 1.2.0 also fixed it for me. I realize that in some cases performance hit is negligible, but when it comes to this like using CSS transitions for child components it becomes a deal-breaker issue.
This bug bit me too late. I have routes in constants outside of function components. And nested routing produces re-rendering of the parent component when I switch to one of its sub-routes. And downgrading to 1.2.0 doesn't helps.
Same problem here. Downgrading to 1.2.0 also fixed it for me. I love this library and would be nice to know if we are doing something wrong...
Here is a basic example of the problem in codesandbox.io If you navigate to "/about" page renders the current time and switching between "/people" and "company" remounts AboutPage. If you change the dependency version from 1.2.3 -> 1.2.0 the parent component is not re-mounted on route changed anymore.
If downgrading to 1.2.0 doesn't help then see if some ancestor component is using usePath()
without the active
parameter set to false
.
From the docs
The hook will automatically render the component again, if the path changes. If you don't need that, you can use the hook in passive mode: usePath(false) and it just returns the current path when the component renders and does not trigger renders upon path change.
https://github.com/Paratron/hookrouter/blob/master/src-docs/pages/en/04_other-features.md#using-the-uri-path
I tried moving the routes objects as a constant outside of the class, and set usePath(false), but none of it fix the re-rendering problem with child route navigate.
Downgrading to 1.2.0 works.