I have a Switch with a series of Route elements in my main container:
AppContainer.js
<Switch>
<Route exact path={`/app/:slug/`}>
<Redirect to={`/app/${slug}/home`} />
</Route>
<ProtectedRoute
path='/app/:slug/userAdmin/'
component={UserAdminContainer}
message={'This page is read-only'}
/>
[snip]
<Route
path='/app/:slug/protectedRoute/'
render={(props) => (
<ReadOnlyError message={props.message} />
)}
/>
</Switch>
Along with the ProtectedRoute.js
const ProtectedRoute = (props) => {
const { message } = props;
const { isReadOnlyUser } = useUser();
return (
isReadOnlyUser
?
<Redirect
to={{
pathname: '/app/:slug/protectedRoute/',
state: {message}
}}
/>
: <Route {...props} />
)
}
And the useUser
function
function useUser() {
const context = React.useContext(UserContext);
if (context === undefined) {
throw new Error(`User data is not provided to this component`);
}
return context;
}
My problem is that when AppContainer
renders, it is then immediately redirected to the ProtectedRoute
of "/admin"
, when it should only render if that button was hit. I’m a longtime Java dev, brand new to React. I’m sure there’s something about the rendering process I’m not understanding.
2
Answers
I think the issue is that the user isn’t loaded on the first render. This might happen if you need any server (or third party) communication for your user to load. With this assumption, one solution would be to wait until the user is loaded. Effectively, you’d probably want to separate the following scenarios:
If you prevent hitting the switch until the user is loaded, it should work.
What typically happens is that the initial "auth" condition incorrectly matches either the confirmed authenticated or unauthenticated states. In other words, it’s not simply a binary decision, but that there are actually 3 options: "confirmed authenticated", "confirmed unauthenticated", and "we don’t know yet". Unless you are able to directly determine and initialize the
isReadyOnlyUser
state into one of the "confirmed" cases, you’ll want to initialize to the "unknown" case using a value that neither indicates a user is authenticated nor unauthenticated, and then explicitly check this condition and conditionally return early and not render the protected content or redirect until auth status is confirmed.Example, a "confirmed"
isReadOnlyUser
is a booleantrue|false
value, so a great "unknown" initial value would beundefined
.