Para dar acceso solo a usuarios autenticados, creé un componente PrivateRoute como se describe aquí . Todo funciona bien, pero me da una advertencia de que la 'ubicación' no está definida.
import React from 'react'; import PropTypes from 'prop-types'; import { Redirect, Route } from 'react-router-dom'; import auth from '../../hooks/login/auth'; const PrivateRoute = ({ component: Component, ...rest }) => ( <Route {...rest} render={(props) => ( auth.getToken() !== null ? ( <Component {...props} /> ) : ( <Redirect to={{ pathname: '/log_in', state: { from: props.location }, }} /> ) )} /> ); PrivateRoute.propTypes = { component: PropTypes.any.isRequired, // eslint-disable-line location: PropTypes.shape({ pathname: PropTypes.string.isRequired, }).isRequired, }; export default PrivateRoute; <Switch> <Route exact path="/" component={LogIn} /> <Route exact path="/log_in" component={LogIn} /> <PrivateRoute exact path="/dashboard" component={Dashboard} /> </Switch>Si hago un inicio de sesión en la consola en el método de representación, la ubicación siempre está definida. Entonces, ¿qué?
<Route {...rest} render={(props) => { console.log('LOCATION', props.location); return auth.getToken() !== null ? ( <Component {...props} /> ) : ( <Redirect to={{ pathname: '/log_in', state: { from: props.location }, }} /> ); }} />Intenté darle a la ubicación un valor predeterminado, pero luego toda la página estaba en blanco.
PrivateRoute.propTypes = { component: PropTypes.any.isRequired, // eslint-disable-line location: PropTypes.shape({ pathname: PropTypes.string.isRequired, }), }; PrivateRoute.defaultProps = { location: { pathname: '', }, };¿Cuál es el problema aquí? ¿Y cómo es posible que la ubicación no esté definida cuando cualquier salida de registro de la consola muestra un objeto de ubicación definido?
Está declarando un PropType de location para el componente PrivateRoute , que obviamente no estará definido, ya que no está pasando un accesorio de location a su componente PrivateRoute al renderizar, y está registrando los accesorios de Route que está renderizando PrivateRoute .
const PrivateRoute = ({ component: Component, // <-- not logging any of these props ...rest }) => ( <Route {...rest} render={(props) => ( // <-- logging these route props auth.getToken() !== null ? ( <Component {...props} /> ) : ( <Redirect to={{ pathname: '/log_in', state: { from: props.location }, }} /> ) )} /> ); La location ni siquiera es una propiedad del componente Route , es solo una de las propiedades que se pasan a los tres métodos de renderizado ( component , render y función children ).
Si desea/necesita especificar que la propiedad location.pathname está disponible, entonces esto debe hacerse en el componente que está representando su componente PrivateRoute personalizado, ya que aquí es donde se pasa una propiedad de location . En este caso, es el componente Dashboard el que debe tener definido location.pathname como accesorio necesario.
Si ayuda, hay un paquete react-router-prop-types que puede instalar y usar. Exporta una declaración PropType de location con la propiedad de nombre de pathname ya requerida.
export const location = PropTypes.shape({ hash: PropTypes.string.isRequired, key: PropTypes.string, // only in createBrowserHistory and createMemoryHistory pathname: PropTypes.string.isRequired, search: PropTypes.string.isRequired, state: PropTypes.oneOfType([ PropTypes.array, PropTypes.bool, PropTypes.number, PropTypes.object, PropTypes.string, ]), // only in createBrowserHistory and createMemoryHistory });
En Dashboard :
import { location } from 'react-router-prop-types'; Dashboard.propTypes = { // ... the other prop types location: location.isRequired, };