【问题标题】:React-router urls not working when manually typing in browser在浏览器中手动输入时,React-router url 不起作用
【发布时间】:2020-05-30 14:27:53
【问题描述】:

当我使用导航栏和按钮在页面之间导航时,浏览器上的 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/

App.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} />

Index.js

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

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

Athletes.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/",
  });
}}

【问题讨论】:

标签: reactjs react-router


【解决方案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/url 变为localhost:3000/some/hello --> 不容易,所以避免

所以,只要您使用上述 history.push 方法进行 FIRST 和 SECOND,一切都工作正常

但是当您开始在浏览器中手动键入 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形成完整的 URL .


解决方案 2:

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

使用pathsmakePaths 定义您的路线:

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:

做嵌套路由。请参阅nesting example in docshow to do nesting?how to access URL Params i.e. :id in path


我建议使用Solution 2,但请阅读Solution 3(嵌套),如果/如果可能的话。

【讨论】:

    猜你喜欢
    • 2019-02-14
    • 2018-08-16
    • 2019-09-03
    • 1970-01-01
    相关资源
    最近更新 更多