erictaylor / yarr

A React router library enabling the render-as-you-fetch concurrent UI pattern.
MIT License
141 stars 11 forks source link

When the page is changed, the existing page is called additionally #24

Closed wickedev closed 2 years ago

wickedev commented 2 years ago

When using ReactDOM.hydrateRoot or ReactDOM.createRoot, clicking <Link /> will cause unnecessary rendering. Of course I could use ReactDOM.render, but as you know it will display a warning message like below.

Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot

Minimal, Reproducible Example

erictaylor commented 2 years ago

@wickedev could you provide more context around what you mean by unnecessary rendering? What is the behavior you are expecting, and what instead happens?

wickedev commented 2 years ago

stackblitz link

If I use the legacy API render, when open the page HomePage is called twice. And when About Link is clicked, AboutPage is called once. However, if I use hydrateRoot or createRoot, which are recommended concurrency mode APIs, HomePage is called twice, then when About Link is clicked, HomePage is called once and AboutPage is called once.

The behavior I expect is that HomePage is called only once when the first page is loaded, and then the existing page is not called additionally even when a link is clicked.

Perhaps What is tearing? #69 seems to be related.

render version

image

hydrateRoot or createRoot version

image
wickedev commented 2 years ago

After digging a bit more, It looks like a re-rendering due to a state change inside the RouteRenderer. I solved it by wrapping the page component with memo. How about wrapping a page component with memo as the default behavior?

jakobvase commented 2 years ago

React 18 with strict mode in dev will render components twice: https://github.com/facebook/react/issues/24467. And the render after clicking the <Link> component is fixed by adding memo. I think this issue can be closed.