admin管理员组

文章数量:1387354

I'm trying to use react router in the following code, and render the CourseDetail ponent on button click. However, nothing renders (just goes to the appropriate URL).

I don't want to put it in my App.js file with all my other routes, as I want to use the props in this specific parent ponent. Any help is appreciated!

Also edit: ${match.url} gives /student/courses

import {
  BrowserRouter,
  Route,
  Switch,
  withRouter,
  Link,
} from "react-router-dom";
import { Card, Button } from "react-bootstrap";
import "./style.css";
import CourseDetail from "./CourseDetail";

class CourseItem extends React.Component {
  render() {
    const { course, match } = this.props;
    return (
      <div>
        <Card style={{ width: "18rem" }}>
          <Card.Body>
            <Card.Title>
              {course.subject} {course.code}: {course.name}
            </Card.Title>
            <Button variant="primary">
              <Link to={`${match.url}/${course.subject}${course.code}`}>
                Access Course
              </Link>
            </Button>
          </Card.Body>
        </Card>
        <BrowserRouter>
          <Switch>
            <Route
              exact
              path="/student/courses/:course"
              render={(props) => <CourseDetail {...props} course={course} />}
            />
          </Switch>
        </BrowserRouter>
      </div>
    );
  }
}

export default withRouter(CourseItem);

Course Item is rendered by Course List:

import React from "react";
import { withRouter } from "react-router-dom";
import Header from "../../../ponents/Header";
import CourseItem from "./CourseItem";
import { CardDeck, Container } from "react-bootstrap";
import axios from "axios";

class CourseList extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      courses: [],
      isLoading: false,
      error: "",
    };
  }


  render() {
    const { courses } = this.state;
    return (
      <div className="course-list">
        <Header title="Courses & Labs" />
        <Container>
          <CardDeck>
            {courses &&
              courses.map((course) => {
                return <CourseItem course={course} />;
              })}
          </CardDeck>
        </Container>
      </div>
    );
  }
}

export default withRouter(CourseList);

App renders CourseList:

import React from "react";
import { BrowserRouter, Route, Switch } from "react-router-dom";
import data from "./data.json";
import Navigation from "./ponents/Navigation";
import Footer from "./ponents/Footer";
import Home from "./pages/Home";
import About from "./pages/About";
import Research from "./pages/Research";
import Publications from "./pages/Publications";
import HallOfFame from "./pages/HallOfFame";
import EvaluationList from "./pages/Student/TAEvaluations/EvaluationList";
import CourseList from "./pages/Student/Courses/CourseList";
import CourseDetail from "./pages/Student/Courses/CourseDetail";
import CourseEditorList from "./pages/Prof/CourseEditor/CourseEditorList";
import CourseEditorDetail from "./pages/Prof/CourseEditor/CourseEditorDetail";
import EvaluationEditorList from "./pages/Prof/EvaluationEditor/EvaluationEditorList";
import EvaluationEditorDetail from "./pages/Prof/EvaluationEditor/EvaluationEditorDetail";
import ReportList from "./pages/Prof/ReportEditor/ReportList";
import ReportDetail from "./pages/Prof/ReportEditor/ReportDetail";

class App extends React.Component {
  render() {
    const mockCourses = data.Courses;

    return (
      <div className="App">
        <BrowserRouter>
          <Navigation />
          <Switch>
            <Route exact path="/" ponent={Home} />
            <Route path="/about" ponent={About} />
            <Route path="/research" ponent={Research} />
            <Route path="/publications" ponent={Publications} />
            <Route path="/halloffame" ponent={HallOfFame} />
 
            <Route exact path="/student/courses" ponent={CourseList} />
          </Switch>
        </BrowserRouter>
        <Footer />
      </div>
    );
  }
}

export default App;

I'm trying to use react router in the following code, and render the CourseDetail ponent on button click. However, nothing renders (just goes to the appropriate URL).

I don't want to put it in my App.js file with all my other routes, as I want to use the props in this specific parent ponent. Any help is appreciated!

Also edit: ${match.url} gives /student/courses

