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

Posted

技术标签:

【中文标题】React/Router/MemoryRouter - 如何传递历史属性并在子组件中使用 push()?【英文标题】:React/Router/MemoryRouter - how to pass history property and use push() in child component? 【发布时间】:2020-07-16 18:23:13 【问题描述】:

我正在构建一个不希望更新浏览器中的 URL 的 React 应用程序。我没有使用“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 之间导航(注意我将“历史”作为道具传递):

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 属性作为组件属性从 Parent 传递给 Child 到 GrandChild 组件,因为这看起来效率不高。我发现了以下 *** 问题,但这些选项都不适合我:

this.props.history.push works in some components and not others

react-router getting this.props.location in child components

我尝试了上面第二个 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 &lt;withRouter(PseudoLink) /&gt; outside a &lt;Router&gt;

最后,this.props.history.push works in some components and not others 接受的答案以代码块 export default withRouter(connect(mapStateToProps, matchDispatchToProps)(ChildView)); 结尾,但没有解释 mapStateToProps 或 matchDispatchToProps 来自哪里?

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

谁能帮帮我?

【问题讨论】:

【参考方案1】:

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

最后,this.props.history.push 的公认答案在某些组件中有效,而在其他组件中则以代码块 export 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;

【讨论】:

我已将类组件更改为可以使用,但在 useHistory() 'TypeError: Cannot read property 'history' of undefined' 时仍然出现错误 至于 withRouter() 我在上面解释说我已经使用了它并且包含了错误。 @PippyLongstocking 确保所有使用withRouter 的元素都用BrowserRouter docs 包裹起来 Ramesh,从 'react' 导入 React;从“反应路由器”导入 useHistory ;导入'./AppLink.scss'; const AppLink = (props) => let history = useHistory(); console.log('HISTORY:::', 历史);返回( history.push(props.url)> props.label ); 导出默认 AppLink;另外,我没有使用 BrowserRouter 似乎来自的 react-router-dom 。我只使用'react-router' 拉梅什,我不明白你的意思。这是一个子组件,用于显示在父组件之间导航的标签,并且当我在上面提出代码时,这些父组件由路由器包装......你能提供示例吗?

以上是关于React/Router/MemoryRouter - 如何传递历史属性并在子组件中使用 push()?的主要内容,如果未能解决你的问题,请参考以下文章