Home > Software engineering >  Why am I getting "Objects are not valid as a React child" error?
Why am I getting "Objects are not valid as a React child" error?

Time:01-06

I have a lot of files, but I think the problem is coming from my authentication component in React. I basically want to only display a page if the user is logged in otherwise I want to the user to be redirected.

react-dom.development.js:14887 Uncaught Error: Objects are not valid as a React child (found: object with keys {$$typeof, type, compare, WrappedComponent}). If you meant to render a collection of children, use an array instead.

requireAuth.js

// function that can wrap any component to determine if it is authenticated

import React, { Component } from "react";
import { connect } from "react-redux";
import PropTypes from "prop-types";
import { push } from "@lagunovsky/redux-react-router"; // not sure if this correct
export default function requireAuth(Component) {
  class AuthenticationComponent extends React.Component {
    constructor(props) {
      super(props);
      this.checkAuth();
    }
    componentDidUpdate(prevProps, prevState) {
      this.checkAuth();
    }

    checkAuth() {
      // if not authenticated then it is redirected
      if (!this.props.isAuthenticated) {
        const redirectAfterLogin = this.props.location.pathname;
        this.props.dispatch(push(`/login?next=${redirectAfterLogin}`));
      }
    }
    // if authenticated then renders the component
    render() {
      return (
        <div>
          {this.props.isAuthenticated === true ? (
            <Component {...this.props} />
          ) : null}
        </div>
      );
    }
  }

  AuthenticationComponent.propTypes = {
    isAuthenticated: PropTypes.bool.isRequired,
    location: PropTypes.shape({
      pathname: PropTypes.string.isRequired,
    }).isRequired,
    dispatch: PropTypes.func.isRequired,
  };

  // checks isAuthenticated from the auth store
  const mapStateToProps = (state) => {
    return {
      isAuthenticated: state.auth.isAuthenticated,
      token: state.auth.token,
    };
  };

  return connect(mapStateToProps)(AuthenticationComponent);
}

App.js

class App extends Component {
  render() {
    return (
      <div>
        <Root>
          <ToastContainer hideProgressBar={true} newestOnTop={true} />
          <Routes>
            <Route exact path="/" element={<Home />} />
            <Route path="/closet" element={requireAuth(Closet)} />
            <Route path="*" element={<NotFound />} />
          </Routes>
        </Root>
      </div>
    );
  }
}

I have done some digging but I can't find a problem like this.

CodePudding user response:

The error is because on this line:

<Route path="/closet" element={React.createComponent(requireAuth(Closet))} />

You're passing the actual class definition to the element prop and not an instance of the class (which would be the React component). To fix this, you can use React.createElement:

class App extends Component {
  render() {
    return (
      <div>
        <Root>
          <ToastContainer hideProgressBar={true} newestOnTop={true} />
          <Routes>
            <Route exact path="/" element={<Home />} />
            <Route path="/closet" element={React.createElement(requireAuth(Closet))} />
            <Route path="*" element={<NotFound />} />
          </Routes>
        </Root>
      </div>
    );
  }
}

CodePudding user response:

Because Route's element props need a ReactNode,But requireAuth(Closet)'s type is () => React.ReactNode, you can change your App.js like this:


const AuthComponent = requireAuth(Closet);

class App extends Component {
  render() {
    return (
      <div>
        <Root>
          <ToastContainer hideProgressBar={true} newestOnTop={true} />
          <Routes>
            <Route exact path="/" element={<Home />} />
            <Route path="/closet" element={<AuthComponent />} />
            <Route path="*" element={<NotFound />} />
          </Routes>
        </Root>
      </div>
    );
  }
}
  • Related