import {
  BrowserRouter,
  Route,
  Switch,
  withRouter,
  Link,
} from "react-router-dom";
import { Card, Button } from "react-bootstrap";
import "./style.css";
import CourseDetail from "./CourseDetail";

class CourseItem extends React.Component {
  render() {
    const { course, match } = this.props;
    return (
      <div>
        <Card style={{ width: "18rem" }}>
          <Card.Body>
            <Card.Title>
              {course.subject} {course.code}: {course.name}
            </Card.Title>
            <Button variant="primary">
              <Link to={`${match.url}/${course.subject}${course.code}`}>
                Access Course
              </Link>
            </Button>
          </Card.Body>
        </Card>
        <BrowserRouter>
          <Switch>
            <Route
              exact
              path="/student/courses/:course"
              render={(props) => <CourseDetail {...props} course={course} />}
            />
          </Switch>
        </BrowserRouter>
      </div>
    );
  }
}

export default withRouter(CourseItem);

Course Item is rendered by Course List:

import React from "react";
import { withRouter } from "react-router-dom";
import Header from "../../../ponents/Header";
import CourseItem from "./CourseItem";
import { CardDeck, Container } from "react-bootstrap";
import axios from "axios";

class CourseList extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      courses: [],
      isLoading: false,
      error: "",
    };
  }


  render() {
    const { courses } = this.state;
    return (
      <div className="course-list">
        <Header title="Courses & Labs" />
        <Container>
          <CardDeck>
            {courses &&
              courses.map((course) => {
                return <CourseItem course={course} />;
              })}
          </CardDeck>
        </Container>
      </div>
    );
  }
}

export default withRouter(CourseList);

App renders CourseList:

import React from "react";
import { BrowserRouter, Route, Switch } from "react-router-dom";
import data from "./data.json";
import Navigation from "./ponents/Navigation";
import Footer from "./ponents/Footer";
import Home from "./pages/Home";
import About from "./pages/About";
import Research from "./pages/Research";
import Publications from "./pages/Publications";
import HallOfFame from "./pages/HallOfFame";
import EvaluationList from "./pages/Student/TAEvaluations/EvaluationList";
import CourseList from "./pages/Student/Courses/CourseList";
import CourseDetail from "./pages/Student/Courses/CourseDetail";
import CourseEditorList from "./pages/Prof/CourseEditor/CourseEditorList";
import CourseEditorDetail from "./pages/Prof/CourseEditor/CourseEditorDetail";
import EvaluationEditorList from "./pages/Prof/EvaluationEditor/EvaluationEditorList";
import EvaluationEditorDetail from "./pages/Prof/EvaluationEditor/EvaluationEditorDetail";
import ReportList from "./pages/Prof/ReportEditor/ReportList";
import ReportDetail from "./pages/Prof/ReportEditor/ReportDetail";

class App extends React.Component {
  render() {
    const mockCourses = data.Courses;

    return (
      <div className="App">
        <BrowserRouter>
          <Navigation />
          <Switch>
            <Route exact path="/" ponent={Home} />
            <Route path="/about" ponent={About} />
            <Route path="/research" ponent={Research} />
            <Route path="/publications" ponent={Publications} />
            <Route path="/halloffame" ponent={HallOfFame} />
 
            <Route exact path="/student/courses" ponent={CourseList} />
          </Switch>
        </BrowserRouter>
        <Footer />
      </div>
    );
  }
}

export default App;
Share Improve this question edited Jul 2, 2020 at 4:18 turkr asked Jul 2, 2020 at 3:47 turkrturkr 432 silver badges8 bronze badges 3
  • Can you share your main router, the one that is rendering this ponent, CourseItem, chances are CourseItem is on a different route than "/student/courses/:course" and thus won't match, ever. Your ment "${match.url} gives /student/courses" also implies/confirms this. – Drew Reese Commented Jul 2, 2020 at 4:09
  • Just did - let me know what you think! – turkr Commented Jul 2, 2020 at 4:19
  • Yes, precisely as I expected to see. <Route exact path="/student/courses" ponent={CourseList} /> means as soon as you push to a new route it no longer matches and thus doesn't render CourseList anymore which means the other route also isn't mounted and won't render anything. CourseDetail will receive course as a prop off the route's match params, if you can also update question with CourseDetail's code I can provide a good refactoring suggestion. – Drew Reese Commented Jul 2, 2020 at 4:59
