我正在通过一个练习应用程序来结识React-Router
在我的App
组件中,我有一条路线,该路线可以负担404's
class App extends Component {
render() {
return (
<Router>
<div>
<Navbar />
<Switch>
<Route path="/" exact component={Home} />
<Route path="/players" component={Players} />
<Route path="/teams" component={Teams} />
{/* params should be last Route as it would match players and teams */}
<Route path="/:teamId" exact component={TeamPage} />
<Route
render={({ location }) => (
<h1 className="text-center">
Sorry, we couldn't find {location.pathname.substr(1)} <br />{" "}
404: page not found.
</h1>
)}
/>
</Switch>
</div>
</Router>
);
}
}
那很好。
但是我有一个另一个组件TeamPage
,该组件基本上具有相同的机制。
import React, { Component } from "react";
import { Redirect, Link } from "react-router-dom";
import { getTeamNames, getTeamsArticles } from "../api";
import TeamLogo from "./TeamLogo";
import Team from "./Team";
import slug from "slug";
export default class TeamPage extends Component {
state = {
loading : true,
teamNames: {},
articles : []
};
componentDidMount() {
Promise.all([
getTeamNames(),
getTeamsArticles(this.props.match.params.teamId)
]).then(([teamNames, articles]) => {
this.setState(() => ({
teamNames,
articles,
loading: false
}));
});
}
render() {
const { loading, teamNames, articles } = this.state;
const { match } = this.props;
const { teamId } = match.params;
if (loading === false && teamNames.includes(teamId) === false) {
return (
<Redirect
to={{
pathname: "/",
location: { location: window.location.pathname.substr(1) }
}}
/>
);
}
return (
<div>
<Team id={teamId}>
{team =>
team === null ? (
<h1>LOADING</h1>
) : (
<div className="panel">
<TeamLogo id={teamId} />
<h1 className="medium-header">{team.name}</h1>
<h4 style={{ margin: 5 }}>
<Link
style = {{ cursor: "pointer" }}
to = {{ pathname: "/players", search: `?teamId=${teamId}` }}
>
View Roster
</Link>
</h4>
<h4>Championships</h4>
<ul className="championships">
{team.championships.map(ship => (
<li key={ship}>{ship}</li>
))}
</ul>
<ul className="info-list row" style={{ width: "100%" }}>
<li>
Established
<div>{team.established}</div>
</li>
<li>
Manager
<div>{team.manager}</div>
</li>
<li>
Coach
<div>{team.coach}</div>
</li>
<li>
Record
<div>
{team.wins}-{team.losses}
</div>
</li>
</ul>
<h2 className="header">Articles</h2>
<ul className="articles">
{articles.map(article => (
<li key={article.id}>
<Link to={`${match.url}/articles/${slug(article.title)}`}>
<h4 className="article-title">{article.title}</h4>
<div className="article-date">
{article.date.toLocaleDateString()}
</div>
</Link>
</li>
))}
</ul>
</div>
)
}
</Team>
</div>
);
}
}
但是在这种情况下,我只能完成重定向,而UI中不会显示任何消息。
我正在尝试将道具传递给home
或"/"
,所以如果有人从TeamPage
提出了建议。我的App
组件中的Route会像往常一样用该消息进行响应。
TeamPage的摘录:
const { loading, teamNames, articles } = this.state;
const { match } = this.props;
const { teamId } = match.params;
if (loading === false && teamNames.includes(teamId) === false) {
return (
<Redirect
to={{
pathname: "/",
location: { location: window.location.pathname.substr(1) }
}}
/>
);
}
可以做到吗?
谢谢!
更新10月11日下午2:56
因此,根据Hannad的深刻见解,我更新了App component
和TeamPage component
并创建了一条捕获所有ErrorPage路由。我现在需要做的是更新Teams.js
文件,因为当我尝试转到http://localhost:3000/teams/foo
时出现以下错误:
import React, { Component } from "react";
import { Redirect, Route, Link } from "react-router-dom";
import Sidebar from "./Sidebar";
import { getTeamNames } from "../api";
import TeamLogo from "./TeamLogo";
import Team from "./Team";
export default class Teams extends Component {
state = {
teamNames: [],
loading : true
};
componentDidMount() {
getTeamNames().then(teamNames => {
this.setState(() => ({
loading: false,
teamNames
}));
});
}
render() {
const { loading, teamNames } = this.state;
const { location, match } = this.props;
return (
<div className="container two-column">
<Sidebar
loading = {loading}
title = "Teams"
list = {teamNames}
{...this.props}
/>
{loading === false &&
(location.pathname === "/teams" || location.pathname === "/teams/") ? (
<div className="sidebar-instruction">Select a Team</div>
) : null}
<Route
path = {`${match.url}/:teamId`}
render = {({ match }) => (
<div className="panel">
<Team id={match.params.teamId}>
{team =>
team === null ? (
<h1>Loading</h1>
) : (
<div style={{ width: "100%" }}>
<TeamLogo id={team.id} className="center" />
<h1 className="medium-header">{team.name}</h1>
<ul className="info-list row">
<li>
Established
<div>{team.established}</div>
</li>
<li>
Manager
<div>{team.manager}</div>
</li>
<li>
Coach
<div>{team.coach}</div>
</li>
</ul>
<Link
className = "center btn-main"
to = {`/${match.params.teamId}`}
>
{team.name} Team Page
</Link>
</div>
)
}
</Team>
</div>
)}
/>
</div>
);
}
}
答案 0 :(得分:2)
还有另一种进行404重定向的方法。我会建议。因为它拥有更多控制权。.
定义需要简单参数的错误组件。
class App extends Component {
render() {
return (
<Router>
<div>
<Navbar />
<Switch>
<Route path="/" exact component={Home} />
<Route path="/players" component={Players} />
<Route path="/teams" component={Teams} />
{/* params should be last Route as it would match players and teams */}
<Route path="/:teamId" exact component={TeamPage} />
<Route path="/error/:errortype" exact component={ErrorPage} />
</Switch>
</div>
</Router>
);
}
}
//您的重定向逻辑
const { loading, teamNames, articles } = this.state;
const { match } = this.props;
const { teamId } = match.params;
if (loading === false && teamNames.includes(teamId) === false) {
return (
<Redirect
to={'/error/404'}
/>
);
}
// ErrorPage组件
const ErorPage = ({match: { params:{ errortype } }})=>(
// have your logic for different templates for different types of errors.
// ex.
<div>
{
errortype === 404 ?
<div>you got a 404</div> :
<div>sone generic message</div>
// this logic can change with respect to your app.
}
</div>
)