0

The server sends a 401 response if the user is not authenticated and I was trying to check for authentication in the front end using a HOC as seen in Performing Authentication on Routes with react-router-v4. However, I am getting an error saying TypeError: Cannot read property 'Component' of undefined in RequireAuth

RequireAuth.js

import {React} from 'react'
import {Redirect} from 'react-router-dom'

const RequireAuth = (Component) => { 

    return class Apps extends React.Component { 
        state = {
            isAuthenticated: false,
            isLoading: true
        }

        async componentDidMount() {
            const url = '/getinfo'
            const json = await fetch(url, {method: 'GET'})
            if (json.status !== 401)    
                this.setState({isAuthenticated: true, isLoading: false})
            else
                console.log('not auth!')
        } 

        render() { 
           const { isAuthenticated, isLoading } = this.state;
           if(isLoading) {
               return <div>Loading...</div>
           }
           if(!isAuthenticated) {
               return <Redirect to="/" />
           }
           return <Component {...this.props} /> 
        }
    } 

} 

export { RequireAuth }

App.js

import React from 'react';
import { BrowserRouter as Router, Route, Switch, withRouter } from 'react-router-dom';
import SignIn from './SignIn'
import NavigationBar from './NavigationBar'
import LandingPage from './LandingPage'
import Profile from './Profile'
import Register from './Register'
import { RequireAuth } from './RequireAuth'

class App extends React.Component {
  constructor(props) {
    super(props);
  }

  render() { 
  return (
    <div>
      <Router>
            <NavigationBar />
            <Switch>
              <Route exact path = '/'
                component = {LandingPage}
              />
              <Route exact path = '/register'
                component = {Register}
              />
              <Route exact path = '/profile' 
                component = {RequireAuth(Profile)}
              />
              <Route path="*" component = {() => "404 NOT FOUND"}/>
            </Switch>
      </Router>
    </div>
  );
}
}

export default withRouter(App);

xyz6675
  • 355
  • 2
  • 6
  • 17
  • On line three of `App.js` above you're having `App` extend `React.Component` but you haven't imported `React` into that file yet. This might be why you're getting the error `TypeError: Cannot read property 'Component' of undefined`-- because `React` is undefined in this context? Although I guess I would expect in this context that you'd get a `ReferenceError` not a `TypeError`. – Alexander Nied Jun 08 '20 at 01:49
  • I had not copied the import statements but that is not the issue. Updated the post! – xyz6675 Jun 08 '20 at 01:55

2 Answers2

1

I can think of some possibilities:

------- Moved this to top which eventually fixed OP's issue -------

  1. Try remove the curly braces at {React},
import React from 'react';

------- Moved this to top which eventually fixed OP's issue -------


  1. In RequireAuth.js, Try
const RequireAuth = ({ Component }) => {} // changed from Component to { Component }

In App.js, use Component start with capital letter

<Route exact path = '/' Component = {LandingPage}/>


  1. Also, in <Route path="*" component = {() => "404 NOT FOUND"}/>, looks like you're not passing in a React component because the function is not returning a JSX (I can't test now so I'm not very sure, though).

try this instead:

() => <div>404 NOT FOUND</div>

or if it doesn't work, define a functional component externally and pass into the Route:

const NotFoundComponent = () => <div>404 NOT FOUND</div>
<Route path="*" component = {NotFoundComponent}/>
Andus
  • 1,713
  • 13
  • 30
  • @xyz6675 sry, `component`, according to your code, small letter, updated my answer – Andus Jun 08 '20 at 01:57
  • I changed that and then I had to change the line ``` return ``` but then was getting the same error – xyz6675 Jun 08 '20 at 04:05
  • Yes you have to, or you can remain capital letter and use capital also in your route like `Component={LandingPage}` – Andus Jun 08 '20 at 04:15
  • Also, in ` "404 NOT FOUND"}/>` you're not passing in a component, maybe that's one of the cause too – Andus Jun 08 '20 at 04:16
  • @xyz6675 updated my answer again, hope it helps you – Andus Jun 08 '20 at 04:23
  • Sorry, appreciate the effort but it still does not go through – xyz6675 Jun 08 '20 at 05:51
  • @xyz6675 last suggestion, try remove the curly braces: `import React from 'react';`, just figured out this classical mistake, couldn't help if that doesn't work :P – Andus Jun 08 '20 at 05:58
  • 1
    Yes it worked, can't believe that tiny issue! Thank you so much! – xyz6675 Jun 08 '20 at 07:09
  • Glad it helps, I edited by answer for better reading for whom may have the same issue – Andus Jun 08 '20 at 07:15
  • What can I do if I need to pass another prop to requireAuth from App? – xyz6675 Jun 10 '20 at 01:42
  • 1
    @xyz6675 `const RequireAuth = ({ Component, anotherProp }) => {}` – Andus Jun 10 '20 at 01:43
  • Is there any way I can send the status of Authenticated/Not Authenticated to NavigationBar so that I render conditionally there? – xyz6675 Jun 10 '20 at 02:22
  • @xyz6675 Yes, but it's a little too out of scope of this question and it's hard to reply in the comment section. Maybe you can open a new question for that. – Andus Jun 10 '20 at 02:25
  • Made a new post: https://stackoverflow.com/questions/62294873/how-to-use-isauthenticatedstatus-in-hoc-to-send-to-navigationbar-to-render-condi – xyz6675 Jun 10 '20 at 02:30
  • @xyz6675 You'll need to loft your authentication state out of the local component state of the `RequireAuth` HOC in order to use it outside a "Route" component, or refactor/rewrite it in such a way that doesn't couple it to your navigation. – Drew Reese Jun 10 '20 at 02:51
0

try to do it like this:

const RequireAuth = ({ component: Component }) => {}
Skerrepy
  • 354
  • 4
  • 6
  • Still getting the same error. It says that the error is on line ```return class Apps extends React.Component { ``` – xyz6675 Jun 08 '20 at 04:04
  • i didn't know how i missed the react import that was in curly braces but i guess @andus answer is correct – Skerrepy Jun 08 '20 at 14:22