Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React router remounts children while changing routes (without reconciliation)

I have a situation where few routes consists of the same component and I want to preserve its state, but with this behavior it's fairly impossible.

Live example (look at seconds elapsed): https://csb-43lp1km647-nkiinaibit.now.sh

CodeSandbox: https://codesandbox.io/s/43lp1km647

Of course I could save and restore state of timer while changing routes, but my app has an infinite CSS transition as a background (not on every route).

I was trying adding keys, even portal, but it still remounts everything.

Is there any way to enforce typical React's reconciliation (remount only elements that have to be remounted)?

Update: Just found out that <Switch /> will render everything until it finds element that matches, and that could be either a certain <Route /> or any element except it's inside <Fragment />.

Code:

<Router history={history}>
  <Switch>
    <Route path="/third" component={RouteWithoutTimer} />
    <React.Fragment>
      <Timer />
      <Route exact path="/" component={FirstRoute} />
      <Route path="/second" component={SecondRoute} />
    </React.Fragment>
  </Switch>
</Router>

Edit React router remounts children while changing routes

Or with wildcard route:

<Router history={history}>
  <Switch>
    <Route path="/third" component={RouteWithoutTimer} />
    <React.Fragment>
      <Timer />
      <Switch>
        <Route exact path="/" component={FirstRoute} />
        <Route component={NotFoundRoute} />
      </Switch>
    </React.Fragment>
  </Switch>
</Router>

It's not a solution I was looking for, but it works fine.

like image 819
Artur Avatar asked Jun 02 '18 18:06

Artur


People also ask

How do you prevent people from going back in React Dom router?

Using componentDidUpdate method of React page lifecycle, you can handled or disabled go back functionality in browser. basically componentDidUpdate method will call automatocally when component got updated. so once your component is updated you can prevent to go back as below.

How do I restrict access to routes in React router?

To restrict access to routes in React Router, we set the render prop to a function that renders the component we want according to the condition we're checking. import { Route, Redirect } from "react-router"; <Route exact path="/" render={() => (loggedIn ?

How do I stop route change in React?

for more information you can read the documentation. @vsync docs Instead of conditionally rendering a <Prompt> behind a guard, you can always render it but pass when={true} or when={false} to prevent or allow navigation accordingly. This is no longer the case with Router v6, unfortunately as Prompt was removed.


Video Answer


1 Answers

You are mounting a new instance of Timer in each route.
If you want to share a component across routes, you should lift it to the parent component of the routes:

<React.Fragment>
  <Timer />
  <Switch>
    <Route exact path="/" component={FirstRoute} />
    <Route path="/second" component={SecondRoute} />
  </Switch>
</React.Fragment>

Edit React router remounts children while changing routes

like image 67
Roy Wang Avatar answered Nov 15 '22 18:11

Roy Wang