router-реакція отримує this.props.location у дочірніх компонентах


85

Як я розумію, <Route path="/" component={App} />воля дає Appреквізити, пов'язані з маршрутизацією, як locationі params. Якщо мій Appкомпонент має багато вкладених дочірніх компонентів, як я можу отримати дочірній компонент доступ до цих реквізитів без:

  • передача реквізиту з програми
  • за допомогою віконного об'єкта
  • створення маршрутів для вкладених дочірніх компонентів

Я думав, this.context.routerщо матиму певну інформацію, пов’язану з маршрутами, але, this.context.routerсхоже, маю лише деякі функції для керування маршрутами.


В App Component прямий вкладений дочірній компонент можна знайти за адресою this.props.children
gu mingfeng

Відповіді:


143

(Оновлення) V5.1 і хуки (Потрібна реакція> = 16,8)

Ви можете використовувати useHistory, useLocationа useRouteMatchу вашому компоненті отримати match, historyі 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

(Оновлення) V4 і V5

Ви можете використовувати withRouterHOC для того , щоб ввести match, historyі locationв ваших компонентів реквізиту.

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)

(Оновлення) V3

Ви можете використовувати withRouterHOC для того , щоб ввести router, params, location, routesв ваших компонентів реквізиту.

class Child extends React.Component {

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

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

export default withRouter(Child)

Оригінальна відповідь

Якщо ви не хочете використовувати реквізит, ви можете використовувати контекст, як описано в документації React Router

По-перше, ви повинні налаштувати свій childContextTypesіgetChildContext

class App extends React.Component{

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

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

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

Тоді ви зможете отримати доступ до об'єкта розташування у ваших дочірніх компонентах, використовуючи такий контекст

class Child extends React.Component{

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

}

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

дякую за вказівник. Я не читав цю частину документації. Я думав, що є лишеcontext.router
xiaofan2406


3
Я новачок у React. Таким чином, вибачте мене, якщо я помиляюся, але що поганого у використанні window.location.pathname?
Артур Барсегян

1
window.location змінюється, тому вважається найкращою практикою не отримувати до нього доступ, воліючи використовувати незмінну версію. Крім того, я думаю, що можна використовувати логічні розташування, які відрізняються від розміщення window.location (принаймні, це вірно в nextjs), тому можна отримати інше розташування від вашого маршрутизатора, ніж пряма історія вікон
Chanoch

@ArturBarseghyan windowОб'єкт не існує, якщо код React запущений на сервері, наприклад, для реалізації маршрутизації на стороні сервера.
ChrisW

5

Якщо вищевказане рішення не допомогло вам, ви можете скористатися ним import { withRouter } from 'react-router-dom';


Використовуючи це, ви можете експортувати свій дочірній клас як -

class MyApp extends Component{
    // your code
}

export default withRouter(MyApp);

А ваш клас із маршрутизатором -

// your code
<Router>
      ...
      <Route path="/myapp" component={MyApp} />
      // or if you are sending additional fields
      <Route path="/myapp" component={() =><MyApp process={...} />} />
<Router>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.