React / Router / MemoryRouter - как передать свойство истории и использовать pu sh () в дочернем компоненте? - PullRequest
1 голос
/ 04 апреля 2020

Я создаю приложение React, в котором я НЕ хочу, чтобы URL-адрес в браузере обновлялся. Я НЕ использую «response-router-dom», а только «response-router» и MemoryRouter (https://reacttraining.com/react-router/web/api/MemoryRouter). History.pu sh () доступна непосредственно в операторах компонентов, но я могу sh передать историю дочерним элементам дочерних элементов этих основных компонентов, но свойство не определено.

Вот Маршрутизатор раздел в главном приложении. js (компоненты Home и ScreeningTool могут обращаться к this.props.history.pu sh (), как и ожидалось):

...
import {Route, MemoryRouter} from "react-router";
...
<MemoryRouter>
    <Route exact path="/" component={Home} />
    <Route path="/screening-tool" component={ScreeningTool} />
</MemoryRouter>
... 

И Home, и ScreeningTool используют дочерний компонент AppLink, который генерирует «ссылку» для перехода между Home и ScreeningTool следующим образом (обратите внимание, я передаю «history» в качестве реквизита):

Home.js:
...
<AppLink
    url="/"
    label="Screening Tool"
    history={this.props.history}
/>
...

AppLink.js:
...
<div className="pseudo-link">
    <span onClick={() => this.props.history.push(this.props.url)}>
        {this.props.label}
    </span>
</div>
...

Приведенный выше код работает. Но в Home есть дочерние компоненты, которые будут создавать собственные AppLinks, а также отличные дети. Я НЕ хочу передавать свойство history в качестве компонента prop от Parent to Child компонентам GrandChild, потому что это не кажется эффективным. Я обнаружил следующие вопросы об стеке потока, но ни один из этих вариантов не работает для меня:

this.props.history.pu sh работает в некоторых компонентах, а не в других

реакции-маршрутизатор получает this.props.location в дочерних компонентах

Я попробовал более новую 'userHistory', как описано во втором URL-адресе выше:

...
import { useHistory } from 'react-router';
...
render() {
    let history = useHistory();
    return (
        <div className="pseudo-link">
            <span onClick={() => history.push(this.props.url)}>
                {this.props.label}
            </span>
        </div>
    );
}
...

но я получаю Error: Invalid hook call. Hooks can only be called inside of the body of a function component..

Я пытался использовать withRouter, как здесь определено https://reacttraining.com/react-router/web/api/withRouter, но я получаю Error: Invariant failed: You should not use <withRouter(PseudoLink) /> outside a <Router>.

Наконец, принятый ответ для this.props.history.pu sh работает в некоторых компонентах, а не в других заканчивается блоком кода export default withRouter(connect(mapStateToProps, matchDispatchToProps)(ChildView));, но не объясняет, откуда берется mapStateToProps или matchDispatchToProps?

I ' Я думаю, проблема в том, что я использую MemoryRouter, а не обычный / самый обычный Маршрутизатор из'acto-router-dom '.

Кто-нибудь может мне помочь?

1 Ответ

1 голос
/ 04 апреля 2020

useHistory - это хук, поэтому его следует использовать в функциональном компоненте, а не внутри компонента на основе классов.

Наконец, принятый ответ для this.props.history.pu sh работает в некоторых компонентах, а другие не заканчиваются блоком экспорта кода по умолчанию withRouter (connect (mapStateToProps, matchDispatchToProps) (ChildView)); но не объясняет, откуда берется mapStateToProps или matchDispatchToProps?

-Если вы не используете redux, тогда вы можете просто использовать

export default withRouter(yourComponentName);

update

Я изменил компонент AppLink на этот, и он работает нормально

import React from "react";
import "./AppLink.css";
import { useHistory } from 'react-router';

const AppLink = props => {
  const history = useHistory();
  return (
    <div
      className="app-link-button"
      onClick={() => history.push(props.url)}
    >
      <span>{props.label}</span>
    </div>
  );
};

export default AppLink;
...