React/Router/MemoryRouter - 如何在子组件中传递历史属性并使用 push()?

IT技术 javascript html reactjs react-native react-router
2021-05-16 01:35:22

我正在构建一个 React 应用程序,我不希望浏览器中的 URL 被更新。我没有使用“react-router-dom”,而只使用“react-router”和 MemoryRouter(https://reacttraining.com/react-router/web/api/MemoryRouter)。history.push() 可直接在组件语句中使用,但我希望将历史记录传递给这些主要组件的子组件的子组件,但该属性未定义。

这是主 App.js 中的 Router 部分(组件 Home 和 ScreeningTool 可以按预期访问 this.props.history.push()):

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

Home 和 ScreeningTool 都使用子组件 AppLink 生成“链接”以在 Home 和 ScreeningTool 之间导航,如下所示(注意我将“历史”作为props传递):

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 和曾孙。我不想将历史属性作为组件props从 Parent 传递到 Child 到 GrandChild 组件,因为这似乎效率不高。我发现了以下 stackoverflow 问题,但这些选项都不适合我:

this.props.history.push 适用于某些组件而不适用于其他组件

react-router 在子组件中获取 this.props.location

我尝试了上面第二个 URL 中描述的较新的“userHistory”:

...
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.push的公认答案适用于某些组件,而不是其他组件,以代码块结尾,export default withRouter(connect(mapStateToProps, matchDispatchToProps)(ChildView));但没有解释 mapStateToProps 或 matchDispatchToProps 来自哪里?

我在想问题是我使用的是 MemoryRouter 而不是来自“reacto-router-dom”的普通/最常见的路由器。

谁能帮我吗?

1个回答

useHistory 是一个 Hook,所以它应该用在功能组件中,而不是在基于类的组件中。

最后,this.props.history.push 的公认答案适用于某些组件,而不适用于其他组件,以代码块导出 default withRouter(connect(mapStateToProps, matchDispatchToProps)(ChildView)); 结束。但没有解释 mapStateToProps 或 matchDispatchToProps 来自哪里?

- 如果你不使用 redux 那么你可以使用

export default withRouter(yourComponentName);

更新

我已将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;