Reputation: 339
I am trying to do a token check when using Route. I liked one solution, but for some reason it does not want to work and gives an error:
Class constructor App cannot be invoked without 'new'
const RequireAuth = (Component) => {
return class App extends Component {
componentWillMount() {
const getToken = localStorage.getItem('token');
if(!getToken) {
this.props.history.replace({pathname: '/'});
}
}
render() {
return <Component {...this.props} />
}
}
}
export { RequireAuth };
Usage:
...
<PrivateRoute path="/profile" component={RequireAuth(Profile)} />
...
I have no idea why it is coming out and how to fix it. Have a clue?
Upvotes: 0
Views: 222
Reputation: 202801
You may be masking the react Component
type. Try changing the name of the parameter, or change to functional component if possible. Also, componentWillMount
is soon to be deprecated, you really should use componentDidMount
instead.
import React, { Component } from "react";
const requireAuth = (component) => { // lowercase to not conflict with React.Component!
return class App extends Component {
componentDidMount() {
const getToken = localStorage.getItem('token');
if(!getToken) {
this.props.history.replace({pathname: '/'});
}
}
render() {
const Component = component; // convert to PascalCase for react use
return <Component {...this.props} />
}
}
}
export { requireAuth };
or
import React, { useEffect } from "react";
const requireAuth = (Component) => {
return props => {
useEffect(() => {
const getToken = localStorage.getItem('token');
if(!getToken) {
props.history.replace({pathname: '/'});
}
}, []); // empty dependency array runs once on mount
return <Component {...this.props} />;
}
}
export { requireAuth };
I should note though that react's convention for Higher Order Components is to camelCase the name and not render them directly, and instead decorate an existing component.
const RequiresAuthMyComponent = requireAuth(MyComponent);
export default requireAuth(MyComponent);
Upvotes: 1
Reputation: 8774
You can simply transform it to a functional component, which can be called instead of a class. And instead of componentWillMount
use useEffect
with an empty dependency array.
const RequireAuth = Component => props => {
useEffect(() => {
const getToken = localStorage.getItem("token");
if (!getToken) {
props.history.replace({ pathname: "/" });
}
}, []);
return <Component {...props} />;
};
Upvotes: 1
Reputation: 339
I'm sure javascript class is not call such as you have mention (App Class).
So you can try something like below:
const RequireAuth = (Component) => {
class App extends Component {
componentWillMount() {
const getToken = localStorage.getItem('token');
if(!getToken) {
this.props.history.replace({pathname: '/'});
}
}
render() {
return <Component {...this.props} />
}
}
return new App();
}
export { RequireAuth };
Upvotes: 1