React/Router/MemoryRouter - 如何在子组件中传递历史属性并使用 push()? [英] React/Router/MemoryRouter - how to pass history property and use push() in child component?

查看:145
本文介绍了React/Router/MemoryRouter - 如何在子组件中传递历史属性并使用 push()?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一个 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()):

<代码>...从反应路由器"导入 {Route, MemoryRouter};...<MemoryRouter><路由精确路径="/" component={Home}/><Route path="/screening-tool" component={ScreeningTool}/></MemoryRouter>...

Home 和 ScreeningTool 都使用子组件 AppLink,它生成一个链接"以在 Home 和 ScreeningTool 之间导航,就像这样(注意我将历史"作为道具传递):

Home.js:...<应用链接网址="/"标签=筛选工具"历史={this.props.history}/>...AppLink.js:...<div className="伪链接"><span onClick={() =>this.props.history.push(this.props.url)}>{this.props.label}</span>

...

以上代码有效.但是 Home 中有子组件会创建自己的 AppLinks 和曾孙.我不想将 history 属性作为组件 prop 从 Parent 传递到 Child 到 GrandChild 组件,因为这似乎效率不高.我发现了以下 stackoverflow 问题,但这些选项都不适合我:

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

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

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

<代码>...从反应路由器"导入 { useHistory };...使成为() {让历史 = useHistory();返回 (<div className="伪链接"><span onClick={() =>history.push(this.props.url)}>{this.props.label}</span>

);}...

但我得到 错误:无效的钩子调用.钩子只能在函数组件的主体内部调用..

我尝试使用此处定义的 withRouter https://reacttraining.com/react-router/web/api/withRouter 但我得到 Error: Invariant failed: You should not use <withRouter(PseudoLink)/><路由器>之外.

最后,这个的公认答案.props.history.push 适用于某些组件,而不适用于其他组件 以代码块结束 export default withRouter(connect(mapStateToProps, matchDispatchToProps)(ChildView)); 但没有解释 mapStateToProps 的位置还是 matchDispatchToProps 来自?

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

有人可以帮我吗?

解决方案

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

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

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

导出默认 withRouter(yourComponentName);

更新

我已将 AppLink 组件更改为此,它工作正常

从react"导入React;导入./AppLink.css";从反应路由器"导入 { useHistory };const AppLink = 道具 =>{const 历史 = useHistory();返回 (

history.push(props.url)}><span>{props.label}</span>

);};导出默认的 AppLink;

I'm building a React app where I do NOT want the URL in the browser to be updated. I am NOT using 'react-router-dom' but only 'react-router' and MemoryRouter (https://reacttraining.com/react-router/web/api/MemoryRouter). The history.push() is available directly in the component statements but I wish to pass the history to children of children of these main components but the property is undefined.

Here is the Router section in main App.js (components Home and ScreeningTool can access this.props.history.push() as expected):

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

Both Home and ScreeningTool both use child component AppLink that generates a 'link' to navigate between Home and ScreeningTool like so (notice I'm passing 'history' as a prop):

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>
...

The above code works. But there are children components in Home that will create their own AppLinks and also greatgrandchildren. I do NOT want to pass the history property as a component prop from Parent to Child to GrandChild components because this does not seem efficient. I have found the following stackoverflow questions but none of these options are working for me:

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

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

I tried the newer 'userHistory' as described in the second URL above:

...
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>
    );
}
...

but I get Error: Invalid hook call. Hooks can only be called inside of the body of a function component..

I tried using withRouter as defined here https://reacttraining.com/react-router/web/api/withRouter but I get Error: Invariant failed: You should not use <withRouter(PseudoLink) /> outside a <Router>.

Finally, the accepted answer for this.props.history.push works in some components and not others ends with block of code export default withRouter(connect(mapStateToProps, matchDispatchToProps)(ChildView)); but does not explain where mapStateToProps or matchDispatchToProps comes from?

I'm thinking the issue is that I am using MemoryRouter and not normal/most common Router from 'reacto-router-dom'.

Can anyone help me out?

解决方案

useHistory is a Hook so it should be used in a functional component, not inside a class based component.

Finally, the accepted answer for this.props.history.push works in some components and not others ends with block of code export default withRouter(connect(mapStateToProps, matchDispatchToProps)(ChildView)); but does not explain where mapStateToProps or matchDispatchToProps comes from?

-If you're not using redux then you can just use

export default withRouter(yourComponentName);

update

I've changed the AppLink component to this and it is working fine

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;

这篇关于React/Router/MemoryRouter - 如何在子组件中传递历史属性并使用 push()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