Add a ment  | 

3 Answers 3

Reset to default 3

Issue

<Route exact path="/student/courses" ponent={CourseList} /> means as soon as you push to a new route it no longer matches and thus doesn't render CourseList anymore which means the route for "/student/courses/:course" also isn't mounted and won't render anything.

Solution

CourseDetail will receive course as a prop off the route's match params given the path definition "/student/courses/:course".

props.match.params.course

Go ahead and define its route in the main router. Remove the exact prop and define the more specific path before the less specific path as the Switch returns only the first match.

class App extends React.Component {
  render() {
    const mockCourses = data.Courses;

    return (
      <div className="App">
        <BrowserRouter>
          <Navigation />
          <Switch>
            <Route exact path="/" ponent={Home} />
            <Route path="/about" ponent={About} />
            <Route path="/research" ponent={Research} />
            <Route path="/publications" ponent={Publications} />
            <Route path="/halloffame" ponent={HallOfFame} />
 
            <Route
              path="/student/courses/:course"
              ponent={CourseDetail}
            />
    
            <Route path="/student/courses" ponent={CourseList} />
          </Switch>
        </BrowserRouter>
        <Footer />
      </div>
    );
  }
}

Remove the router from CourseItem, the main router can now handle that route/path.

class CourseItem extends React.Component {
  render() {
    const { course, match } = this.props;
    return (
      <div>
        <Card style={{ width: "18rem" }}>
          <Card.Body>
            <Card.Title>
              {course.subject} {course.code}: {course.name}
            </Card.Title>
            <Button variant="primary">
              <Link to={`${match.url}/${course.subject}${course.code}`}>
                Access Course
              </Link>
            </Button>
          </Card.Body>
        </Card>
      </div>
    );
  }
}

Refactor CourseDetail to pull the course from the match params versus props root. Implement the appropriate lifecycle functions to handle course prop value updating, for example, if user goes from "/student/courses/ABC" to "/student/courses/DEF" directly without first going to a different route/path.

class CourseDetail extends Component {

  ...

  ponentDidMount() {
    const {
      match: {
        params: {
          course,
        },
      },
    } = this.props;
    // use `course` to load the correct course content
    
    ...
  }

  ...

  ponentDidUpdate(prevProps) {
    const {
      match: {
        params: {
          course,
        },
      },
    } = this.props;

    const {
      match: {
        params: {
          course: prevCourse,
        },
      },
    } = prevProps;

    if (prevCourse !== course) {
      // use `course` to reload the correct course content
    }
    
    ...
  }
  
  ...
}

Note: if you can provide your CourseDetail ponent code I can provide a more accurate suggestion, the above is just a rough estimate.

in react-router-Dom 6, ponent is replaced by element, so instead of this:

 <Route path="/" ponent="App" />

use this:

<Route path="/" element={<App/>} />

What worked for me is:

  • I enclosed all my 'Route' ponents into one 'Routes' ponent. They are all imported from 'react-router-dom'

  • Also ensure you use the 'element' props to link to a ponent.

      import "./App.css";
      import { BrowserRouter, Route, Routes } from "react-router-dom";
      import Header from "./ponents/Header";
      import Homepage from "./pages/Homepage";
      import Coinpage from "./pages/Coinpage";
      import { makeStyles } from "@material-ui/core";    
      function App() {
      return (
      <BrowserRouter>
        <div>
          <Header />
          <Routes>
            <Route path="/" element={<Homepage/>} exact />
            <Route path="/coins/:id" element={<Coinpage/>} />
          </Routes>
        </div>
      </BrowserRouter>
    );
    }
    

本文标签: javascriptRoute not rendering componentStack Overflow