React Link Router中的this.props.location.state未定义。

3

我在Stack Overflow上看到过多个这样的问题,但是没有一个修复方法管用。 this.props.location.state 始终返回未定义。这是我的 AppContainerExamplePageParentExamplePage

import {Router, Route, Switch} from "react-router-dom";

class AppContainer extends Component {
  render() {
    return (
      <Router>
        <Switch>   
          <Route exact path="/page" component={Page}
          <Route exact path="/examplePage" component={ExamplePage}/>
        </Switch>
      </Router>
    )
  }
}
//has mapStateToProps and mapDispatch to Props here

export default connect(mapStateToProps, mapDispatchToProps)(AppContainer);

--

class Page extends Component {

  render() {
   return(
     <AnotherPage key=this.props.id>
   );
  }
    }

// has mapStateToProps here (this.props.id comes from here)

export default connect(mapStateToProps, mapDispatchToProps)(Page);

--

class AnotherPage extends Component {

  render() {
   return(
     <ExamplePageParent key=this.props.id>
   );
  }
    }

// has mapStateToProps here (this.props.id comes from here)

export default connect(mapStateToProps, null)(AnotherPage);

--

class ExamplePageParent extends Component {

  //pathName and dataPassed content filled, not relevant to question

  render() {
   return(
     <Link
       class={'link-styling'}
       target="_blank"
       rel="noreferrer"
       to={{pathname: this.state.pathName, state: {dataPassed: true} }}
     >
       Click Me
     </Link>
   );
  }
    }

//has mapStateToProps here

export default connect(mapStateToProps, null)(ExamplePageParent);

--

import {withRouter} from "react-router";

class ExamplePage extends Component {

  constructor(props) {
    super(props);

    //this has content:
    console.log(this.props.location);

    //undefined:
    console.log(this.props.location.state);
  }

  render() {
   return(
     // do stuff
   );
  }
}
export default withRouter(ExamplePage);

props.location.state 究竟在哪里未定义? ExamplePage 组件被呈现在 component prop 上,因此路由 prop 被传递给它,并且它也被包装在 withRouter HOC 中,所以再次传递了路由 prop。这个传递路由状态的 ExamplePageParent 是在哪里被呈现的? - Drew Reese
好问题。ExamplePageParent 是路由 Page 的第三个子组件,我已经将其添加在上面了。 - penguin
意思是它将是 Page > AnotherPage1 > AnotherPage2 > ExamplePageParent。但只有 Page 有路由。 - penguin
你能更新一下问题,把所有相关的代码都包括进来吗?包括完整的 App 组件和从 PageExamplePageParent 的所有页面组件。你使用的是哪个路由器?this.state.pathName 是否是你期望的路径值? - Drew Reese
我已经在Page和ExamplePageParent之间添加了页面组件。Router来自于"react-router-dom",而withRouter来自于"react-router"。我已经为您添加了适当的导入以供查看。是的,this.state.pathName是正确的路径值。 - penguin
另外,我想说的是ExamplePageParent实际上是Page的第二个子组件。因此,Page > AnotherPage > ExamplePageParent - penguin
1个回答

1

问题

  • 您正在使用低级别的Router,需要一个已定义location对象的history对象才能正常工作。
  • 代码链接到新窗口,因此应用程序将重新加载/挂载并且传递的路由状态不会被传输。

为了解决未定义的location问题,您有几个选项:

  1. Import a custom history creator from the history package:

    import { createBrowserHistory } from 'history';
    
    const history = createBrowserHistory();
    
    ...
    
    <Router history={history}>
      ...
    </Router>
    
  2. Use one of the higer-level routers, i.e. BrowserRouter, HashRouter, MemoryRouter, etc...:

    import { BrowserRouter as Router } from 'react-router-dom';
    
    ...
    
    <Router>
      ...
    </Router>
    
为了处理在接收组件中访问“state”​​,您需要添加一些逻辑。当应用程序在新窗口/选项卡中启动时,状态不会转移,因此为了解决这个问题,您可以将路由状态序列化为查询字符串搜索参数发送。
<Link
  className={"link-styling"}
  target="_blank"
  rel="noreferrer"
  to={{
    pathname: this.state.pathName,
    search:
      "stuff=content&moreStuff=moreContent" + // existing search params
      "&dataPassed=This is the passed data.", // additional for state
    state: { dataPassed: "This is the passed data." }
  }}
>
  Click Me
</Link>

然后在ExamplePage中处理queryString,提取并删除添加的"dataPassed"查询参数,并使用先前存在的queryString重定向并填充路由状态。

class ExamplePage extends Component {
  componentDidMount() {
    const { history, location } = this.props;
    const { pathname, state, search } = location;

    console.log({ location });

    const searchParams = new URLSearchParams(search);
    let dataPassed;

    if (searchParams.has("dataPassed")) {
      dataPassed = searchParams.get("dataPassed");
      searchParams.delete("dataPassed");
    }
    history.replace({
      pathname,
      search: searchParams.toString(),
      state: { dataPassed }
    });
  }

  render() {
    return (
      ...
    );
  }
}

Edit this-props-location-state-is-undefined-in-react-link-router


@penguin 这个解决方案根本不会修改 this.state.pathName。完全合格的 URL 是 pathname + search + hash,没错,但这正是解决方案的第二部分通过处理接收路由组件上的 search 并重定向到只有实际路由状态的 pathname 来解决的。 - Drew Reese
我明白了。然而,this.state.pathName 在该状态中包含一些查询参数。基本上,this.state.pathName 看起来像这样:/path/?stuff=content&moreStuff=moreContent。当然,这不包括 dataPassed。我认为你所包含的 history.replace 行只会保留 /path/ 而不是 ?stuff=content&moreStuff=moreContent。如果我错了,请纠正我。 - penguin
@penguin 请查看更新的答案和链接的codesandbox。 - Drew Reese
1
嗨,Drew,非常感谢你花费时间和精力回答我的问题。多亏了你,我学到了很多关于路由器和UrlSearchParams的知识。谢谢你! :) - penguin
1
@企鹅 欢迎。很高兴能帮忙。祝你好运! - Drew Reese
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接