我正在使用ReactRouter 4。
我有以下基础路由器
<Router>
<Route exact path="/" component={HomePage} />
<Route
path="/courses/:courseName"
render={(props) => {
switch (props.match.params) {
case '1':
return React.createElement(
fetch('courses/1/')(CoursePage),
props,
null
);
case '2':
return React.createElement(
fetch('courses/2/')(CoursePage),
props,
null
);
default:
return <FourOFour />
}
}}
/>
</Router>
fetch('courses/NUMBER/')(CoursePage)
所做的是,它将CoursePage
组件包装在HOC中,该HOC使得API请求获取与特定课程相关的数据,并且当它获得成功响应时{{1}使用作为props传递的数据呈现组件。同时显示加载屏幕。
现在,在CoursePage
内,其内容的布局方式取决于用户是登录还是退出。
如果用户已注销,CoursePage
组件将在LoggedOut
的{{1}}方法内呈现,并且他们会看到一个页面,其中所有内容都会在页面中连续放置。< / p>
如果用户已登录,则CoursePage
组件会在render()
的{{1}}方法内呈现,并且他们会看到与上面相同的内容,但现在它已被分解为选项卡式部分,意味着用户无法再通过一次滚动查看页面的整个内容,他们必须选择相应的选项卡才能查看相关内容。
因此,例如,如果我已注销,并点击课程1的页面,我会转到LoggedIn
,并依次查看包含3个部分(概述,内容,评论)的页面。
如果我已登录并点击课程1的页面,我会转到CoursePage
并看到包含3个标签的页面(概述,内容,评论),然后点击每个标签应显示相关内容。< / p>
现在,我得到了以下要求:
当用户登录时,每个部分都应该在选择时反映URL。因此,如果我在登录时点击“内容”标签,则网址应为render()
。
我决定使用ReactRouter实现此功能,因此,在www.page.com/courses/1
组件的www.page.com/courses/1
方法中,我创建了标签www.page.com/courses/1/contents
元素,并放置了以下代码:
LoggedIn
render()
只需将NavLink
传递给相应的组件即可根据<Router>
<section>
<Route
exact
path="/courses/:courseName"
render={(props) => {
return this.determineVisibleSection('overview', data);
}}
/>
<Route
path="/courses/:courseName/:section"
render={(props) => {
return this.determineVisibleSection(props.match.params.section, data);
}}
/>
</section>
</Router>
进行渲染并返回。
问题在于,当单击某个部分时,整个页面会再次加载。
我的意思是,this.determineVisibleSection(sectionName, data)
再次被触发,我们在等待数据返回时获得加载屏幕,最后页面显示我们单击的部分现在被选中以及下面的正确内容。
我想我明白为什么会这样。由于URL已更改,所有data
组件都会收到更改通知,因此sectionName
组件也会收到通知,因此,在基础fetch('courses/NUMBER/')(CoursePage)
中,要呈现的组件每次都基本上是新的,甚至如果我们在同一页面上,由于Router
返回了一个新页面,页面将被“重新加载”。
有没有办法阻止这种行为?意思是,所选部分没有对URL进行更改会影响整个页面。它只会影响当前的课程页面内容。
我提出的一种方法似乎有效:
我像这样重写了我的基地Route
Router
和fetch()()
就是这个
Router
整个事情的关键是<Router>
<Page>
<Route exact path="/" component={HomePage} />
<Route path="/courses/:courseName" component={CoursePages} />
</Page>
</Router>
以及我在CoursePages
组件中有第二个class CoursePages extends React.Component {
shouldComponentUpdate(nextProps, nextState) {
return this.props.match.url !== nextProps.match.url;
}
render() {
switch (this.props.match.url) {
case '/courses/1':
return React.createElement(fetch('courses/1/')(CoursePage), this.props, null);
case '/courses/2':
return React.createElement(fetch('courses/2/')(CoursePage), this.props, null);
default:
return <FourOFour />;
}
}
}
的事实,因为第二个shouldComponentUpdate
会强制其内容即使父组件没有重新渲染(因为<Router />
)
有没有更好的方法可以解决这个问题?
答案 0 :(得分:0)
我认为将部分路径放在LoggedIn
组件中更好。因为它更像是react-router v4方式来处理这种情况(参见文档中的this basic example)。
首先,将基本路由器保持在第一个代码块中。根据给定的解释,我假设您的CoursePage组件或多或少是这样的。
class CoursePage extends Component{
//...
render(){
return this.props.IsLoggedIn ? <LoggedIn/> : <LoggedOut/>
}
}
现在将Routes放在LoggedIn组件中以用于不同的部分,如下所示。
import React, { Component } from 'react';
import {
Switch
Route,
Redirect
} from 'react-router-dom'
class LoggedIn extends Component{
// ...
render(){
const { match } = this.props;
return (
<Switch>
{/* This will redirect /courses/:courseName to /courses/:courseName/overview */}
<Redirect exact from={`${match.url}/`} to={`${match.url}/overview`}/>
<Route path={`${match.url}/overview`} component={Overview}/>
<Route path={`${match.url}/contents`} component={Contents}/>
<Route path={`${match.url}/reviews`} component={Reviews}/>
</Switch>
);
}
}
可能您需要向此渲染方法添加更多组件或HTML标记,以使其看起来像带标题的标签。
由于在CoursePage渲染后渲染剖面路径,因此当您导航到同一课程中的不同剖面时,它不会再次获取数据。