React Router重定向丢失参数

30

我正在使用React Router的next版本,但似乎会丢失参数。我期望下面的重定向保留channelId的值,但是to路由在路径中使用了文字字符串":channelId"。

<Switch>
  <Route exact path="/" component={Landing} />
  <Route path="/channels/:channelId/modes/:modeId" component={Window} />
  <Redirect
    from="/channels/:channelId"
    to="/channels/:channelId/modes/window" />
</Switch>

看起来像一个已解决的问题,但它并没有起作用。我需要传递其他什么参数到to路由吗?


你找到解决方案了吗,Matt? - Sebastian Roth
@SebastianRoth,不幸的是我从未这样做过。现在我正在以一种不同的方式进行操作,使用组件内部的重定向。然而,如果能够验证这一点将会很好,因为它应该像上面链接的线程中所述那样工作。 - Matt Norris
1
就我个人而言,我已经在 react-router 的 Discord 频道上询问了这个问题。最终我做了类似的处理,创建了一个带有 render 方法的路由,并从 props 中提取值并返回 Redirect。 - Gabriel Isenberg
1
我认为你提供的链接并不是同一个问题。那个楼主想要在from/to中定义的参数之外添加额外的参数。我遇到了相同的情况,其中:someId作为1234输入,但在URL中被重定向为字面上的“:someID”字符串。非常令人沮丧。 - coblr
8个回答

26

这是我一直在使用的方式,与其他答案类似,但不需要依赖:

<Route
  exact
  path="/:id"
  render={props => (
    <Redirect to={`foo/${props.match.params.id}/bar`} />;
  )}
/>

这在 react-router-dom@4.2.2 中绝对有效。奇怪的是必须强制使用 Redirect 以这种方式来实现。 - worc
我在版本为 react-router-dom": "^4.2.2 的项目中得到了 /foo/undefined/bar - Badrush
1
这个运行得非常完美。请注意,在 “/foo” 前面必须添加一个斜杠,以便它成为绝对路径。 - Elron

12

我在 React Router 4 的源代码中没有找到这样的逻辑,因此编写了自己的解决方法:

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import pathToRegexp from 'path-to-regexp';
import { Route, Redirect } from 'react-router-dom';

class RedirectWithParams extends Component {
  render() {
    const { exact, from } = this.props;    
    return (
      <Route
        exact={exact}
        path={from}
        component={this.getRedirectComponent}
      />);
  }

  getRedirectComponent = ({ match: { params } }) => {
    const { push, to } = this.props;
    const pathTo = pathToRegexp.compile(to);
    return <Redirect to={pathTo(params)} push={push} />
  }
};

RedirectWithParams.propTypes = {
  exact: PropTypes.bool,
  from: PropTypes.string,
  to: PropTypes.string.isRequired,
  push: PropTypes.bool
};

export default RedirectWithParams;

使用示例:

<Switch>
   <RedirectWithParams
      exact from={'/resuorce/:id/section'}
      to={'/otherResuorce/:id/section'}
   />
</Switch>

1
看起来和你的代码几乎一样:https://github.com/ReactTraining/react-router/blob/master/packages/react-router/modules/generatePath.js - coblr

8
你可以这样做:
<Switch>
  <Route exact path="/" component={Landing} />
  <Route path="/channels/:channelId/modes/:modeId" component={Window} />
  <Route
    exact
    path="/channels/:channelId"
    render={({ match }) => (
      <Redirect to={`/channels/${match.params.channelId}/modes/window`} />   
    )}
  />
</Switch>

使用更少的代码,效果非常好。 - comiventor

5
我做了这件事,它奏效了:

<switch>
  <Route path={`/anypath/:id`} component={Anycomponent} />
   <Route
      exact
      path="/requestedpath/:id"
      render={({ match }) => {
        if (!Auth.loggedIn()) {
          return <Redirect to={`/signin`} />;
        } else {
          return <Redirect to={`/anypath/${match.params.id}`} />;
        }
      }}
    />
</switch>


4
你可以使用 generatePath 来实现此目的:
import { Switch, Route, Redirect, generatePath } from "react-router";

<Switch>
  <Route component={PageOne} path="/one" />
  <Route component={PageTwo} path="/two/:id" />
  <Route
    path="/three/:id"
    render={props => (
      <Redirect
        to={generatePath("/two/:id", {
          id: props.match.params.id,
        })}
      />
    )}
  />
  <Route component={NotFoundPage} path="*" />
</Switch>

4

自React Router 4 4.3.0版本以后,这个功能被添加了进去。如果你的版本在4.3.x之前,那么Gleb的回答是可行的。


使用React Router 4.3.1,我需要将我的“Redirect”标签放在“Switch”标签内才能使其正常工作。 - Garrett Simpson

1

在 React Router v6+ 中,你可以像这样创建自己的NavigateWithParams

import { Navigate, NavigateProps, generatePath, useParams } from 'react-router-dom';

interface Props extends NavigateProps {
  to: string;
}

const NavigateWithParams: React.FC<Props> = ({ to, ...props }) => {
  const params = useParams();

  return <Navigate {...props} to={generatePath(to, params)} />;
};

export default NavigateWithParams;

然后像这样使用它:

  <Route path="/old/:param" element={<NavigateWithParams to="/new/:param" />} />

0

以下是我使用generatePath的简短通用版本,适用于将具有相同参数的from路径重定向到to路径:

import { Route, Redirect, generatePath } from "react-router"

<Route path={from} 
       exact
       component={({match}) => 
             <Redirect to={generatePath(to, match.params)} />} />

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