React Router v4 - 使用不同的查询参数重定向到相同的路由

Posted

技术标签:

【中文标题】React Router v4 - 使用不同的查询参数重定向到相同的路由【英文标题】:React Router v4 - Redirect to same route with different query params 【发布时间】:2018-11-04 01:54:57 【问题描述】:

场景:

有一个主页,从那里搜索用户被重定向到一个带有查询参数的搜索页面(例如 q=abc)。现在在搜索页面上,用户再次尝试搜索不同的值,因此他再次被重定向到相同的搜索页面,但查询参数不同(例如 q=xyz)

问题:

当我尝试使用不同的查询参数再次从搜索页面执行重定向到同一路由时,我收到错误消息“您尝试重定向到当前所在的同一路由”。

预期结果:

用户应该使用不同的查询参数再次重定向到相同的路由,以便在按下返回按钮时,他可以返回到上一个查询,就像它不是 SPA 时一样。结果应该类似于我使用相同组件将用户从 /search/abc 重定向到 /search/xyz 的情况。

可能的解决方案:

在提交搜索查询时,我可以检查它是否是相同的路由,并基于此我可以以某种方式重定向或更新组件状态。此解决方案的问题是用户无法在单击浏览器的后退按钮时返回上一个查询。我希望将页面添加到历史记录中。

代码片段:

在主页和搜索页面上都存在的搜索组件内的渲染函数中使用以下代码进行重定向

if (this.state.isReady) 
        let queryString = "q=" + this.state.q;
        return (
            <Redirect push to=`/search/hotels?$queryString` />
        );
    

我认为这是任何具有搜索功能的网站的常见问题,因此应该有一种优雅的方式来处理这种情况,但我无法考虑。

【问题讨论】:

你是如何重定向的?你能显示那个代码吗? @azium 添加重定向代码 sn-p 【参考方案1】:

找到解决方案:

我没有使用 React Router 中的 &lt;Redirect /&gt;,而是使用 history api 推送新路由。

this.props.history.push(`/search/hotels?$queryString`);

我将我的 SearchComponent 包裹在 withRouter 中,这是一个由 React-Router 提供的 HOC,然后使用了 history api。

代码片段:

import  withRouter  from 'react-router-dom';

class SearchComponent 

    // Component Code goes here

    onSubmit()
        let queryString = "q=" + this.state.q;
        this.props.history.push(`/search/hotels?$queryString`);
    


export default withRouter(SearchComponent)

【讨论】:

我们不得不放弃&lt;Redirect/&gt; 并求助于手动使用history API 似乎很奇怪。有没有人通过严格使用&lt;Redirect/&gt; 来解决这个问题? @Danchez 我同意这是一个奇怪的问题,但坦率地说,我更喜欢使用历史 API 而不是渲染组件。这种重定向通常发生在事件的情况下,并且能够通过代码处理它而不是保持状态条件是否呈现 是相当干净的。 但是每当我更改 queryString 时,如何在当前组件的某处获取此值?【参考方案2】:

您可以使用对象表示法而不是字符串文字,并传递一个包含您要重定向到示例的新路径名的位置对象


const Topic = ( location ) => (
   <Redirect to= ...location, pathname: '/topics?user=prolific'  />
)

所以使用扩展运算符,您可以保留以前的位置属性,然后您可以将路径名更改为您想要的。

在将新路由传递给重定向组件之前,您可以对新路由的查询进行格式化并添加路由名称。例如


const Topic = ( location ) => 
   const userQuery = 'user=prolific&title=The Long Night';
   const newRoute = `topics?$userQuery`

   return <Redirect to=newRoute />


希望有帮助

【讨论】:

【参考方案3】:

Ebis 答案对我来说不能正常工作。 直接向pathname添加查询字符串时,react router尝试匹配路径,导致使用Redirect组件时找不到路由

一种解决方法是在查询字符串之前添加/,如下所示:

<Redirect to= pathname: `/search/hotels/?$queryString`  />

但是,这似乎不对。相反,我只添加了pathname 的路径,并将查询字符串添加到search 键,如下所示:

<Redirect to= pathname: '/search/hotels', search: `?$queryString`  />

【讨论】:

【参考方案4】:

我找到的最简单的解决方案就是使用 location.search 属性:

<Redirect from="/color-profile/quiz" to=`/quiz?$props.location.search` exact />

【讨论】:

您需要包含一个“?”在您的示例中进行测验之后,否则这是一个很好的答案。【参考方案5】:

对于react-router-dom v5.1,to 对象可以包含search 字段

<Redirect to= pathname: "/search/hotels", search: `?$queryString`  />

如果您手动连接 pathname 中的那些,它在我的用例中不会按预期工作。注意 ? 包含在 search 参数中。

此外,这个to 结构与使用RouterComponentProps 时返回的形状相似。

import  RouteComponentProps  from 'react-router-dom';

interface Props extends RouteComponentProps<> 

export function GoToPrevious(props: Props) 
  // previous page
  let from = (props.history.location.state as any)?.from
  // remember to check undefined's here
  return <Redirect to=from></>;

【讨论】:

【参考方案6】:

这是我使用 React 钩子的解决方案。 为这些组件创建了一个新文件,并在我需要的地方导入。

import  Route, Link, useLocation, Redirect  from 'react-router-dom';

export const LinkWithQuery = ( children, to, ...props ) => 
  const  search  = useLocation();

  return (
    <Link to=to + search ...props>
      children
    </Link>
  );
;

export const RedirectWithQuery = ( to, exact, from ) => 
  return (
    <Route
      exact=exact
      path=from
      render=(props) => <Redirect to=`$to$props.location.search` />
    />
  );
;

【讨论】:

以上是关于React Router v4 - 使用不同的查询参数重定向到相同的路由的主要内容,如果未能解决你的问题,请参考以下文章

在 react-router v4 中对不同的路由路径使用相同的组件

React-router v4教程

在 react-router V4 中,如何以编程方式设置查询字符串参数?

使用 React Router v4.1 的分页问题

javascript 使用React Router v4的多个布局

使用 React Router v4 正确重定向