How to do protected (authenticated vs. anonymous) routes?

I have an app that currently has two different <IonReactRouter>; one for logged-in users, and one for users who have not signed up yet.

Recently, I have been trying to combine them into a single <IonReactRouter>, but I need to deny access to certain routes to non-logged-in users.

Following this guide on protected routes in React, I came up with this component:

interface MyProps {
  children: JSX.Element,
  userObject: User,
  path: string,
  exact?: boolean,
}

// https://ui.dev/react-router-v5-protected-routes-authentication/
const AuthRoute: React.VFC<MyProps> = ({
  children, userObject, path, exact,
}: MyProps) => (
  <Route
    path={path}
    exact={exact}
    render={() => {
      if (userObject.userId > 0 && userObject.emailVerified) {
        if (hasAccessPaidFeatures(userObject)) {
          return children;
        }
        // Membership has expired.
        return <Redirect to={routeTabWelcome} />;
      }
      // User needs to log in.
      return <Redirect to={routeLogin} />;
    }}
  />
);

AuthRoute.defaultProps = {
  exact: false,
};

export default AuthRoute;

This works, but it introduces a slight flicker on every <AuthRoute>, which is annoying because it destroys the “native app” feeling that Ionic normally has.

How can I do access checks on routes with <IonReactRouter> without adding any flicker?

I experimented with this some more and tried using children instead of render:

const redirectByState = (children: JSX.Element, state: RouterUserAccessState) => {
  if (state === 'isNotLoggedIn') {
    return <Redirect to={routeLogin} />;
  }
  return children;
};

const AuthRoute: React.VFC<MyProps> = ({
  children, userAuthState, path, exact,
}: MyProps) => (
  <Route
    path={path}
    exact={exact}
  >
    { redirectByState(children, userAuthState) }
  </Route>
);

However, this very simple code also introduces flicker on every <AuthRoute>.

I’m still searching for a way to do protected routes with no flicker.