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.

bug: react - maximum depth exceeded from PrivateRoute

See original GitHub issue

Bug Report

Ionic version: [ ] 4.x [x] 5.x

Current behavior: Redirecting from a PrivateRoute causes “Maximum update depth exceeded”.

Expected behavior: Redirect to, for example, a “/login” page.

I have been trying to use the PrivateRoute pattern described here without success.

Steps to reproduce:

ionic start ionic-react-redirect-bug conference --type=react cd ionic-react-redirect-bug

Add the following to src/App.tsx:

interface PrivateRouteProps extends RouteProps {
  component: any;
}

const PrivateRoute = ({component: Component, ...rest}: PrivateRouteProps) => {
  const isLoggedIn = false;

  return (
    <Route
      {...rest}
      render={(routeProps) =>
        isLoggedIn ? (
          <Component {...routeProps} />
        ) : (
          <Redirect to={{pathname: "/login", state: {from: routeProps.location}}}/>
        )
      }
    />
  );
}

In src/App.tsx replace:

<Route path="/support" component={Support} />

with:

<PrivateRoute path="/support" component={Support} />

Comment out useEffect in src/components/Map.tsx if it complains about anything (unrelated to this issue).

ionic serve

Click the Support menu item.

Other information:

In the browser console:

Uncaught Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.
    React 4
    unlisten react-router.js:69
    listener history.js:162
    notifyListeners history.js:180
    notifyListeners history.js:179
    setState history.js:300
    replace history.js:414
    confirmTransitionTo history.js:152
    replace history.js:397
    onUpdate react-router.js:309
    componentDidUpdate react-router.js:189
    React 6
    unstable_runWithPriority scheduler.development.js:659
    React 5
    unstable_runWithPriority scheduler.development.js:659
    React 6

Ionic info:

Ionic:

   Ionic CLI       : 6.10.1 (/usr/local/lib/node_modules/@ionic/cli)
   Ionic Framework : @ionic/react 5.2.3

Capacitor:

   Capacitor CLI   : 1.3.0
   @capacitor/core : 1.3.0

Utility:

   cordova-res : not installed
   native-run  : 1.0.0

System:

   NodeJS : v14.4.0 (/usr/local/Cellar/node/14.4.0/bin/node)
   npm    : 6.14.6
   OS     : macOS Catalina

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:2
  • Comments:18 (9 by maintainers)

github_iconTop GitHub Comments

1reaction
sean-perkinscommented, Nov 11, 2022

Awesome, I am going to close this issue out as completed, as the main issue reported is resolved.

If any run into any other issues, feel free to open a new issue and the team would be happy to take a look.

1reaction
sean-perkinscommented, Nov 10, 2022

Hello @m3thom looking into this issue again.

I believe the routing structure may be a driving factor to the issue here.

The /login page does not fit within mobile tabs navigation rules. The route is a root route, but is being rendered inside of the tabs router outlet, having the tab bar being displayed when the route is active. The tab bar should only be displayed for tab pages, or sub-pages of tabs (that are within the stack).

There are two valid solutions I see with this use case:

Login is a root route outside of the tabs outlet

Treating the /login page as a page outside of the tabs outlet will result in the page being full height (not displaying the tab bar). This pattern is most often use when the entire tabs experience is protected by authentication.

e.g.:

const App: React.FC = () => (
  <ProvideAuth>
    <IonApp>
      <IonReactRouter>
        <IonRouterOutlet>
          <Route exact path="/login">
            <Login />
          </Route>
          <IonTabs>
            <IonRouterOutlet>
              <Route exact path="/tab1">
                <Tab1 />
              </Route>
              <Route exact path="/tab2">
                <Tab2 />
              </Route>

              <PrivateRoute path="/tab3">
                <Tab3 />
              </PrivateRoute>

              <Route exact path="/">
                <Redirect to="/tab1" />
              </Route>
            </IonRouterOutlet>
            <IonTabBar slot="bottom">
              <IonTabButton tab="tab1" href="/tab1">
                <IonIcon icon={triangle} />
                <IonLabel>Tab 1</IonLabel>
              </IonTabButton>
              <IonTabButton tab="tab2" href="/tab2">
                <IonIcon icon={ellipse} />
                <IonLabel>Tab 2</IonLabel>
              </IonTabButton>
              <IonTabButton tab="tab3" href="/tab3">
                <IonIcon icon={square} />
                <IonLabel>Tab 3</IonLabel>
              </IonTabButton>
            </IonTabBar>
          </IonTabs>
        </IonRouterOutlet>
      </IonReactRouter>
    </IonApp>
  </ProvideAuth>
);

<video src="https://user-images.githubusercontent.com/13732623/201206944-952dfece-c028-4397-9cdb-fa9455cf33e2.mp4"></video>

I did have to tweak some of the logic around the location state, repro: https://github.com/sean-perkins/ionic-gh-21717

Use a modal in place of a protected route

If the true desire is to allow unauthenticated users to access tab 1 and tab 2, but have to sign into access tab 3, a modal experience that takes over the fullscreen when tab 3 is activated would be desired.

I experimented with trying to render the private route inside of the tab3 routing structure, but this leads to other problems, that activating the tab bar button for tab3 attempts to route to /tab3, but is redirected to /tab3/login when unauthenticated. This results in a push transition which looks bad and is probably an anti-pattern for navigation.

Can you try either of these suggestions and let me know if that resolves your issue or if you observe anything else?

Read more comments on GitHub >

github_iconTop Results From Across the Web

React private Route infinite render - Getting error Error
Error : Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or ...
Read more >
React App Login Error : Maximum update depth exceeded ...
Coding example for the question React App Login Error : Maximum update depth exceeded-Reactjs.
Read more >
The Complete Guide to React User Authentication with Auth0
Learn how to add user authentication to React using Context and Hooks. ... Uncaught (in promise) Error: Maximum update depth exceeded.
Read more >
Fix the "Maximum Update Depth Exceeded" Error in React
Fix the "Maximum Update Depth Exceeded" Error in React. Nick Scialli April 13, 2021. React is an excellent framework, but it can have...
Read more >
react-dom.development.js:18687 the above error occurred in ...
Uncaught Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate.
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