I'm trying to create a simple poll app, where you can make new polls.
我正在尝试创建一个简单的投票应用程序,在那里你可以进行新的投票。
In the section 'MyPolls', I want it to render only the first 5 polls that I've made instead of rendering the entire list of polls.
在“我的民意调查”一节中,我希望它只显示我所做的前5个民意调查,而不是显示所有的民意调查。
At the bottom is a 'Load More' button, where upon clicking, loads another 5 polls and so on.
底部是一个“Load More”按钮,点击后会加载另外5个轮询等等。
I've been using Mongoose/MongoDB backend and my approach has been to use skip
and limit
.
我一直在使用Mongoose/MongoDB后端,我的方法是使用skip和limit。
I've managed to implement this feature, but the problem is the entire component re-renders, which is annoying for a user as you have to scroll down again the click the 'Load More' button.
我已经实现了这个特性,但问题是整个组件重新呈现,这对用户来说很烦人,因为您必须再次向下滚动“加载更多”按钮。
Here is my app: https://voting-app-drhectapus.herokuapp.com/
这是我的应用:https://voting-app-drhectapus.herokuapp.com/
(use can you these login details for convenience: username: riverfish@gmail.com
password: 123
)
(用户名:riverfish@gmail.com密码:123)
And then goto the My Polls
page.
然后到我的民意调查页面。
MyPoll.js:
MyPoll.js:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import * as actions from '../../actions';
class MyPolls extends Component {
constructor(props) {
super(props);
this.state = {
skip: 0
};
}
componentDidMount() {
this.props.fetchMyPolls(this.state.skip);
this.setState({ skip: this.state.skip + 5 });
}
sumVotes(polls) {
return polls.reduce((a, b) => {
return a.votes + b.votes;
});
}
loadMore(skip) {
this.props.fetchMyPolls(skip);
const nextSkip = this.state.skip + 5;
this.setState({ skip: nextSkip });
}
renderPolls() {
return this.props.polls.map(poll => {
return (
<div className='card' key={poll._id}>
<div className='card-content'>
<span className='card-title'>{poll.title}</span>
<p>Votes: {this.sumVotes(poll.options)}</p>
</div>
</div>
)
})
}
render() {
console.log('polls', this.props.polls);
console.log('skip:', this.state.skip);
return (
<div>
<h2>My Polls</h2>
{this.renderPolls()}
<a href='#' onClick={() => this.loadMore(this.state.skip)}>Load More</a>
</div>
);
}
}
function mapStateToProps({ polls }) {
return { polls }
}
export default connect(mapStateToProps, actions)(MyPolls);
Action creator:
行动的创造者:
export const fetchMyPolls = (skip) => async dispatch => {
const res = await axios.get(`/api/mypolls/${skip}`);
dispatch({ type: FETCH_MY_POLLS, payload: res.data });
}
Poll route:
调查路线:
app.get('/api/mypolls/:skip', requireLogin, (req, res) => {
console.log(req.params.skip);
Poll.find({ _user: req.user.id })
.sort({ dateCreated: -1 })
.skip(parseInt(req.params.skip))
.limit(5)
.then(polls => {
res.send(polls);
});
});
Entire github repo: https://github.com/drhectapus/voting-app
整个github回购:https://github.com/drhectapus/voting-app
I understand that might method of implementing this feature might be the best possible solution so I'm open to any suggestions.
我知道实现这个特性的方法可能是最好的解决方案,所以我愿意接受任何建议。
1 个解决方案
#1
2
It looks like the re-render is triggered by the fact that clicking the "Load More" link actually causes react router to navigate to a new route, causing the entire MyPolls
component to re-render.
看起来重新呈现是由点击“Load More”链接而触发的,这实际上会导致react router导航到一个新路径,从而导致整个MyPolls组件重新呈现。
Just replace the <a href='#' onClick={...}>
with <button onClick={...}>
.
If you don't want to use a button
, you could also change the onClick
function to
如果您不想使用按钮,也可以将onClick函数更改为
const onLoadMoreClick = e => {
e.preventDefault(); // this prevents the navigation normally occuring with an <a> element
this.loadMore(this.state.skip);
}
#1
2
It looks like the re-render is triggered by the fact that clicking the "Load More" link actually causes react router to navigate to a new route, causing the entire MyPolls
component to re-render.
看起来重新呈现是由点击“Load More”链接而触发的,这实际上会导致react router导航到一个新路径,从而导致整个MyPolls组件重新呈现。
Just replace the <a href='#' onClick={...}>
with <button onClick={...}>
.
If you don't want to use a button
, you could also change the onClick
function to
如果您不想使用按钮,也可以将onClick函数更改为
const onLoadMoreClick = e => {
e.preventDefault(); // this prevents the navigation normally occuring with an <a> element
this.loadMore(this.state.skip);
}