React-Router: ไม่พบเส้นทาง?


132

พิจารณาสิ่งต่อไปนี้:

var AppRoutes = [
    <Route handler={App} someProp="defaultProp">
        <Route path="/" handler={Page} />
    </Route>,

    <Route  handler={App} someProp="defaultProp">
        <Route path="/" handler={Header} >
            <Route path="/withheader" handler={Page} />
        </Route>
    </Route>,

    <Route handler={App} someProp="defaultProp">
        <Route path=":area" handler={Area} />
        <Route path=":area/:city" handler={Area} />
        <Route path=":area/:city/:locale" handler={Area} />
        <Route path=":area/:city/:locale/:type" handler={Area} />
    </Route>
];

ฉันมีแม่แบบแอปส่วนหัวและชุดเส้นทางที่กำหนดพารามิเตอร์ด้วยตัวจัดการเดียวกัน (ภายในเทมเพลตแอป) ฉันต้องการให้บริการ 404 เส้นทางเมื่อไม่พบบางสิ่ง ตัวอย่างเช่น / CA / SanFrancisco ควรพบและจัดการโดย Area ในขณะที่ / SanFranciscoz ควรเป็น 404

นี่คือวิธีที่ฉันทดสอบเส้นทางอย่างรวดเร็ว

['', '/', '/withheader', '/SanFranciscoz', '/ca', '/CA', '/CA/SanFrancisco', '/CA/SanFrancisco/LowerHaight', '/CA/SanFrancisco/LowerHaight/condo'].forEach(function(path){
    Router.run(AppRoutes, path, function(Handler, state){
        var output = React.renderToString(<Handler/>);
        console.log(output, '\n');
    });
});

ปัญหาคือ / SanFranciscoz มักจะถูกจัดการโดยเพจ Area แต่ฉันต้องการให้เป็น 404 นอกจากนี้หากฉันเพิ่ม NotFoundRoute ในการกำหนดค่าเส้นทางแรกหน้า Area ทั้งหมด 404

<Route handler={App} someProp="defaultProp">
    <Route path="/" handler={Page} />
    <NotFoundRoute handler={NotFound} />
</Route>,

ผมทำอะไรผิดหรือเปล่า?

นี่คือส่วนสำคัญที่สามารถดาวน์โหลดและทดลองได้

https://gist.github.com/adjavaherian/aa48e78279acddc25315


สำหรับการอ้างอิงในอนาคตสำหรับผู้ที่จบลงด้วยคำถามนี้นอกเหนือจากคำตอบที่เหมาะสมด้านล่างได้อ่านในบทความนี้ ฉันเจอมันก่อนหน้านี้และฉันคิดว่าคน ๆ นั้นอธิบายได้อย่างสมบูรณ์แบบ
Dimitris Damilos

คำตอบ:


251

DefaultRoute และ NotFoundRoute ถูกลบออกใน react-router 1.0.0

ฉันต้องการเน้นว่าเส้นทางเริ่มต้นที่มีเครื่องหมายดอกจันต้องอยู่ในลำดับชั้นปัจจุบันจึงจะทำงานได้ มิฉะนั้นจะแทนที่เส้นทางอื่น ๆ ทั้งหมดที่ปรากฏหลังจากนั้นในแผนภูมิเนื่องจากเป็นเส้นทางแรกและตรงกับทุกเส้นทาง

สำหรับ react-router 1, 2 และ 3

หากคุณต้องการแสดง 404 และเก็บเส้นทาง (ฟังก์ชันเดียวกับ NotFoundRoute)

<Route path='*' exact={true} component={My404Component} />

หากคุณต้องการแสดงเพจ 404 แต่เปลี่ยน url (ฟังก์ชันเดียวกับ DefaultRoute)

<Route path='/404' component={My404Component} />
<Redirect from='*' to='/404' />

ตัวอย่างที่มีหลายระดับ:

<Route path='/' component={Layout} />
    <IndexRoute component={MyComponent} />
    <Route path='/users' component={MyComponent}>
        <Route path='user/:id' component={MyComponent} />
        <Route path='*' component={UsersNotFound} />
    </Route>
    <Route path='/settings' component={MyComponent} />
    <Route path='*' exact={true} component={GenericNotFound} />
</Route>

สำหรับ react-router 4 และ 5

รักษาเส้นทาง

