[英]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 上没有。
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.name
和this.props.match.params.id
都是空值。 Meanwhile, the props className
, name
, and no
which you set on the Course
are all unused.同时,您在
Course
上设置的道具className
、 name
和no
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 和编写可重用组件的基础知识。
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
对象中设置道具name
和no
。 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.