this.props.location.state 在 React Link 路由器中未定义
this.props.location.state is undefined in React Link Router
我在 Stack Overflow 上看到了其中的几个问题,但 none 的修复似乎有效。 this.props.location.state
总是 returns 未定义。这是我的 AppContainer
、ExamplePageParent
和 ExamplePage
。
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);
问题
- 您正在使用 low-level
Router
,它需要一个 history
对象来定义一个 location
对象。
- 代码正在链接到一个新的 window,因此该应用程序是 loaded/mounted 从头开始的,并且传递的路由状态不会被转移。
要解决未定义的问题 location
,您有两种选择:
从 history
包中导入自定义历史创建器:
import { createBrowserHistory } from 'history';
const history = createBrowserHistory();
...
<Router history={history}>
...
</Router>
使用 higer-level 路由器之一,即 BrowserRouter
、HashRouter
、MemoryRouter
等...:
import { BrowserRouter as Router } from 'react-router-dom';
...
<Router>
...
</Router>
要解决在接收组件中访问“状态”的问题,您需要添加一些逻辑。当应用程序在新 window/tab 中启动时,状态不会传输,因此为了解决这个问题,您可以发送序列化为 queryString 搜索参数的路由状态。
<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
中处理查询字符串以提取和删除添加的 "dataPassed"
查询参数,并使用填充的路由状态重定向先前存在的查询字符串。
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 (
...
);
}
}
我在 Stack Overflow 上看到了其中的几个问题,但 none 的修复似乎有效。 this.props.location.state
总是 returns 未定义。这是我的 AppContainer
、ExamplePageParent
和 ExamplePage
。
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);
问题
- 您正在使用 low-level
Router
,它需要一个history
对象来定义一个location
对象。 - 代码正在链接到一个新的 window,因此该应用程序是 loaded/mounted 从头开始的,并且传递的路由状态不会被转移。
要解决未定义的问题 location
,您有两种选择:
从
history
包中导入自定义历史创建器:import { createBrowserHistory } from 'history'; const history = createBrowserHistory(); ... <Router history={history}> ... </Router>
使用 higer-level 路由器之一,即
BrowserRouter
、HashRouter
、MemoryRouter
等...:import { BrowserRouter as Router } from 'react-router-dom'; ... <Router> ... </Router>
要解决在接收组件中访问“状态”的问题,您需要添加一些逻辑。当应用程序在新 window/tab 中启动时,状态不会传输,因此为了解决这个问题,您可以发送序列化为 queryString 搜索参数的路由状态。
<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
中处理查询字符串以提取和删除添加的 "dataPassed"
查询参数,并使用填充的路由状态重定向先前存在的查询字符串。
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 (
...
);
}
}