<Switch>
    <Route exact path="/users" component={MyComponent} />
    <Route component={GenericNotFound} />
</Switch>

เปลี่ยนเส้นทางไปยังเส้นทางอื่น (เปลี่ยน url)

<Switch>
    <Route path="/users" component={MyComponent} />
    <Route path="/404" component={GenericNotFound} />
    <Redirect to="/404" />
</Switch>

ลำดับเรื่อง!


หากคุณมีแอป redux คุณจะทำอย่างไร: <Redirect from='*' to='/home' />ในไวยากรณ์นี้:const routes = { component: Main, childRoutes: [ { path: '/', component: Home }, ], indexRoute: { component: Main, }, };
tatsu

1
หากคุณต้องการตั้งค่าอุปกรณ์ประกอบฉากสำหรับ 404-Compontent ให้ใช้รหัสนี้:<Route render={(props)=> <MyComponent myProp={someVar} {...props} />} />
Marco Weber

แล้ว 500 หน้าล่ะ? เช่นเดียวกับหน้าที่ควรโหลด แต่ API แสดงข้อผิดพลาด จะแสดงสิ่งนี้แทนหน้าเว็บที่ล้มเหลวขณะรักษาเส้นทางได้อย่างไร?
PixMach

<เปลี่ยนเส้นทางไปยัง = "/ 404" /> ทำให้ความลึกของการอัปเดตสูงสุดเกินบน react-router-dom 5.0.0 แม้ว่าหน้า 404 จะออกไป แต่ก็เปลี่ยนเส้นทาง
MiguelSlv

5
ฉันไม่ชอบใช้การเปลี่ยนเส้นทางเพราะมันซ่อน URL ที่เป็นปัญหาจากผู้ใช้ นอกจากนี้ยังต้องกดปุ่มย้อนกลับสองครั้งเพื่อกลับไปที่หน้าก่อนหน้า
sdgfsdh

39

ใน react-router เวอร์ชันใหม่กว่าคุณต้องการรวมเส้นทางไว้ในสวิตช์ซึ่งแสดงผลเฉพาะส่วนประกอบแรกที่ตรงกันเท่านั้น มิฉะนั้นคุณจะเห็นส่วนประกอบหลายรายการแสดงผล

ตัวอย่างเช่น:

import React from 'react';
import ReactDOM from 'react-dom';
import {
  BrowserRouter as Router,
  Route,
  browserHistory,
  Switch
} from 'react-router-dom';

import App from './app/App';
import Welcome from './app/Welcome';
import NotFound from './app/NotFound';

const Root = () => (
  <Router history={browserHistory}>
    <Switch>
      <Route exact path="/" component={App}/>
      <Route path="/welcome" component={Welcome}/>
      <Route component={NotFound}/>
    </Switch>
  </Router>
);

ReactDOM.render(
  <Root/>,
  document.getElementById('root')
);

12
คุณไม่จำเป็นต้องรวมpath="*"ไว้ในเส้นทาง NotFound การละเว้นpathจะทำให้เส้นทางตรงกันเสมอ
chipit24

1
สำหรับคนที่มาสาย @ chipit24 ถูกต้องเพื่อหลีกเลี่ยงความสับสนเพียงแค่เว้นเส้นทางpathทั้งหมดสำหรับเส้นทางที่ไม่รู้จัก
Altair312

14

ด้วย React Router เวอร์ชันใหม่ (ตอนนี้ใช้ 2.0.1) คุณสามารถใช้เครื่องหมายดอกจันเป็นเส้นทางในการกำหนดเส้นทาง "เส้นทางอื่น" ทั้งหมด

มันจะมีลักษณะดังนี้:

<Route route="/" component={App}>
    <Route path=":area" component={Area}>
        <Route path=":city" component={City} />
        <Route path=":more-stuff" component={MoreStuff} />    
    </Route>
    <Route path="*" component={NotFoundRoute} />
</Route>

10

คำตอบนี้ใช้สำหรับ react-router-4 คุณสามารถรวมเส้นทางทั้งหมดในบล็อกสวิตช์ซึ่งทำหน้าที่เหมือนกับนิพจน์กรณีสวิตช์และแสดงผลองค์ประกอบด้วยเส้นทางแรกที่ตรงกัน เช่น)

