How To Handle Authentication With React-router?
Solution 1:
A simple solution would be to make a HOC
(High Order Component) that wraps all protected routes.
Depending upon how nested your app is, you may want to utilize local state or redux
state.
Working example: https://codesandbox.io/s/5m2690nn6n (this uses local state)
routes/index.js
importReactfrom"react";
import { BrowserRouter, Switch, Route } from"react-router-dom";
importHomefrom"../components/Home";
importPlayersfrom"../components/Players";
importSchedulefrom"../components/Schedule";
importRequireAuthfrom"../components/RequireAuth";
exportdefault () => (
<BrowserRouter><RequireAuth><Switch><Routeexactpath="/"component={Home} /><Routeexactpath="/players"component={Players} /><Routepath="/schedule"component={Schedule} /></Switch></RequireAuth></BrowserRouter>
);
components/RequireAuth.js
importReact, { Component, Fragment } from"react";
import { withRouter } from"react-router-dom";
importLoginfrom"./Login";
importHeaderfrom"./Header";
classRequireAuthextendsComponent {
state = { isAuthenticated: false };
componentDidMount = () => {
if (!this.state.isAuthenticated) {
this.props.history.push("/");
}
};
componentDidUpdate = (prevProps, prevState) => {
if (
this.props.location.pathname !== prevProps.location.pathname &&
!this.state.isAuthenticated
) {
this.props.history.push("/");
}
};
isAuthed = () =>this.setState({ isAuthenticated: true });
unAuth = () =>this.setState({ isAuthenticated: false });
render = () =>
!this.state.isAuthenticated ? (
<LoginisAuthed={this.isAuthed} />
) : (
<Fragment><HeaderunAuth={this.unAuth} />
{this.props.children}
</Fragment>
);
}
exportdefaultwithRouter(RequireAuth);
Or, instead of wrapping routes, you can create a protected component that houses protected routes.
Working example: https://codesandbox.io/s/yqo75n896x (uses redux
instead of local state).
routes/index.js
importReactfrom"react";
import { BrowserRouter, Route, Switch } from"react-router-dom";
import { createStore } from"redux";
import { Provider } from"react-redux";
importHomefrom"../components/Home";
importHeaderfrom"../containers/Header";
importInfofrom"../components/Info";
importSponsorsfrom"../components/Sponsors";
importSigninfrom"../containers/Signin";
importRequireAuthfrom"../containers/RequireAuth";
import rootReducer from"../reducers";
const store = createStore(rootReducer);
exportdefault () => (
<Providerstore={store}><BrowserRouter><div><Header /><Switch><Routeexactpath="/"component={Home} /><Routepath="/info"component={Info} /><Routepath="/sponsors"component={Sponsors} /><Routepath="/protected"component={RequireAuth} /><Routepath="/signin"component={Signin} /></Switch></div></BrowserRouter></Provider>
);
containers/RequireAuth.js
importReactfrom"react";
import { Route, Redirect } from"react-router-dom";
import { connect } from"react-redux";
importShowPlayerRosterfrom"../components/ShowPlayerRoster";
importShowPlayerStatsfrom"../components/ShowPlayerStats";
importSchedulefrom"../components/Schedule";
constRequireAuth = ({ match: { path }, isAuthenticated }) =>
!isAuthenticated ? (
<Redirectto="/signin" />
) : (
<div><Routeexactpath={`${path}/roster`} component={ShowPlayerRoster} /><Routepath={`${path}/roster/:id`} component={ShowPlayerStats} /><Routepath={`${path}/schedule`} component={Schedule} /></div>
);
exportdefaultconnect(state => ({
isAuthenticated: state.auth.isAuthenticated
}))(RequireAuth);
You can even get more modular by creating a wrapper function. You would be able to pick and choose any route by simply wrapping over the component. I don't have a codebox example, but it would be similar to this setup.
For example: <Route path="/blog" component={RequireAuth(Blog)} />
Solution 2:
You spelled Autheenticated
wrong.
Also, this is an assumption because you only provided the stack trace and not the above error
, which probably says AuthenticationService.IsAutheenticated
is not a function.
Post a Comment for "How To Handle Authentication With React-router?"