Actualización (16 de agosto de 2019)
En react-router v4 y usando React Hooks, esto se ve un poco diferente. Empecemos con tu App.js.
export default function App() {
const [isAuthenticated, userHasAuthenticated] = useState(false);
useEffect(() => {
onLoad();
}, []);
async function onLoad() {
try {
await Auth.currentSession();
userHasAuthenticated(true);
} catch (e) {
alert(e);
}
}
return (
<div className="App container">
<h1>Welcome to my app</h1>
<Switch>
<UnauthenticatedRoute
path="/login"
component={Login}
appProps={{ isAuthenticated }}
/>
<AuthenticatedRoute
path="/todos"
component={Todos}
appProps={{ isAuthenticated }}
/>
<Route component={NotFound} />
</Switch>
</div>
);
}
Estamos usando una Authbiblioteca para verificar si el usuario está autenticado actualmente. Reemplace esto con su función de verificación de autenticación. Si es así, establecemos la isAuthenticatedbandera en true. Hacemos esto cuando nuestra aplicación se carga por primera vez. También vale la pena mencionar que es posible que desee agregar un signo de carga en su aplicación mientras se ejecuta la verificación de autenticación, para que no muestre la página de inicio de sesión cada vez que actualice la página.
Luego pasamos la bandera a nuestras rutas. Creamos dos tipos de rutas AuthenticatedRoutey UnauthenticatedRoute.
Se AuthenticatedRoute.jsve así.
export default function AuthenticatedRoute({ component: C, appProps, ...rest }) {
return (
<Route
{...rest}
render={props =>
appProps.isAuthenticated
? <C {...props} {...appProps} />
: <Redirect
to={`/login?redirect=${props.location.pathname}${props.location.search}`}
/>}
/>
);
}
Comprueba si isAuthenticatedestá configurado en true. Si es así, renderizará el componente deseado. De lo contrario, redirigirá a la página de inicio de sesión.
El UnauthenticatedRoute.jspor otro lado se ve así.
export default ({ component: C, appProps, ...rest }) =>
<Route
{...rest}
render={props =>
!appProps.isAuthenticated
? <C {...props} {...appProps} />
: <Redirect to="/" />}
/>;
En este caso, si isAuthenticatedestá configurado en false, renderizará el componente deseado. Y si está configurado como verdadero, lo enviará a la página de inicio.
Puede encontrar versiones detalladas de esto en nuestra guía: https://serverless-stack.com/chapters/create-a-route-that-redirects.html .
Versión antigua
La respuesta aceptada es correcta, pero el equipo de React considera que los Mixins son dañinos ( https://facebook.github.io/react/blog/2016/07/13/mixins-considered-harmful.html ).
Si alguien se encuentra con esta pregunta y está buscando la forma recomendada de hacerlo, le sugiero que use Componentes de orden superior en lugar de Mixins.
Aquí hay un ejemplo de un HOC que verificará si el usuario inició sesión antes de continuar. Y si el usuario no ha iniciado sesión, lo redireccionará a la página de inicio de sesión. Este componente toma un accesorio llamado isLoggedIn, que es básicamente una bandera que su aplicación puede almacenar para indicar si el usuario está conectado.
import React from 'react';
import { withRouter } from 'react-router';
export default function requireAuth(Component) {
class AuthenticatedComponent extends React.Component {
componentWillMount() {
this.checkAuth();
}
checkAuth() {
if ( ! this.props.isLoggedIn) {
const location = this.props.location;
const redirect = location.pathname + location.search;
this.props.router.push(`/login?redirect=${redirect}`);
}
}
render() {
return this.props.isLoggedIn
? <Component { ...this.props } />
: null;
}
}
return withRouter(AuthenticatedComponent);
}
Y para usar este HOC, simplemente envuélvalo en sus rutas. En el caso de su ejemplo, sería:
<Route handler={requireAuth(Todos)} name="todos"/>
Cubro este y algunos otros temas en un tutorial detallado paso a paso aquí: https://serverless-stack.com/chapters/create-a-hoc-that-checks-auth.html