在浏览器中手动输入时,React-router url 不起作用

IT技术 reactjs react-router
2021-04-28 05:52:39

当我使用导航栏和按钮在页面之间导航时,浏览器上的 URL 会正常更改。但是一旦我尝试手动修改 URL,它就不起作用了!

示例 1

  • 第 1 步:我打开localhost:3000
  • 第 2 步:我点击 Athletes 转到localhost:3000/Athletes
  • 第 3 步:我选择一个运动员去localhost:3000/Athletes/2/AthleteSessions/
  • 第 4 步:我手动将 URL 更改为localhost:3000/Athletes然后我选择一个运动员,我被重定向到localhost:3000/Athletes/2/AthleteSessions/直到现在,但是当我修改 URL 以放置localhost:3000 /Athletes/斜线然后我选择一个运动员它不起作用,我被重定向到localhost:3000/Athletes/Athletes/2/AthleteSessions/

示例 2

  • 步骤 1、2 和 3 与第一个示例相同。
  • 第 4 步:我选择一个 AthleteSession 转到localhost:3000/Athletes/2/AthleteSessions/1/TrainingSession/它工作正常,但是当我尝试通过手动修改 URL localhost:3000/Athletes/2返回上一页时/AthleteSessions然后我再次选择一个 AthleteSession,它不起作用,我被重定向到localhost:3000/Athletes/2/1/TrainingSession/

应用程序.js

import { Route, Switch, Redirect } from "react-router-dom";

<Route path="/Athletes" exact component={Athletes} />
<Route path="/Athletes/:id/AthleteSessions" exact component={AthleteSessions} />
<Route path="/Athletes/:athleteId/AthleteSessions/:athleteSessionId/TrainingSession"
       exact component={AthleteTrainingSession} />

索引.js

import { BrowserRouter as Router } from "react-router-dom";

render( <Router> <App /> </Router>, document.getElementById("root") );

运动员.js

onClick={() => {
  this.props.history.push({
    pathname:
      "Athletes/" + ath.AthleteId + "/AthleteSessions/",
  });
}}

AthleteSessions.js

passedAthleteId = this.props.match.params.id;

onClick={() => {
  this.props.history.push({
    pathname:
      athSess.AthleteSessionId + "/TrainingSession/",
  });
}}
1个回答

当前的路线定义很好

<Switch>
    <Route exact path="/" component={Home} />
    <Route exact path="/Athletes" component={Athletes} />
    <Route
        exact
        path="/Athletes/:id/AthleteSessions"
        component={AthleteSessions}
    />
    <Route
        exact
        path="/Athletes/:athleteId/AthleteSessions/:athleteSessionId/TrainingSession"
        component={AthleteTrainingSession}
    />
</Switch>

但是,去你任何航线目前在做history.push领导/,并与尾随/导致问题

// FIRST (lets refer it first)
onClick={() => { 
    this.props.history.push({
    pathname:
        "Athletes/" + ath.AthleteId + "/AthleteSessions/",
    });
}}

// SECOND (lets refer it second)
onClick={() => {
    this.props.history.push({
    pathname:
        athSess.AthleteSessionId + "/TrainingSession/",
    });
}}

history.push('/hello')localhost:3000/some/urllocalhost:3000/hello-->容易理解

history.push('hello')localhost:3000/some/urllocalhost:3000/some/hello-->没那么容易,所以避免

因此,只要您使用上述方法进行 FIRST 和 SECOND ,一切都正常history.push

但是当您开始在浏览器中手动输入 URL时,问题就开始了,有时有结尾,有时没有结尾/


解决方案1:

更改您的 FIRST 和 SECOND 以使用带前导和无尾随的完全限定网址,尾随不再重要,因为我们使用完全限定网址。另请参阅Strict-Bool///

// FIRST
onClick={() => { 
    this.props.history.push({
    pathname:
        "/Athletes/" + ath.AthleteId + "/AthleteSessions",
    });
}}

// SECOND
onClick={() => {
  this.props.history.push({
    pathname: `/Athletes/${this.props.match.params?.id}/AthleteSessions/${athSess.AthleteSessionId}/TrainingSession`,
  });
}}

正如我们现在使用的完全限定的网址,它会工作完美,但代码似乎很难管理,你将形成完整的URL在每个history push


解决方案2:

与解决方案 1 相同,但代码更好:

使用paths定义您的路线makePaths

export const paths = {
  Athletes: "/Athletes",
  AthleteSessions: "/Athletes/:id/AthleteSessions",
  AthleteTrainingSession:
    "/Athletes/:athleteId/AthleteSessions/:athleteSessionId/TrainingSession",
};

export const makePaths = {
  AthleteSessions: (id) => {
    return `/Athletes/${id}/AthleteSessions`;
  },
  AthleteTrainingSession: (athleteId, athleteSessionId) => {
    return `/Athletes/${athleteId}/AthleteSessions/${athleteSessionId}/TrainingSession`;
  },
};

// in JSX
<Switch>
  <Route exact path="/" component={Home} />
  <Route exact path={paths.Athletes} component={Athletes} />
  <Route exact path={paths.AthleteSessions} component={AthleteSessions} />
  <Route
    exact
    path={paths.AthleteTrainingSession}
    component={AthleteTrainingSession}
  />
</Switch>

并且history.push

// FIRST
onClick={() => {
  this.props.history.push({
    pathname: makePaths.AthleteSessions(ath.AthleteId),
  });
}}

// SECOND
onClick={() => {
  this.props.history.push({
    pathname: makePaths.AthleteTrainingSession(
      this.props.match.params?.id,
      athSess.AthleteSessionId
    ),
  });
}}


解决方案3:

做嵌套路由。请参阅文档中的嵌套示例如何进行嵌套?以及如何访问 URL Params ie :idin path


我建议使用解决方案 2,但请阅读解决方案 3(嵌套),如果可能的话,请使用它。