简体   繁体   English

反应:动态嵌套路由中的问题。 如何解决这个错误?

[英]React: Problem in dynamic nested routing. How to solve this error?

I am getting the following error while trying to implement dynamic routing in React JS.尝试在 React JS 中实现动态路由时出现以下错误。 在此处输入图片说明

The required files are:所需的文件是:

Assignment.js作业.js

import React, { Component } from 'react';
import Users from './containers/Users/Users';
import Courses from './containers/Courses/Courses';
import {Route, Link, Switch, Redirect} from 'react-router-dom';
import Course from './containers/Course/Course';

class Assignment extends Component{
    render(){
        return(
            <div>
                <ul>
                    <li><Link to ="/Users"> Users </Link></li>
                    <li><Link to ="/Courses"> Courses </Link></li>
                </ul>
             <Switch>
             <Route path ="/Users" component = {Users}/>
             <Route path ="/Courses" exact component = {Courses}/>  
             </Switch>
            </div>
        )
    }
};

export default Assignment;

Courses.js课程.js

import React, { Component } from 'react';
import {Link, Route} from 'react-router-dom';
import './Courses.css';
import Course from '../Course/Course';
class Courses extends Component {
    state = {
        courses: [
            { id: 1, title: 'Angular - The Complete Guide' },
            { id: 2, title: 'Vue - The Complete Guide' },
            { id: 3, title: 'PWA - The Complete Guide' }
        ]
    }

    render () {
        return (
            <div>
                <h1>Amazing Udemy Courses</h1>
                <section className="Courses">
                    {
                        this.state.courses.map( course => {
                            return (<Link key ={course.id} to = {this.props.match.url + '/' + course.id + '/' + course.title}>
                            <Course className = "Course" name = {course.title} no = {course.id} />
                            </Link>);
                        } )
                    }
                    <Route path = "/Courses/:id/:name" exact component = {Course} />
                </section>
            </div>
        );
    }
}

export default Courses;

Course.js课程.js

import React, { Component } from 'react';

class Course extends Component {
    render () {
        return (
            <div>
                <h1>{this.props.match.params.name}</h1>
                <p>{this.props.match.params.id}_</p>
            </div>
        );
    }
}

export default Course;

Why am I getting this error?为什么我收到这个错误? Can anyone fix this?任何人都可以解决这个问题吗? I am also finding it difficult to following dynamic routing.我也发现很难遵循动态路由。 PS.附注。 I am getting the error at /Courses url only not at the base url.我在 /Courses url 上收到错误,只是在基本 url 上没有。

Problems问题

The props such as params are only passed down to the top-level component which is rendered by a Route .诸如params类的道具只会向下传递到由Route呈现的顶级组件。 When you are rendering the list of individual Course components inside your Course component, the Courses gets this.props.params but each Course does not.当你渲染个人的名单Course的内部组件Course组成部分, Courses得到this.props.params但每Course不。 You can pass them down manually:您可以手动传递它们:

<Course {...this.props} className="Course" name={course.title} no={course.id} />

The above passes all props, while the below passes just the params prop.以上通过了所有道具,而下面只通过了 params 道具。

<Course params={this.props.params} className="Course" name={course.title} no={course.id} />

This resolves your error, but it is not at all doing what you want it to be doing.这解决了您的错误,但它根本没有做您希望它做的事情。 The match is for the current URL, so this.props.match.params.name and this.props.match.params.id are both empty values when we are on the /Courses page. match是针对当前URL 的,因此当我们在/Courses页面上时, this.props.match.params.namethis.props.match.params.id都是空值。 Meanwhile, the props className , name , and no which you set on the Course are all unused.同时,您在Course上设置的道具classNamenameno className使用。

Additionally, the Route to "/Courses/:id/:name" which you have put inside of Courses should really be on the top level of the app alongside the main "/Courses" Route .此外,该Route"/Courses/:id/:name"你已经把里面Courses确实应该对应用程序旁边的主要的顶层"/Courses" Route Ideally it should be listed before the courses homepage route because you want to match to more specific paths before broader ones, but it won't present any conflicts with exact either way.理想情况下,应在课程主页的路由之前,因为要匹配之前更加广泛的更具体的路径上市,但它不会出现任何冲突exact两种方式。

