React Router - 如何动态替换字符串中的参数

问题描述 投票:0回答:5

我在 URL 中有一组动态参数,例如用户区域设置,如下所示:

/en/homepage

在我的路由器配置 JSON 文件中,我有类似的内容:

/:locale/homepage

在 React Router 中直接替换这些参数的最佳方法是什么?

我提出了这个解决方案,在我看来,它与标准或便携式解决方案相去甚远:

const urlTemplate = '/:language/homepage';
const mappedUrl = pathToRegexp.compile(urlTemplate);
const url = mappedUrl({
  'language': this.props.match.params.language
})
this.props.history.push(url);

如果组件由 withRouter (来自 React router 的 HOC )包装,我可以检索匹配参数并将其替换为 pathToRegexp (🐾pillarjs/path-to-regexp ),但是如果我需要在 a 中使用

<Link to={}>
无状态组件非常烦人。

有标准解决方案可以做到这一点吗?

提前谢谢您:)

javascript reactjs react-router react-router-v4
5个回答
56
投票

当用户更改 Leaflet 地图视图时,我使用 React Router 的

generatePath
来更新路径
/map/:zoom/:lon/:lat/
。请注意,在我的例子中,我替换了路径而不是推送它。

import { generatePath } from 'react-router';

function updatePath(lat, lon, zoom) {
  const path = generatePath(this.props.match.path, { lat, lon, zoom });
  this.props.history.replace(path);
}

2
投票

我使用一个函数,该函数使用正则表达式将路由路径的参数替换为函数的参数。

如果路线是:

'/:language/homepage'

该函数将用传递给函数的参数替换

:language

功能

这是替换路径中的值的函数:

function getRoute(path) {
    let args = Array.prototype.slice.call(arguments, 1);
    let count = -1;
    return path.replace(/:[a-zA-Z?]+/g, function (match) {
        count += 1;
        return args[count] !== undefined ? args[count] : match;
    });
};

这里的关键是正则表达式

/:[a-zA-Z?]+/g
,它只匹配以
:
开头并包含
a-z
A-Z
之间的任何字符的字符串,这意味着当找到下一个
/
时,它将完成匹配,所以它将替换所有像这样定义的参数。

这适用于我对简单参数的特定用法,但如果您需要向匹配的正则表达式添加更多字符,您可以这样做(例如数字、下划线等)。

用法

它的用法是这样的:

let newPath = getRoute('/:language/homepage', 'en');

结果将是:

'/en/homepage'

链接示例

它可以用于

Links
,如下所示:

<Link to={ getRoute('/:language/homepage', 'en') }>

rout中的多个参数e

它也接受多个参数:

getRoute('/:id/:language/homepage/:value', 123, 'en', 'myVal')

这将返回:

'/123/en/homepage/myVal'

1
投票

React Router Dom参数替换功能。好处:

  • 无限数量的参数
  • 通过可选的
    prefix
    参数灵活用于其他库
  • 处理相对 URL 和绝对 URL

const repalacePathParams = (path, params, prefix = ':') => {
  let newPath = path

  Object.entries(params).forEach(([key, value]) => {
    newPath = newPath.replace(prefix + key, value)
  })
  return newPath
}

console.log(repalacePathParams('/profile/:id/:name', { id: '111', name: 'tim' })) 
//return '/profile/111/tim'


0
投票

好吧,不确定您是否仍然对答案感兴趣,也不确定我的答案是否会对您有所帮助,但是...

如果您的路径很简单,例如您的示例(我的意思是,它们不包含正则表达式,例如

/:locale/kappa([a-z]{2})
),您可以编写这个独立于路由器的函数,您可以在其中手动处理路径并替换参数:)

function placeParams(pathRegex, params) {
  var segments = pathRegex.split("/")
  return segments.map(segment => {
    var offset = segment.indexOf(":") + 1
    if (!offset)
      return segment

    var key = segment.slice(offset)
    return params[key]
  }).join("/")
}

console.log(placeParams("/:locale/kappa", { locale: "en" }))


0
投票

这是一个改进的答案,还允许您放置可选参数。

function placeParams(pathRegex, params) {
  const segments = pathRegex.split("/");
  return (
    segments
    .map((segment) => {
      let offset = segment.indexOf(":?") + 1;

      if (offset) {
        let key = segment.slice(offset + 1);
        return params[key];
      }

      offset = segment.indexOf(":") + 1;
      if (!offset) return segment;

      let key = segment.slice(offset);
      return params[key];
    })
    .join("/")
    // Remove trailing "/"
    .replace(/\/+$/, "")
    // Remove redundant "/"
    .replace(/\/{2,}/, "/")
  );
}

console.log(placeParams("/:locale/user/:?name/:?lastname", {
  locale: "en",
  name: "Nady",
  lastname: "Shalaby"
}))

© www.soinside.com 2019 - 2024. All rights reserved.