unl*_*.it 12 reactjs react-router
这真让我抓狂.当我尝试在嵌套路由中使用React Router的链接时,链接会在浏览器中更新,但视图不会更改.然而,如果我将页面刷新到链接,它确实如此.不知何故,组件不应该更新(或者至少是目标).
这是我的链接的样子(上一个/下一个项目真的是变量):
<Link to={'/portfolio/previous-item'}>
<button className="button button-xs">Previous</button>
</Link>
<Link to={'/portfolio/next-item'}>
<button className="button button-xs">Next</button>
</Link>
Run Code Online (Sandbox Code Playgroud)
一个hacky解决方案是manaully调用forceUpate(),如:
<Link onClick={this.forceUpdate} to={'/portfolio/next-item'}>
<button className="button button-xs">Next</button>
</Link>
Run Code Online (Sandbox Code Playgroud)
这工作,但导致整页刷新,我不想要和错误:
ReactComponent.js:85 Uncaught TypeError: Cannot read property 'enqueueForceUpdate' of undefined
Run Code Online (Sandbox Code Playgroud)
我已经搜索了高低的答案,我最接近的是:https://github.com/reactjs/react-router/issues/880.但它已经过时了,我没有使用纯渲染混合.
以下是我的相关路线:
<Route component={App}>
<Route path='/' component={Home}>
<Route path="/index:hashRoute" component={Home} />
</Route>
<Route path="/portfolio" component={PortfolioDetail} >
<Route path="/portfolio/:slug" component={PortfolioItemDetail} />
</Route>
<Route path="*" component={NoMatch} />
</Route>
Run Code Online (Sandbox Code Playgroud)
无论出于何种原因,调用Link不会导致组件重新安装哪些需要发生以获取新视图的内容.它确实调用componentDidUpdate,我确信我可以检查url slug更改然后在那里触发我的ajax调用/视图更新,但似乎不应该这样做.
编辑(更多相关代码):
PortfolioDetail.js
import React, {Component} from 'react';
import { browserHistory } from 'react-router'
import {connect} from 'react-redux';
import Loader from '../components/common/loader';
import PortfolioItemDetail from '../components/portfolio-detail/portfolioItemDetail';
import * as portfolioActions from '../actions/portfolio';
export default class PortfolioDetail extends Component {
static readyOnActions(dispatch, params) {
// this action fires when rendering on the server then again with each componentDidMount.
// but not firing with Link...
return Promise.all([
dispatch(portfolioActions.fetchPortfolioDetailIfNeeded(params.slug))
]);
}
componentDidMount() {
// react-router Link is not causing this event to fire
const {dispatch, params} = this.props;
PortfolioDetail.readyOnActions(dispatch, params);
}
componentWillUnmount() {
// react-router Link is not causing this event to fire
this.props.dispatch(portfolioActions.resetPortfolioDetail());
}
renderPortfolioItemDetail(browserHistory) {
const {DetailReadyState, item} = this.props.portfolio;
if (DetailReadyState === 'WORK_DETAIL_FETCHING') {
return <Loader />;
} else if (DetailReadyState === 'WORK_DETAIL_FETCHED') {
return <PortfolioItemDetail />; // used to have this as this.props.children when the route was nested
} else if (DetailReadyState === 'WORK_DETAIL_FETCH_FAILED') {
browserHistory.push('/not-found');
}
}
render() {
return (
<div id="interior-page">
{this.renderPortfolioItemDetail(browserHistory)}
</div>
);
}
}
function mapStateToProps(state) {
return {
portfolio: state.portfolio
};
}
function mapDispatchToProps(dispatch) {
return {
dispatch: dispatch
}
}
export default connect(mapStateToProps, mapDispatchToProps)(PortfolioDetail);
Run Code Online (Sandbox Code Playgroud)
PortfolioItemDetail.js
import React, {Component} from 'react';
import {connect} from 'react-redux';
import Gallery from './gallery';
export default class PortfolioItemDetail extends React.Component {
makeGallery(gallery) {
if (gallery) {
return gallery
.split('|')
.map((image, i) => {
return <li key={i}><img src={'/images/portfolio/' + image} alt="" /></li>
})
}
}
render() {
const { item } = this.props.portfolio;
return (
<div className="portfolio-detail container-fluid">
<Gallery
makeGallery={this.makeGallery.bind(this)}
item={item}
/>
</div>
);
}
}
function mapStateToProps(state) {
return {
portfolio: state.portfolio
};
}
export default connect(mapStateToProps)(PortfolioItemDetail);
Run Code Online (Sandbox Code Playgroud)
gallery.js
import React, { Component } from 'react';
import { Link } from 'react-router';
const Gallery = (props) => {
const {gallery, prev, next} = props.item;
const prevButton = prev ? <Link to={'/portfolio/' + prev}><button className="button button-xs">Previous</button></Link> : '';
const nextButton = next ? <Link to={'/portfolio/' + next}><button className="button button-xs">Next</button></Link> : '';
return (
<div>
<ul className="gallery">
{props.makeGallery(gallery)}
</ul>
<div className="next-prev-btns">
{prevButton}
{nextButton}
</div>
</div>
);
};
export default Gallery;
Run Code Online (Sandbox Code Playgroud)
新路线,基于Anoop的建议:
<Route component={App}>
<Route path='/' component={Home}>
<Route path="/index:hashRoute" component={Home} />
</Route>
<Route path="/portfolio/:slug" component={PortfolioDetail} />
<Route path="*" component={NoMatch} />
</Route>
Run Code Online (Sandbox Code Playgroud)
无法追根究底,但我能够使用 ComponentWillRecieveProps 实现我的目标:
componentWillReceiveProps(nextProps){
if (nextProps.params.slug !== this.props.params.slug) {
const {dispatch, params} = nextProps;
PortfolioDetail.readyOnActions(dispatch, params, true);
}
}
Run Code Online (Sandbox Code Playgroud)
换句话说,无论出于何种原因,当我使用 React Router Link 链接到具有相同父组件的页面时,它都不会触发 componentWillUnMount/componentWillMount。所以我必须手动触发我的操作。每当我链接到具有不同父组件的路由时,它都会按照我的预期工作。
也许这是设计好的,但看起来不正确而且不直观。我注意到 Stackoverflow 上有很多关于 Link 更改 url 但不更新页面的类似问题,所以我不是唯一的一个。如果有人对此有任何见解,我仍然很想听听!
| 归档时间: |
|
| 查看次数: |
5991 次 |
| 最近记录: |