There is a lot wrong here and I recommend that you read up on the fundamentals of react-router and writing reusable components.这里有很多错误,我建议您阅读 react-router 和编写可重用组件的基础知识。

Rewrites重写

You are trying to use the same component to render a course for both your Route "/Courses/:id/:name" and as a list item on the Courses page, but one needs to have its data passed directly as props while the other gets its data from this.props.match.params .您正在尝试使用相同的组件为您的Route "/Courses/:id/:name"和作为Courses页面上的列表项呈现Courses ,但一个需要将其数据直接作为道具传递,而另一个从this.props.match.params获取它的数据。 In order to solve this, we will make a component that handles just the rendering of the course.为了解决这个问题,我们将制作一个只处理课程渲染的组件。 It gets its information from props, and is agnostic to where those props come from.它从 props 获取信息,并且不知道这些 props 的来源。 This means we can use this component on any page of your app as long as we pass it a name and no .这意味着我们可以在您应用程序的任何页面上使用此组件,只要我们传递给它一个name并且no . I used a function component, but it doesn't matter.我用了一个函数组件,不过没关系。

const CourseListItem = ({ name, no }) => {
  return (
    <div className="course">
      <h1>{name}</h1>
      <p>Course #{no}</p>
    </div>
  );
};

We can't send our Route directly to this component, because it wouldn't know the name and no .我们不能发送我们的Route直接到该组件,因为它不知道的name ,并no So we use an intermediate component that is responsible for setting the props of CourseListItem based on the router props ( this.props.match.params ).所以我们使用了一个中间组件,负责根据路由器道具( this.props.match.params )设置CourseListItem的道具。 You could of course render other HTML or components and not just CourseListItem .您当然可以呈现其他 HTML 或组件,而不仅仅是CourseListItem I used a class for consistency with what you had before, but again it doesn't matter.我使用了一个class来与您之前的内容保持一致,但这又无关紧要。

class SingleCoursePage extends Component {
  render() {
    return (
      <CourseListItem
        name={this.props.match.params.name}
        no={this.props.match.params.id}
      />
    );
  }
}

In our Courses component, we loop through the courses from this.state and for each course we render the CourseListItem , setting the props name and no from the course object.在我们的Courses组件中,我们从this.state循环遍历课程,并为每门课程渲染CourseListItem ,从course对象中设置道具nameno See how we can use same component in different ways?看看我们如何以不同的方式使用相同的组件? If you wanted, you could make className be a prop of CourseListItem so that you could style it differently in different places.如果你愿意,你可以让className成为CourseListItem的道具,这样你就可以在不同的地方设置不同的样式。

class Courses extends Component {
  state = {
    courses: [
      { id: 1, title: "Angular - The Complete Guide" },
      { id: 2, title: "Vue - The Complete Guide" },
      { id: 3, title: "PWA - The Complete Guide" }
    ]
  };

  render() {
    return (
      <div>
        <h1>Amazing Udemy Courses</h1>
        <section className="Courses">
          {this.state.courses.map((course) => {
            return (
              <Link
                key={course.id}
                to={"/Courses/" + course.id + "/" + course.title}
              >
                <CourseListItem name={course.title} no={course.id} />
              </Link>
            );
          })}
        </section>
      </div>
    );
  }
}

As I explained, we are moving that Route for the single course page up to the top-level component, alongside the other routes.正如我所解释的,我们正在该Route的单一课程页面到顶层组件外,其他航线并肩作战。

class Assignment extends Component {
  render() {
    return (
      <BrowserRouter>
        <div>
          <ul>
            <li><Link to="/Users">Users</Link></li>
            <li><Link to="/Courses">Courses</Link></li>
          </ul>
          <Switch>
            <Route path="/Users" component={Users} />
            <Route path="/Courses/:id/:name" component={SingleCoursePage} />
            <Route path="/Courses" exact component={Courses} />
          </Switch>
        </div>
      </BrowserRouter>
    );
  }
}

Code Sandbox Link - There's no CSS styling but all of the routing works! 代码沙盒链接- 没有 CSS 样式,但所有路由都有效!

Have you tried withRouter?你试过路由器吗?

import { withRouter } from 'react-router-dom';
console.log(props.match.params);

then export the component like:然后导出组件,如:

export default withRouter(TestComponent);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM