Reputation: 2950
I have the following index.js
file which handles routing:
import React from "react";
import ReactDOM from "react-dom";
import "bootstrap/dist/css/bootstrap.css";
import "./global.css";
import Login from "./pages/Login/Login";
import { Provider } from "react-redux";
import configureStore, { history } from "./store";
import { Route, Switch } from "react-router";
import * as serviceWorker from "./serviceWorker";
import { ConnectedRouter } from "connected-react-router";
import Home from "./pages/Home/Home";
import AuthProvider from "./AuthProvider";
import IsLoggedIn from "./components/auth/IsLoggedIn";
import IsNotLoggedIn from "./components/auth/IsNotLoggedIn";
const store = configureStore();
ReactDOM.render(
<Provider store={store}>
<AuthProvider>
<ConnectedRouter history={history}>
<Switch>
<Route exact path="/" component={() => <IsNotLoggedIn component={Login} redirect="/Home"/>}/>
<Route path="/Login" component={() => <IsNotLoggedIn component={Login} redirect="/Home"/>}/>
<Route path="/Home" component={() => <IsLoggedIn component={Home} redirect="/Login"/>} />
<Route render={() => <div>Not Found</div>} />
</Switch>
</ConnectedRouter>
</AuthProvider>
</Provider>,
document.getElementById("root")
);
serviceWorker.unregister();
Which is surrounded by a component called AuthProvider
:
import React, { useEffect } from "react";
import { connect } from "react-redux";
import { getAuth } from "./authSlice";
const AuthProvider = (props) => {
const {dispatch, children} = props;
console.log(props, "AUTH PROPS");
useEffect(() => {
dispatch(getAuth());
}, []);
return <>{children}</>;
};
const mapStateToProps = (state) => {
return state.auth;
};
export default connect(mapStateToProps)(AuthProvider);
This is so we can retrieve auth details on every page load.
Now if you look at my routes, I've created two components to handle the redirection depending on authentication: IsLoggedIn
and IsNotLoggedIn
, both of which are very similar. Here is IsLoggedIn
:
import React from "react";
import { connect } from "react-redux";
import { Redirect } from "react-router";
const IsLoggedIn = (props) => {
const { component, auth, redirect } = props;
if(auth.authenticated) {
return component;
}
return <Redirect to={redirect}/>
};
const mapStateToProps = (state) => {
return {
auth: state.auth,
};
};
export default connect(mapStateToProps)(IsLoggedIn);
This worked fine when I tested it with just one of the routes, Home
. When I tried adding it to the rest, as you see in the code above, I get the followings error:
×
Error: Objects are not valid as a React child (found: object with keys {$$typeof, type, compare, WrappedComponent, displayName}). If you meant to render a collection of children, use an array instead.
in IsNotLoggedIn (created by ConnectFunction)
in ConnectFunction (at src/index.js:23)
in component (created by Context.Consumer)
in Route (at src/index.js:23)
in Switch (at src/index.js:22)
in Router (created by ConnectedRouter)
in ConnectedRouter (created by Context.Consumer)
in ConnectedRouterWithContext (created by ConnectFunction)
in ConnectFunction (at src/index.js:21)
in AuthProvider (created by ConnectFunction)
in ConnectFunction (at src/index.js:20)
in Provider (at src/index.js:19)
Upvotes: 1
Views: 449
Reputation: 4988
Your problem is most likely here:
const IsLoggedIn = (props) => {
const { component, auth, redirect } = props;
if(auth.authenticated) {
return component;
}
return <Redirect to={redirect}/>
};
You receive a component as props (the component itself, not a react element) and instead of rendering it in JSX you return it. The component itself is an object, you need to render it to avoid this error:
const IsLoggedIn = (props) => {
// Components need to start with uppercase letters
const { component: Component, auth, redirect } = props;
if(auth.authenticated) {
return <Component />;
}
return <Redirect to={redirect}/>
};
Let me know if this works now, or if you have any other issues.
Upvotes: 1