Передача реквизита в компонент Redirect (React.js) не работает должным образом - PullRequest
0 голосов
/ 11 октября 2018

Я работаю через приложение для практики, чтобы познакомиться с 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>
    );
  }
}

Нов этом случае я могу выполнить перенаправление только без сообщения в пользовательском интерфейсе.

Я пытаюсь передать реквизиты на home или "/", поэтому, если кто-то сделал , то изTeamPage.Маршрут в моем App компоненте будет отвечать этим сообщением, как обычно.

Выдержка из 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) }
      }}
    />
  );
}

Можно ли это сделать?

Спасибозаранее!

Обновление 11 октября 2:56 PM

Так, согласно великому пониманию Ханнада, я обновил свои App component и TeamPage component и создал перехват всех ErrorPageмаршрут.Теперь мне нужно обновить файл Teams.js, так как при попытке перейти на http://localhost:3000/teams/foo я получаю следующую ошибку:

enter image description here

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

1 Ответ

0 голосов
/ 11 октября 2018

есть другой способ сделать 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 Component

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