单击 ReactJs 中 table 行中的 link 时如何在不同页面中呈现组件

How to render a component in a different page when click on a link in a table row in ReactJs

我是 ReactJs 的初学者,我有一个 ProjectsList 组件,其中包含一个 html table。其中一列是 link,单击它时必须导航到呈现 ProjectInfo 组件的不同页面。

但是,发生的情况是该组件在 table 末尾的 ProjectsList 组件的同一页面中呈现。 单击 Projects 组件中的 link Show Projects 时呈现 ProjectsList 组件。

Projects.component.jsx

import React, { Component } from "react";
import { Link, Route, Switch } from "react-router-dom";
import NewProject from "../NewProject/NewProject.component";
import ProjectsList from "../ProjectsList/ProjectsList.component";
import "./Projects.css";

export default class Projects extends Component {
  render() {
    return (
      <div className="projects-dashboard">
        <nav className="nav-up">
          <ul>
            <li>
              <Link to={"/dashboard/projects/add"}>add project</Link>
            </li>

            <li>
              <Link to={"/dashboard/projects/list"}>show projects</Link>
            </li>
          </ul>
        </nav>
        <main>
          <Route path={"/dashboard/projects/add"} component={NewProject} />
          <Route path={"/dashboard/projects/list"} component={ProjectsList} />
        </main>
      </div>
    );
  }
}

ProjectsList.component.jsx

import React, { Component } from "react";
import axios from "axios";
import { Route, Link } from "react-router-dom";
import "./ProjectsList.css";
import ProjectInfo from "../ProjectInfo/ProjectInfo.component";

export default class ProjectsList extends Component {
  constructor(props) {
    super(props);
    this.state = {
      allProject: []
    }
  }

  componentWillMount() {
    this.fetchAllProjects();
  }

  componentDidMount() {
    document.body.style.overflowY = "auto";
  }

  fetchAllProjects = () => {
    axios.get("/api/projects").then(res => {
      this.setState({ allProject: res.data }, () => { console.log(this.state.allProject); });
    });
  };

  render() {
    const projects = this.state.allProject.map(project => {
      return (
        <tr>
          <td>{project.id}</td>
          <td>{project.title}</td>
          <td>{project.organization_name}</td>
          <td className="project-options">
            <Link to={`/dashboard/projects/list/${project.id}`}>
              <i className="far fa-eye" /> show
            </Link>
          </td>
        </tr>
      );
    });

    return (
      <div>
        <table class="projects-list-table">
          <thead>
            <tr>
              <th>
                <h1>Project ID</h1>
              </th>
              <th>
                <h1>Project Name</h1>
              </th>
              <th>
                <h1>Organization Name</h1>
              </th>
              <th>
                <h1>Options</h1>
              </th>
            </tr>
          </thead>
          <tbody>{projects}</tbody>
        </table>
        <main>
          <Route path={"/dashboard/projects/list/:id"} component={ProjectInfo} />
        </main>
      </div>
    );
  }
}

ProjectInfo.component.jsx

import React, { Component } from 'react';
import "./ProjectInfo.css";

export default class ProjectInfo extends Component {
    render() {
        return (
            <div>
                <h1>Project Info Component</h1>
            </div>
        )
    }
}

React router 将这些组件包含到 Route 标签所在的指定部分。例如:

<section>
  <h1>Hello</h1>
  <Route path={"/random/path"} component={MyComponent} />
</section>

将return

<section>
  <h1>Hello</h1>
  <MyComponent />
</section>

要解决此问题,您需要将其添加到与 ProjectList 路由相同的路由级别。

所以改变这个

<main>
  <Route path={"/dashboard/projects/add"} component={NewProject} />
  <Route path={"/dashboard/projects/list"} component={ProjectsList} />
</main>

<main>
  <Route path={"/dashboard/projects/add"} component={NewProject} />
  <Route exact path={"/dashboard/projects/list"} component={ProjectsList} />
  <Route exact path={"/dashboard/projects/list/:id"} component={ProjectInfo} />
</main>

编辑

最后一条路线不应该有确切的标签

<main>
  <Route path={"/dashboard/projects/add"} component={NewProject} />
  <Route exact path={"/dashboard/projects/list"} component={ProjectsList} />
  <Route path={"/dashboard/projects/list/:id"} component={ProjectInfo} />
</main>

如果你想独占渲染一个组件,这意味着当你点击 table,在这种情况下你不想渲染 Projects 组件,你需要在路由器中使用 Switch

来自official docs

<Switch>

Renders the first child <Route> or <Redirect> that matches the location.

How is this different than just using a bunch of <Route>s?

<Switch> is unique in that it renders a route exclusively. In contrast, every <Route> that matches the location renders inclusively.

Consider this code:

<Route path="/about" component={About}/> 
<Route path="/:user" component={User}/>
<Route component={NoMatch}/>

If the URL is /about, then <About>, <User>, and <NoMatch> will all render because they all match the path. This is by design, allowing us to compose <Route>s into our apps in many ways, like sidebars and breadcrumbs, bootstrap tabs, etc.

因此,将您的 Projects 组件更改为如下内容(您已经在导入 Switch,因此无需再次导入):

<main>
  <Switch>
    <Route exact path={"/dashboard/projects/add"} component={NewProject} />
    <Route exact path={"/dashboard/projects/list"} component={ProjectsList} />
  </Switch>
</main>