<Switch>
      <Route path="/" component={home}/>
      <Route path="/home" component={home}/>
      <Route component={GenericNotFound}/> {/* The Default not found component */}
</Switch>

ควรใช้เมื่อใด exact

ไม่มีที่แน่นอน:

<Route path='/home'
       component = {Home} />

{/* This will also work for cases like https://<domain>/home/anyvalue. */}

ด้วยความแน่นอน:

<Route exact path='/home'
       component = {Home} />

{/* 
     This will NOT work for cases like https://<domain>/home/anyvalue. 
     Only for https://<url>/home and https://<domain>/home/
*/}

ตอนนี้หากคุณยอมรับพารามิเตอร์การกำหนดเส้นทางและหากปรากฎว่าไม่ถูกต้องคุณสามารถจัดการได้ในองค์ประกอบเป้าหมายเอง เช่น)

<Route exact path='/user/:email'
       render = { (props) => <ProfilePage {...props} user={this.state.user} />} />

ตอนนี้อยู่ใน ProfilePage.js

if(this.props.match.params.email != desiredValue)
{
   <Redirect to="/notFound" component = {GenericNotFound}/>
   //Or you can show some other component here itself.
}

สำหรับรายละเอียดเพิ่มเติมคุณสามารถอ่านรหัสนี้:

App.js

ProfilePage.js


6

อ้างอิงถึงเอกสารเส้นทางถูกพบแม้ว่าทรัพยากรไม่ได้

หมายเหตุ : สิ่งนี้ไม่ได้มีไว้สำหรับใช้เมื่อไม่พบทรัพยากร มีความแตกต่างระหว่างเราเตอร์ที่ไม่พบเส้นทางที่ตรงกันและ URL ที่ถูกต้องซึ่งส่งผลให้ไม่พบทรัพยากร หลักสูตร url / 123 เป็น URL ที่ถูกต้องและส่งผลให้มีเส้นทางที่ตรงกันดังนั้นจึง "พบ" เท่าที่เกี่ยวข้องกับการกำหนดเส้นทาง จากนั้นหากเราดึงข้อมูลบางส่วนและพบว่าไม่มีหลักสูตร 123 อยู่เราไม่ต้องการเปลี่ยนไปใช้เส้นทางใหม่ เช่นเดียวกับบนเซิร์ฟเวอร์คุณดำเนินการต่อและให้บริการ URL แต่แสดง UI ที่แตกต่างกัน (และใช้รหัสสถานะอื่น) คุณไม่ควรพยายามเปลี่ยนเป็น NotFoundRoute

ดังนั้นคุณสามารถเพิ่มบรรทัดในRouter.run()ก่อนหน้านี้React.render()เพื่อตรวจสอบว่าทรัพยากรนั้นถูกต้องหรือไม่ เพียงแค่ส่งเสาลงไปที่คอมโพเนนต์หรือแทนที่Handlerคอมโพเนนต์ด้วยคอมโพเนนต์ที่กำหนดเองเพื่อแสดงมุมมอง NotFound


ขอบคุณ @brad คุณพูดถูกคุณต้องจัดการกับองค์ประกอบนี้และหรือแทนที่ตัวจัดการก่อนที่เราเตอร์รัน
4m1r

3
NotFound เลิกใช้แล้วgithub.com/reactjs/react-router/releases/tag/v1.0.0ตอนนี้ใช้<Route path="*" to="/dest" />หรือ<Redirect from="*" to="/dest" />เป็นเส้นทางย่อยสุดท้ายที่จะจับคู่ฉันเชื่อว่า
ptim

5

ฉันเพิ่งดูตัวอย่างของคุณอย่างรวดเร็ว แต่ถ้าฉันเข้าใจวิธีที่ถูกต้องคุณกำลังพยายามเพิ่มเส้นทาง 404 ไปยังกลุ่มไดนามิก ฉันมีปัญหาเดียวกันเมื่อสองสามวันก่อนพบ# 458และ# 1103และลงเอยด้วยการตรวจสอบด้วยมือภายในฟังก์ชันการแสดงผล:

if (!place) return <NotFound />;

หวังว่าจะช่วย!


ขอบคุณ @jorn ฉันคิดว่าคุณพูดถูกดูเหมือนว่าจะสามารถระบุได้จากระดับส่วนประกอบเท่านั้น
4m1r
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.