在浏览器中手动输入时,React-router url 不起作用 [英] React-router urls not working when manually typing in browser

查看:91
本文介绍了在浏览器中手动输入时,React-router 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" 精确组件={Athletes}/><Route path="/Athletes/:id/AthleteSessions" 精确组件={AthleteSessions}/><路线路径="/Athletes/:athleteId/AthleteSessions/:athleteSessionId/TrainingSession"精确分量={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({路径名:"运动员/" + ath.AthleteId + "/AthleteSessions/",});}}

AthleteSessions.js

passedAthleteId = this.props.match.params.id;onClick={() =>{this.props.history.push({路径名:athSess.AthleteSessionId + "/TrainingSession/",});}}

解决方案

您的当前路线定义很好:

<开关><路由精确路径="/" component={Home}/><路线精确路径="/Athletes" component={Athletes}/><路线精确的path="/Athletes/:id/AthleteSessions"组件={AthleteSessions}/><路线精确的path="/Athletes/:athleteId/AthleteSessions/:athleteSessionId/TrainingSession"组件={AthleteTrainingSession}/></开关>

但是要前往您目前正在做的任何路线history.push 没有前导/,并带有尾随/导致问题:

//FIRST(让我们先参考它)onClick={() =>{this.props.history.push({路径名:"运动员/" + ath.AthleteId + "/AthleteSessions/",});}}//第二(让我们第二次引用它)onClick={() =>{this.props.history.push({路径名:athSess.AthleteSessionId + "/TrainingSession/",});}}

<块引用>

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

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

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

但是当您在浏览器中手动键入网址问题就开始了,有时以结尾/有时没有.


解决方案 1:

更改您的 FIRST 和 SECOND 以使用 完全限定的 url 与前导 / 并且没有尾随 /,尾随 / 不再重要,因为我们使用完全限定的 url.另请参阅Strict-Bool:

//第一个onClick={() =>{this.props.history.push({路径名:"/Athletes/" + ath.AthleteId + "/AthleteSessions",});}}//第二onClick={() =>{this.props.history.push({路径名:`/Athletes/${this.props.match.params?.id}/AthleteSessions/${athSess.AthleteSessionId}/TrainingSession`,});}}

由于我们现在使用的是完全限定的 URL,它会工作完美,但代码似乎很难管理,因为您将在每个 形成完整的 URL历史推送.


解决方案 2:

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

使用pathsmakePaths 定义你的路由:

export const 路径 = {运动员: "/运动员",AthleteSessions: "/Athletes/:id/AthleteSessions",运动员训练课程:"/Athletes/:athleteId/AthleteSessions/:athleteSessionId/TrainingSession",};导出 const makePaths = {AthleteSessions: (id) =>{返回`/Athletes/${id}/AthleteSessions`;},AthleteTrainingSession: (athleteId, athleteSessionId) =>{返回`/Athletes/${athleteId}/AthleteSessions/${athleteSessionId}/TrainingSession`;},};//在 JSX 中<开关><路由精确路径="/" component={Home}/><路由精确路径={paths.Athletes} component={Athletes}/><路由精确路径={paths.AthleteSessions} 组件={AthleteSessions}/><路线精确的路径={paths.AthleteTrainingSession}组件={AthleteTrainingSession}/></开关>

history.push:

//第一个onClick={() =>{this.props.history.push({路径名:makePaths.AthleteSessions(ath.AthleteId),});}}//第二onClick={() =>{this.props.history.push({路径名:makePaths.AthleteTrainingSession(this.props.match.params?.id,athSess.AthleteSessionId),});}}


解决方案 3:

做嵌套路由.请参阅文档中的嵌套示例如何进行嵌套?如何访问 URL 参数,即 :id 在路径.


我建议使用解决方案 2,但一定要阅读解决方案 3(嵌套),如果/在可能的情况下使用它.

When I navigate between pages using the navbar and the buttons, the URL on the browser changes normally. But once I try to modify the URL manually, it does not work !

Example 1

  • Step 1 : I open localhost:3000
  • Step 2 : I click on Athletes to go to localhost:3000/Athletes
  • Step 3 : I choose an athlete to go to localhost:3000/Athletes/2/AthleteSessions/
  • Step 4 : I change the URL manually to localhost:3000/Athletes then I choose an athlete, I'm redirected to localhost:3000/Athletes/2/AthleteSessions/ fine until now, but when I modify the URL to put localhost:3000/Athletes/ with a slash then I choose an athlete it does not work and I'm redirected to localhost:3000/Athletes/Athletes/2/AthleteSessions/

Example 2

  • Step 1, 2 and 3 are the same as the first example.
  • Step 4 : I choose an AthleteSession to go to localhost:3000/Athletes/2/AthleteSessions/1/TrainingSession/ it works fine, but when I try to go back to previous page by modifying manually the URL localhost:3000/Athletes/2/AthleteSessions then I choose an AthleteSession again, it does not work and I'm redirected to 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/",
  });
}}

解决方案

Your current route definition is fine:

<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>

But to go to any route you are currently doing history.push without leading /, and with a trailing / which causes the problem:

// 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') takes from localhost:3000/some/url to localhost:3000/hello --> Easy to understand

history.push('hello') takes from localhost:3000/some/url to localhost:3000/some/hello --> Not so easy, so avoid

So, everything is working fine as long as you are going to FIRST and SECOND using above history.push methods.

But problems start when you start manually typing a URL in the browser, sometimes with an ending / and sometimes without one.


Solution 1:

Change your FIRST and SECOND to use fully qualified urls with leading / and no trailing /, trailing / isn't important anymore as we using full qualified urls. Also, see 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`,
  });
}}

As we are now using full qualified URLs, it will work perfectly but the code seems hard to manage as you will be forming the full urls at each history push.


Solution 2:

SAME as Solution 1 but better code:

Define your routes using paths and 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>

And 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
    ),
  });
}}


Solution 3:

Do nested routing. See nesting example in docs, how to do nesting? and how to access URL Params i.e. :id in path.


I would recommend going with Solution 2 but do read Solution 3 (nesting) and if / when possible go with that.

这篇关于在浏览器中手动输入时,React-router url 不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