ThePerplexedOne
ThePerplexedOne

Reputation: 2950

"Objects are not valid as a React child" when trying to redirect with valid/no authentication

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

Answers (1)

hiddenuser.2524
hiddenuser.2524

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

Related Questions