【问题标题】:How preserve query string and hash fragment, in React-Router 4 <Switch><Redirect>?如何在 React-Router 4 <Switch><Redirect> 中保留查询字符串和哈希片段?
【发布时间】:2018-08-16 03:10:43
【问题描述】:

如果您在&lt;Route&gt; 中有一个&lt;Redirect&gt;,您将获得一个location,并且可以这样做:&lt;Redirect search={props.location.search} hash={props.location.hash} ...

但是,当直接在顶级&lt;Switch&gt; 内时,&lt;Redirect&gt; 没有任何props.location 可以访问searchhash

有没有办法直接在顶级&lt;Switch&gt; 之后的&lt;Redirect&gt; 中保留查询字符串和哈希片段(树中没有更高的&lt;Route&gt;)?

示例:(打字稿)

Router({},
  Switch({},
    Redirect({ path: '/', to: '/latest', exact: true }))))

to: '/latest' 更改为to: { pathname:... search:.. hash:.. } 不起作用,因为没有props.location 可用于访问原始.search.hash on。

在这里(https://github.com/ReactTraining/react-router/issues/5818#issuecomment-384934176),开发人员说保留查询和哈希问题已经解决,但我找不到在上述情况下有效的任何东西:

> 重定向时保存查询字符串的任何选项?

> 它将在 4.3.0 中实现。在此处查看发行说明:https://github.com/ReactTraining/react-router/releases/tag/v4.3.0-rc.1

这些发行说明链接到:https://github.com/ReactTraining/react-router/pull/5209,其中没有提及任何似乎可行的内容。

也许他们已经只在&lt;Route&gt; 中表示&lt;Redirect&gt; 了?然后,可以执行以下操作:

Route({ path: ..., render: (props) => function() {
  Redirect({ to: { pathname:... search: props.location.search, ... } ...}));

【问题讨论】:

  • Route版本有问题吗?您可以只编写一次并在任何地方使用它:let LocationRedirect = p =&gt; &lt;Route render={rp =&gt; &lt;Redirect to={p.to(rp)} /&gt;} /&gt; 或其他东西
  • @azium 是的,代码更多。读起来更复杂。我认为路由的东西已经有点复杂了,添加额外的&lt;Route 并再传递一个级别的道具,使代码更加复杂。无论如何,这也许是最好的解决方案(以防万一)。我喜欢LocationRedirect 这个名字。如果您愿意,请随时将其发布为答案......也许写下您认为没有其他解决方案?如果你这么想。 ...如果没有更简单的答案(没有额外的&lt;Route&gt; 层)出现,我可以在一周左右接受它。
  • 嗯,其他名称:PathRedirect(比“LocationRedirect”更准确?)或者RedirectPathPreserveQueryFrag。 @azium
  • 哈哈也许.. 这并不是您问题的真正答案。不过也没那么复杂。把它想象成一个函数而不是一个组件。通常函数会相互包装以提供额外的功能。这样,您只需编写一次,然后在其他任何地方使用“简单”版本。
  • “RedirectPathPreserveQueryFrag”是个糟糕的名字

标签: reactjs react-router-v4


【解决方案1】:

&lt;Redirect /&gt; 组件获得自己的历史订阅者之前,您可以创建自己的:

const RouteAwareRedirect = props => (
  <Route render={routeProps => 
    <Redirect to={props.to(routeProps)} />
  }/>
)

然后在任何你想要的地方使用它:

<RouteAwareRedirect to={({ location }) => ({ 
  // use location.pathname, etc .. 
}) />

【讨论】:

  • 嗯,“直到...获得自己的历史订阅者”——这可能意味着当前父 &lt;Route&gt;必需的?没有别的办法了吗?好的,这就是我想知道的:-)
【解决方案2】:

如果没有其他方法(显然没有,请参阅 Azium 的答案)...那么这有效 :-) 至少与 exactstrict 两者都 true (尚未测试其他组合) .

像这样使用:(它只会改变路径,而不是查询字符串或哈希)

RedirPath({ path: '/', to: '/latest', exact: true })

&lt;Switch&gt; 中工作,上面没有&lt;Route&gt;。里面有一个&lt;Route&gt;:- P 你需要删除dieIf

许可证:麻省理工学院。 (不是 CC0。)

/**
 * Redirects the URL path only — preserves query string and hash fragment.
 */
export function RedirPath(props: { path: string, to: string, exact: boolean, strict?: boolean }) {
  // @ifdef DEBUG
  dieIf(props.to.indexOf('?') >= 0, 'TyE2ABKS0');
  dieIf(props.to.indexOf('#') >= 0, 'TyE5BKRP2');
  // @endif
  const path = props.path;
  const exact = props.exact;
  const strict = props.strict;
  return Route({ path, exact, strict, render: (routeProps) => {
    return Redirect({
      from: path, exact, strict,
      to: {
        pathname: props.to,
        search: routeProps.location.search,
        hash: routeProps.location.hash }});
  }});
}

【讨论】:

    【解决方案3】:

    你可以像这样扩展&lt;Redirect /&gt;

    const UtmFriendlyRedirect = props => (
        <Redirect computedMatch={props.computedMatch}
                  to={{pathname: props.to, search: props.location.search}}/>
    )

    然后像普通重定向一样使用它:

    &lt;UtmFriendlyRedirect from='/:articleId' to='/article/:articleId'/&gt;

    【讨论】:

      【解决方案4】:

      在我非常有限的测试中,这会保留所有搜索参数。

      const RedirectAndPreserveSearch = ({ to, ...additionalProps }) => (
        <Redirect
          {...additionalProps}
          to={{
            pathname: to,
            search: new URL(window.location.href).search,
          }}
        />
      );
      

      我认为这只有在没有其他任何东西干扰搜索参数的情况下才有效(我不确定这是否会更新组件?它可能会从安装时使用搜索参数重定向?)

      我还没有尝试过,但你也可以用哈希做类似的事情。

      【讨论】:

      • 这看起来与上面 Clay 的答案相同,只是,就像你写的那样,也许你在这里需要担心会干扰搜索参数的东西。
      • 我的组件使用 DOM api window.location.href 获取 url 搜索参数,而 Clay 从必须传入的道具中获取它们。我的也会将所有其他道具传递给其中的 &lt;Redirect/&gt; .
      • 我相信它们的不同足以保证分享我的。另外我相信computedMatch 是一个私有api,最好不要使用它,以防将来更改。
      猜你喜欢
      • 1970-01-01
      • 2015-07-03
      • 2017-05-23
      • 2017-06-18
      • 1970-01-01
      • 1970-01-01
      • 2017-09-22
      • 2016-06-20
      • 2019-12-11
      相关资源
      最近更新 更多