测试用例
https://codesandbox.io/s/rr00y9w2wm
重现步骤
或者
预期行为
match.params.topicId
应该与父相同。在主题组件match.params.topicId
相同。实际行为
在中访问时的
match.params.topicId
主题match.params.topicId
主题我从this closed issue了解这不一定是错误。
在需要在工厂Web应用程序中创建运行的用户中,这种要求是非常普遍的,其中 parent 级别的组件
Topics
需要访问 match.params.paramId ,其中paramId
是与嵌套(子级)匹配的URL参数组件Topic
:const Topic = ({ match }) => (
<div>
<h2>Topic ID param from Topic Components</h2>
<h3>{match.params.topicId}</h3>
</div>
);
const Topics = ({ match }) => (
<div>
<h2>Topics</h2>
<h3>{match.params.topicId || "undefined"}</h3>
<Route path={`${match.url}/:topicId`} component={Topic} />
...
</div>
);
从一般意义上讲,
Topics
可以是“抽屉”或“导航菜单”组件,而Topic
可以是任何子组件,就像我正在开发的应用程序中一样。子组件具有自己的:topicId
参数,也具有自己的<Route path="sections/:sectionId" component={Section} />
路由/组件。更痛苦的是,导航菜单不必与组件树具有一对一的关系。有时,菜单根级的项目(例如
Topics
,Sections
等)可能与嵌套的结构相对应(Sections
仅在Topic,/topics/:topicId/sections/:sectionId
下呈现,尽管它具有自己的规范化列表,用户可以在下面使用标题(导航栏中的部分)。因此,当单击 Sections 时,应突出显示它,而不是 Sections 和主题。
由于导航栏组件的
sectionId
或sections
路径在应用程序的根目录下不可用,因此有必要为这种常见用例编写hacks like this。我根本不是React Router的专家,因此,如果任何人都可以对此用例寻求合适的优雅解决方案,我都会认为这是富有成果的努力。优雅,我的意思是
match
而不使用history.location.pathname
window.location.xxx
this.props.location.pathname
path-to-regexp
其他技巧/部分解决方案/相关问题:
TIA!
最佳答案
尝试利用查询参数?
来允许父级和子级访问当前选定的topic
。不幸的是,您将需要使用qs模块,因为react-router-dom
不会自动解析查询(react-router v3会自动解析)。
工作示例:https://codesandbox.io/s/my1ljx40r9
URL的结构类似于连接字符串:topic?topic=props-v-state
然后,您将使用&
添加到查询中:/topics/topic?topic=optimization&category=pure-components&subcategory=shouldComponentUpdate
✔使用匹配进行路由URL处理
✔不使用this.props.location.pathname
(使用this.props.location.search
)
✔使用qs
解析location.search
✔不涉及骇客方法
Topics.js
import React from "react";
import { Link, Route } from "react-router-dom";
import qs from "qs";
import Topic from "./Topic";
export default ({ match, location }) => {
const { topic } = qs.parse(location.search, {
ignoreQueryPrefix: true
});
return (
<div>
<h2>Topics</h2>
<ul>
<li>
<Link to={`${match.url}/topic?topic=rendering`}>
Rendering with React
</Link>
</li>
<li>
<Link to={`${match.url}/topic?topic=components`}>Components</Link>
</li>
<li>
<Link to={`${match.url}/topic?topic=props-v-state`}>
Props v. State
</Link>
</li>
</ul>
<h2>
Topic ID param from Topic<strong>s</strong> Components
</h2>
<h3>{topic && topic}</h3>
<Route
path={`${match.url}/:topicId`}
render={props => <Topic {...props} topic={topic} />}
/>
<Route
exact
path={match.url}
render={() => <h3>Please select a topic.</h3>}
/>
</div>
);
};
另一种方法是创建一个将参数存储到
HOC
的state
,并且当其参数更改时,子代会更新父级的state
。URL的结构类似于文件夹树:
/topics/rendering/optimization/pure-components/shouldComponentUpdate
工作示例:https://codesandbox.io/s/9joknpm9jy
✔使用匹配进行路由URL处理
✔不使用
this.props.location.pathname
✔使用lodash进行对象间比较
✔不涉及骇客方法
Topics.js
import map from "lodash/map";
import React, { Fragment, Component } from "react";
import NestedRoutes from "./NestedRoutes";
import Links from "./Links";
import createPath from "./createPath";
export default class Topics extends Component {
state = {
params: "",
paths: []
};
componentDidMount = () => {
const urlPaths = [
this.props.match.url,
":topicId",
":subcategory",
":item",
":lifecycles"
];
this.setState({ paths: createPath(urlPaths) });
};
handleUrlChange = params => this.setState({ params });
showParams = params =>
!params
? null
: map(params, name => <Fragment key={name}>{name} </Fragment>);
render = () => (
<div>
<h2>Topics</h2>
<Links match={this.props.match} />
<h2>
Topic ID param from Topic<strong>s</strong> Components
</h2>
<h3>{this.state.params && this.showParams(this.state.params)}</h3>
<NestedRoutes
handleUrlChange={this.handleUrlChange}
match={this.props.match}
paths={this.state.paths}
showParams={this.showParams}
/>
</div>
);
}
NestedRoutes.js
import map from "lodash/map";
import React, { Fragment } from "react";
import { Route } from "react-router-dom";
import Topic from "./Topic";
export default ({ handleUrlChange, match, paths, showParams }) => (
<Fragment>
{map(paths, path => (
<Route
exact
key={path}
path={path}
render={props => (
<Topic
{...props}
handleUrlChange={handleUrlChange}
showParams={showParams}
/>
)}
/>
))}
<Route
exact
path={match.url}
render={() => <h3>Please select a topic.</h3>}
/>
</Fragment>
);
关于javascript - 在根级别无法访问React Router v4嵌套匹配参数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52684017/