react-router obteniendo this.props.location en componentes secundarios


85

Según tengo entendido, <Route path="/" component={App} />will da Appaccesorios relacionados con el enrutamiento como locationy params. Si mi Appcomponente tiene muchos componentes secundarios anidados, ¿cómo consigo que el componente secundario tenga acceso a estos accesorios sin:

  • pasando accesorios de la aplicación
  • usando el objeto de la ventana
  • crear rutas para componentes secundarios anidados

Pensé this.context.routerque tendría alguna información relacionada con las rutas, pero this.context.routerparece que solo tiene algunas funciones para manipular las rutas.


En App Component, el componente secundario anidado directo se puede encontrar en this.props.children
gu mingfeng

Respuestas:


143

(Actualización) V5.1 y Hooks (Requiere React> = 16.8)

Puede usar useHistory, useLocationy useRouteMatchen su componente para obtener match, historyy location.

const Child = () => {
  const location = useLocation();
  const history = useHistory();
  const match = useRouteMatch("write-the-url-you-want-to-match-here");

  return (
    <div>{location.pathname}</div>
  )
}

export default Child

(Actualización) V4 y V5

Puede utilizar withRouterhoc a fin de inyectar match, historyy locationen sus apoyos componentes.

class Child extends React.Component {
  static propTypes = {
    match: PropTypes.object.isRequired,
    location: PropTypes.object.isRequired,
    history: PropTypes.object.isRequired
  }

  render() {
    const { match, location, history } = this.props

    return (
      <div>{location.pathname}</div>
    )
  }
}

export default withRouter(Child)

(Actualización) V3

Puede utilizar withRouterhoc a fin de inyectar router, params, location, routesen sus apoyos componentes.

class Child extends React.Component {

  render() {
    const { router, params, location, routes } = this.props

    return (
      <div>{location.pathname}</div>
    )
  }
}

export default withRouter(Child)

Respuesta original

Si no desea usar los accesorios, puede usar el contexto como se describe en la documentación de React Router

Primero, tienes que configurar tu childContextTypesygetChildContext

class App extends React.Component{

  getChildContext() {
    return {
      location: this.props.location
    }
  }

  render() {
    return <Child/>;
  }
}

App.childContextTypes = {
    location: React.PropTypes.object
}

Luego, podrá acceder al objeto de ubicación en sus componentes secundarios usando el contexto como este

class Child extends React.Component{

   render() {
     return (
       <div>{this.context.location.pathname}</div>
     )
   }

}

Child.contextTypes = {
    location: React.PropTypes.object
 }

gracias por la anotación. No leí esa parte de la documentación. Pensé que solo habíacontext.router
xiaofan2406


3
Soy nuevo en React. Por lo tanto, perdóname si me equivoco, pero ¿qué tiene de malo usar window.location.pathname?
Artur Barseghyan

1
window.location es mutable, por lo que se considera una mejor práctica no acceder a él, prefiriendo usar una versión inmutable. Además, creo que es posible usar ubicaciones lógicas que difieren de window.location (al menos esto es cierto en nextjs), por lo que es posible obtener una ubicación diferente de su enrutador que el historial de ventana directo
Chanoch

@ArturBarseghyan El windowobjeto no existe si el código React se ejecuta en el servidor, por ejemplo, para implementar el enrutamiento del lado del servidor.
ChrisW

5

Si la solución anterior no le funcionó, puede usar import { withRouter } from 'react-router-dom';


Con esto, puede exportar su clase secundaria como:

class MyApp extends Component{
    // your code
}

export default withRouter(MyApp);

Y tu clase con Router -

// your code
<Router>
      ...
      <Route path="/myapp" component={MyApp} />
      // or if you are sending additional fields
      <Route path="/myapp" component={() =><MyApp process={...} />} />
<Router>
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.