如何在 React-Router 的 URL 中移除末尾斜杠

10

我开始在我的应用程序中使用react-router,发现当URL末尾带有斜杠(/url/)时,它无法正常工作。我搜索了更多相关内容,阅读了所有文档和react-router问题,并尝试使用<Redirect from='/*/' to="/*" />,但这并不是一个好的解决方案,因为它也无法正常工作。因此,我继续阅读,发现有一个建议是在URL末尾插入/?,但仍然没有起作用。

路由代码:

export default (
    <Route path="/" component={App}>
        <IndexRoute component={ProfileFillComponents} />
        <Route path="/seguro-residencia" handler={require('./components/Forms/Residencial/ProfileFill/profileFillComponents')} />
        <Route path="/seguro-residencia/informacoes-pessoais" component={CotationNumber} />
    </Route>
)

index.js的代码:

render((<Router history={browserHistory} routes={routes} />), document.getElementById('root'));

我继续搜索,发现有个人写了一个函数来强制在URL末尾添加斜杠,于是我决定制作相反的功能,强制不要加上斜杠。

使用“无斜杠函数”更新routes.js代码:

export default (
    <Route onEnter={forceTrailingSlash} onChange={forceTrailingSlashOnChange}>
        <Route path="/" component={App}>
            <IndexRoute component={ProfileFillComponents} />
            <Route path="/seguro-residencia" handler={require('./components/Forms/Residencial/ProfileFill/profileFillComponents')} />
            <Route path="/seguro-residencia/informacoes-pessoais" component={CotationNumber} />
        </Route>
    </Route>
)

function forceNoTrailingSlash(nextState, replace) {
  const path = nextState.location.pathname;
  if (path.slice(-1) === '/') {
    replace({
      ...nextState.location,
      pathname: path.slice(1,path.lastIndexOf('/')-1)
    });
  }
}    

function forceNoTrailingSlashOnChange(prevState, nextState, replace) {
  forceNoTrailingSlash(nextState, replace);
}

这又不起作用了!我需要尽可能地使这些URL更加友好,并且我希望URL在结尾处没有任何斜杠。你有什么建议可以帮忙实现吗?为什么重定向在这种情况下没有起作用?

3个回答

8

React Router v6 solution

RemoveTrailingSlash.tsx

import React from "react";
import {Navigate, useLocation} from "react-router-dom";

export const RemoveTrailingSlash = ({...rest}) => {
    const location = useLocation()

    // If the last character of the url is '/'
    if (location.pathname.match('/.*/$')) {
        return <Navigate replace {...rest} to={{
            pathname: location.pathname.replace(/\/+$/, ""),
            search: location.search
        }}/>
    } else return null
}

AppRoutes.tsx

const AppRoutes: React.FC = () => {
    return (
        <React.Fragment>
            <RemoveTrailingSlash/>
            <Routes>
            {/* All your routes go here */}
            </Routes>
        </React.Fragment>
    )
}

谢谢,这正是我想要的!如果我们能让正则表达式匹配在“Route”的“path”属性内起作用(并从“Route”内部复制此行为),那就太好了,但我无法做到。 - Avi Nerenberg

3
我找到一个很好的选项来进行重定向。以下是我正在使用的代码:
   app.use(function(req, res, next) {
      if (req.path.length > 1 && /\/$/.test(req.path)) {
        var query = req.url.slice(req.path.length)
        res.redirect(301, req.path.slice(0, -1) + query)
      } else {
        next()
      }
    });

简单来说,这个函数的作用如下:

  1. 首先,验证URL是否包含超过一个字符并且最后一个字符是斜杠。
  2. 如果是,将去掉最后一个斜杠的URL进行301重定向。
  3. 否则,跳转到下一个方法以发送一个值。

1
哦,我本来期望有一些客户端的解决方案。但这个也可以。不过如何维护应用程序的状态呢? - master_dodo
2
该过程不涉及状态,它是在服务器端进行的。因此,它不会干扰您的应用程序。您可以将其路由传递到URL中,而无需添加尾随斜杠。这里只是客户端点击时。要使此功能在路由中正常工作,您可以使用'react-route'并创建类似于此的内容:<Route path="/your-url-extension" component={ProfilePage} />,而不使用尾随斜杠。它不会在您的应用程序中引起任何错误。祝你好运! - Aipi
谢谢回复。你说得对。但在我的情况下,我正在使用声明性URL,并且这些URL可能不会在URL中提到(就像在Dropbox中,URL是根据用户创建新文件夹而动态生成的)。所以,在这种情况下可能行不通。但我猜服务器端是唯一的好解决方案。 - master_dodo

0

使用v6.4的新路由,可以提供一种简单的解决方案

<Route // remove trailing slash
 path="*(/+)"
 loader={({ params }) => redirect(params['*'] || '/')}
/>

这基本上是用没有尾随斜杠的路由替换匹配的路由。我会将其嵌套在您的主要路由下面,就像这样:

<Route path="/" element={<App />}>
  <Route // remove trailing slash
   path="*(/+)"
   loader={({ params }) => redirect(params['*'] || '/')}
  />
</Route>

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