我有一个文章组件,显示帖子列表。该列表是分页的,因此每页最多可显示10个帖子。有一个"下一页"单击时按钮将更新组件状态和相应的url参数,如下所示:
第1页:/ news
第2页:/ news?page = 2
第3页:/ news?page = 3
......等等。设置constructor()
和render()
方法的方式是,如果用户直接导航到/ news?page = 3,它将读取此URL参数并显示正确的帖子。
我遇到的问题是浏览器后退和前进按钮似乎不会重新呈现页面。因此,如果用户点击"下一页"按钮几次,然后点击后退按钮,URL将更新,但页面不会重新呈现。有没有办法强迫它这样做?
我猜测通过添加window.history监听器来实现这一目标,但我不确定是否有建议的做法与gatsby-link
一起使用。
以下是该组件的精简版本供参考:
import React, { Component } from 'react';
import { navigateTo } from 'gatsby-link';
import getUrlParameter from '../functions/getUrlParameter';
export default class extends Component {
constructor(props) {
super(props);
/* external function, will grab value
* of ?page= url parameter if it exists */
const urlParamPage = getUrlParameter('page');
const currentPage = urlParamPage ? urlParamPage : 1;
this.state = {
currentPage
};
}
nextPage() {
const { props, state } = this;
const urlParam = state.currentPage > 1
? `?page=${state.currentPage}`
: '';
navigateTo(props.pathname + urlParam);
this.setState({currentPage: this.state.currentPage + 1});
}
render() {
const { props, state } = this;
const articles = props.articles
.slice(state.currentPage * 10, state.currentPage * 10 + 10);
return (
<div>
<ul>
{articles.map((article) => <li>{article.title}</li>)}
</ul>
<button onClick={() => this.nextPage()}>Next Page</button>
</div>
);
}
}
答案 0 :(得分:7)
您的页面不会重新呈现,因为它实际上是同一页面 - 该组件已经安装。在constructor()
中提取数据时,您的页面不会更新,因为React组件的构造函数在装入之前会被调用(source)。
你所谓的urlParam
只是componentWillReceiveProps(nextProps)
应该在nextProps.location.search
收到的新道具。
您必须解除状态,因为只有根组件会在浏览器后退和前进按钮上收到props.location
。您的文章组件神经的pathname
道具发生了变化,这就是为什么componentWillReceiveProps
永远不会在这里发生的。
import React, { Component } from 'react';
import { navigateTo } from 'gatsby-link';
import Articles from '../components/Articles';
export default class Test extends Component {
constructor(props) {
super(props);
this.state = {
currentPage: 1,
data: {}, // your ext data
};
this.nextPage = this.nextPage.bind(this);
}
nextPage() {
const { currentPage } = this.state;
const { pathname } = this.props.location;
const url = `${pathname}?page=${currentPage + 1}`;
this.setState({ currentPage: currentPage + 1 });
navigateTo(url);
}
componentWillReceiveProps(nextProps) {
const { pathname, search } = nextProps.location;
const getParam = /(\d+)(?!.*\d)/;
const currentPage = search !== '' ? Number(search.match(getParam)[0]) : 1;
/* get your ext. data here */
const data = {};
this.setState({ currentPage, data });
}
render() {
const { currentPage, data } = this.state;
return (
<div>
{/* other contents here */}
<Articles
nextPage={this.nextPage}
currentPage={currentPage}
data={data}
/>
</div>
);
}
}
import React from 'react';
const Articles = ({ nextPage, currentPage }) => {
return (
<div>
<div>Page: {currentPage}</div>
<button onClick={() => nextPage()}>Next Page</button>
</div>
);
};
export default Articles;
答案 1 :(得分:2)
这可以使用窗口对象中存在的历史对象来解决。
另一种方法是使用React-Router-DOM,它是ReactJS应用程序中路由的最新路由模块。因此,要参考V4路由器,请遵循此代码。
import {BrowserRouter as Router, Route, Switch, Redirect} from 'react-router-dom';
导入路由器后,只需尝试将根组件放在其中,然后就可以在其中创建路由。
<Router>
<div className="App" id="App">
<Route path="/" exact component={Home}/>
<Route path="/about" exact component={About}/>
<Route path="/misreports" exact component={MISReport}/>
<Route path="/contact" exact component={Contact}/>
</div>
</Router>
请记住,路由器应该只包含其他单个孩子,它不会按预期工作。通过这种方式,路由变得非常容易使用。