I am trying to understand the nuances behind a specific warning I see when working with React Router. I was trying to setup conditional routing based on whether or not the User was logged in or not. My code is as follows:
// AppRoutes.js
export const AppRoutes = ({ machine }) => {
const [state] = useMachine(machine);
let routes;
if (state.matches('authenticated')) {
routes = (
<React.Fragment>
<Route exact path="/"><HomePage /></Route>
<Route path="/contacts"><ContactsList /></Route>
</React.Fragment>
);
} else if (state.matches('unauthenticated')) {
routes = (
<Route path="/">
<LoginPage service={state.children.loginMachine} />
</Route>
);
} else {
routes = null;
}
return (
<BrowserRouter>
<Switch>{routes}</Switch>
</BrowserRouter>
);
};
Internally, the HomePage component redirects to /contacts
// HomePage.js
export const HomePage = () => {
return <Redirect to="/contacts" />;
};
Now with this code, the application works as I need it to, but I get a warning logged in the console:
Warning: <Route> elements should not change from controlled to uncontrolled (or vice versa). You provided a "location" prop initially but omitted it on a subsequent render.
I did some research and the only thing I could find was this https://stackoverflow.com/a/52540643 which seems to indicate that conditionally rendering the routes is causing the issue. However, conditional rendering of routes is the whole point -- I don't want unauthenticated users accessing /contacts
Then after some playing around, I modified the source as below:
// AppRoutes.js
export const AppRoutes = ({ machine }) => {
const [state] = useMachine(machine);
let routes;
if (state.matches('authenticated')) {
routes = (
<React.Fragment>
<Route path="/home">
<HomePage />
</Route>
<Route path="/contacts">
<ContactsList />
</Route>
<Redirect to="/home" />
</React.Fragment>
);
} else if (state.matches('unauthenticated')) {
routes = (
<React.Fragment>
<Route path="/login">
<LoginPage service={state.children.loginMachine} />
</Route>
<Redirect to="/login" />
</React.Fragment>
);
}
return (
<BrowserRouter>
<Switch>{routes}</Switch>
</BrowserRouter>
);
};
// HomePage.js
export const HomePage = () => {
return <Redirect to="/contacts" />;
};
Now this code redirects authenticated users to /contacts and unauthenticated users to /login, and doesn't log any warnings.
Everything works great, except I still don't understand why the warning no longer appears and how is this different from what I was doing earlier. As far as I can see and understand, I am doing conditional rendering of routes in both versions of the code. Why does one log a warning, while the other doesn't?
Any guidance??
Thanks!