question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[v6] Split location from navigation to prevent unnecessary re-rendering

See original GitHub issue

Good day!

The following is an idea, which would increase the performance of any app which is using react-router. Please keep in mind, that some of the following assumptions could be wrong. This is also based on the v6 code.

Currently we have one combined context called LocationContext, it stores:

interface LocationContextObject {
  action?: Action;
  location?: Location;
  navigator?: Navigator;
  static: boolean;
}

The ContextProvider is the <Router> component, which is also assigning those values here.

After taking a look at any Router implementation (MemoryRouter, BrowserRouter or HashRouter) I was seeing the same pattern, where the context updates:

let [state, setState] = React.useState({
  action: history.action,
  location: history.location
});

React.useLayoutEffect(() => history.listen(setState), [history]);

The context will update each time you navigate, but as you can see only the action and the location update, the navigator remains unchanged. This is important, because many hooks are depending on the LocationContext but are only using the navigator: useNavigate, useBlocker, useHref, and possibly more.

Yes I know, they’re using the useInRouterContext hook which is depending on the location, but this is only used to print error / warning messages and thus could be changed.

If there would be one context for location (and action) and one for navigation, then components which would use hooks where only the navigation is needed, would not update unnecessarily if the location changes, since navigation is static.

Actual Behavior

I noticed this behavior while experimenting with the router. Here is the Codesandbox example I did: https://codesandbox.io/s/charming-hooks-yotlj?file=/src/Admin.js

As you can see, the “renders” stay the same, no matter how many times you change the route. But as soon as I start using the useNavigate hook, they increase with each navigation: https://codesandbox.io/s/peaceful-faraday-32xke?file=/src/Admin.js

Thanks for reading!

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Reactions:6
  • Comments:8 (1 by maintainers)

github_iconTop GitHub Comments

2reactions
timdorrcommented, Aug 11, 2021

Fixed by #7936

0reactions
KingSoracommented, Aug 12, 2021

Thanks for implementing to everyone involved! 😃

Read more comments on GitHub >

github_iconTop Results From Across the Web

[v6] Split location from navigation to prevent unnecessary re ...
The context will update each time you navigate, but as you can see only the action and the location update, the navigator remains...
Read more >
How to prevent same component from re-rendering when ...
Starting react-router-dom v6, you can split your components and have them rendered only on speicifc routes. Your App.js should be like
Read more >
Amazing New Features In React & React Router v6 - Medium
Very useful and cool APIs in React Router v6 ... The above is standard code that is used to created routes for navigation...
Read more >
5 Ways to Avoid React Component Re-Renderings
In this article, I will discuss 5 methods to avoid unnecessary re-renderings in React components. 1. Memoization using useMemo() and UseCallback() Hooks.
Read more >
Ultimate React Router v6 Guide
The Navigate component shares all the props of the Link component so you can pass it the to , replace , and state...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found