React-router
не дает вам параметры совпадения ни одного из сопоставленных дочерних маршрутов, скорее, оно дает вам параметры, основанные на текущем совпадении.Поэтому, если у вас есть настройки маршрутов, например
<Route path='/topic' component={Topics} />
, а в компоненте Topics
у вас есть маршрут, например
<Route path=`${match.url}/:topicId` component={Topic} />
Теперь, если ваш URL-адрес /topic/topic1
соответствует внутреннему маршрутуно для компонента Темы соответствующий Маршрут по-прежнему /topic
и, следовательно, не содержит никаких параметров, что имеет смысл.
Если вы хотите получить параметры дочернего Маршрута, соответствующего в компоненте тем, выпотребуется использовать утилиту matchPath
, предоставляемую React-router, и протестировать дочерний маршрут, параметры которого вы хотите получить
import { matchPath } from 'react-router'
render(){
const {users, flags, location } = this.props;
const match = matchPath(location.pathname, {
path: '/topic/:topicId',
exact: true,
strict: false
})
if(match) {
console.log(match.params.topicId);
}
return (
<div>
<Route exact path="/topic/:topicId" component={Topic} />
</div>
)
}
EDIT:
Один метод для получения всехПараметр params на любом уровне - это использование контекста и обновление параметров в соответствии с тем, когда они совпадают в провайдере контекста.
Вам потребуется создать обертку вокруг Route, чтобы он работал правильно. Типичный пример будет выглядетькак
RouteWrapper.jsx
import React from "react";
import _ from "lodash";
import { matchPath } from "react-router-dom";
import { ParamContext } from "./ParamsContext";
import { withRouter, Route } from "react-router-dom";
class CustomRoute extends React.Component {
getMatchParams = props => {
const { location, path, exact, strict } = props || this.props;
const match = matchPath(location.pathname, {
path,
exact,
strict
});
if (match) {
console.log(match.params);
return match.params;
}
return {};
};
componentDidMount() {
const { updateParams } = this.props;
updateParams(this.getMatchParams());
}
componentDidUpdate(prevProps) {
const { updateParams, match } = this.props;
const currentParams = this.getMatchParams();
const prevParams = this.getMatchParams(prevProps);
if (!_.isEqual(currentParams, prevParams)) {
updateParams(match.params);
}
}
componentWillUnmount() {
const { updateParams } = this.props;
const matchParams = this.getMatchParams();
Object.keys(matchParams).forEach(k => (matchParams[k] = undefined));
updateParams(matchParams);
}
render() {
return <Route {...this.props} />;
}
}
const RouteWithRouter = withRouter(CustomRoute);
export default props => (
<ParamContext.Consumer>
{({ updateParams }) => {
return <RouteWithRouter updateParams={updateParams} {...props} />;
}}
</ParamContext.Consumer>
);
ParamsProvider.jsx
import React from "react";
import { ParamContext } from "./ParamsContext";
export default class ParamsProvider extends React.Component {
state = {
allParams: {}
};
updateParams = params => {
console.log({ params: JSON.stringify(params) });
this.setState(prevProps => ({
allParams: {
...prevProps.allParams,
...params
}
}));
};
render() {
return (
<ParamContext.Provider
value={{
allParams: this.state.allParams,
updateParams: this.updateParams
}}
>
{this.props.children}
</ParamContext.Provider>
);
}
}
Index.js
ReactDOM.render(
<BrowserRouter>
<ParamsProvider>
<App />
</ParamsProvider>
</BrowserRouter>,
document.getElementById("root")
);
РабочийDEMO