我有一个寄存器列表,当我想查看它们时,如果有20多个寄存器,它们就会消失,然后我向下滚动页面并到达末尾,然后它们消失。在这种情况下,控制台中只会出现一个错误。
查看寄存器时浏览器控制台中显示的错误。
This usually means you called setState() on an unmounted component.
This is a no-op. Please check the code for the RegistersList component.
list.js
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux'
import { Link } from 'react-router';
import * as utils from '../../utils';
import moment from 'moment';
import { bindActionCreators } from 'redux'
import InfiniteScroll from 'react-infinite-scroller';
import { index as fetchRegisters } from '../../actions/registers';
var page = 0
@connect(
state => ({
currentFeatures: state.features,
registers: state.registers.items
}),
dispatch => ({
actions: bindActionCreators({
fetchRegisters
}, dispatch)
})
)
export default class RegistersList extends Component {
static propTypes = {
registers: PropTypes.array.isRequired,
articles: PropTypes.array.isRequired,
counterparties: PropTypes.array.isRequired,
handleDestroy: PropTypes.func.isRequired
};
constructor(props) {
super(props);
this.state = { hasMoreItems: true };
}
componentWillReceiveProps(newProps) {
const { props } = this
if (props.current !== newProps.current) {
this.setState({ hasMoreItems: true })
page = 0
}
}
componentWillMount() {
page = 0
}
fetchRegistersOnScroll() {
const { actions, current, dispatch } = this.props
page++
actions.fetchRegisters(current, page)
.then(res => {
dispatch({ type: 'REGISTER/SCROLL', payload: res.data });
if (res.data.items.length < 20)
this.setState({ hasMoreItems: false })
})
}
render() {
const { registers, articles, counterparties, handleDestroy, currentFeatures } = this.props;
const registersList = registers.map((register, i) => {
const article = articles.find(a => a.id === register.article_id) || {}
const typeName = article.type == "Cost" ? 'cost' : 'revenue';
const counterparty = counterparties.find(c => c.id === register.counterparty_id) || {}
const client = counterparties.find(c => c.id === register.client_id) || {}
const manager = counterparties.find(c => c.id === register.sales_manager_id) || {}
return(
<tr className="register-table" key={i}>
<td>{ moment(register.date).format("DD-MM-YYYY") }</td>
<td>
{article.title}
<span className={`register-title-label ${typeName}`}>
({typeName})
</span>
</td>
{ (currentFeatures && currentFeatures.sales) ?
<td>{ client.name }</td>
: null }
{ (currentFeatures && currentFeatures.sales) ?
<td>{ manager.name }</td>
: null }
<td>{counterparty ? counterparty.name : '-'}</td>
<td>{register.value}</td>
<td><div className="register-note">{register.note}</div></td>
<td>
<div className="btn-group btns-hidden" >
<Link
to={`/registers/${register.id}/edit`}
className="btn btn-primary btn-sm"
>
<i className="glyphicon glyphicon-pencil"></i>
</Link>
<button
className="btn btn-sm btn-danger"
onClick={handleDestroy.bind(this, register.id)}
>
<i class="fa fa-times" aria-hidden="true"></i>
</button>
</div>
</td>
</tr>
)
})
if (registers.length) {
return (
<InfiniteScroll
pageStart={0}
loadMore={this.fetchRegistersOnScroll.bind(this)}
hasMore={this.state.hasMoreItems}
loader={<tr className="loader" key={0}><td><b>Loading ...</b></td></tr>}
element={'tbody'}
>
{ registersList }
</InfiniteScroll>
)
}
return(
<tbody>
<tr>
<td rowSpan="6">
There are no registers...
</td>
</tr>
</tbody>
);
}
}
registers.js
import axios from 'axios';
import cookie from 'react-cookie';
const API_URL = `${window.location.origin}/api/v1/registers`;
export function index(params, page) {
return function(dispatch, getState) {
return new Promise((resolve, reject) => {
let headers = {}
headers['Authorization'] = `Bearer ${cookie.load('token')}`
headers['workspace-id'] = getState().workspaces.app.current.id
params.page = page
axios.get(API_URL, { params, headers })
.then(res => {
dispatch({ type: 'REGISTER/FETCH', payload: res.data });
resolve(res)
})
.catch(e => {
console.error("error: ", e);
reject(e)
})
})
}
}
export function show(id){
return function(dispatch, getState) {
return new Promise((resolve, reject) => {
let headers = {}
headers['Authorization'] = `Bearer ${cookie.load('token')}`
headers['workspace-id'] = getState().workspaces.app.current.id
axios.get(`${API_URL}/${id}`, { headers: headers })
.then(res => {
dispatch({ type: 'REGISTER/SHOW', payload: res.data });
resolve(res)
})
.catch(e => {
console.error("error: ", e);
reject(e)
})
})
}
}
export function create(register){
return function(dispatch, getState) {
return new Promise((resolve, reject) => {
let headers = {}
headers['Authorization'] = `Bearer ${cookie.load('token')}`
headers['workspace-id'] = getState().workspaces.app.current.id
let body = {register: register}
axios.post(API_URL, body, { headers: headers })
.then(res => {
dispatch({ type: 'REGISTER/CREATE', payload: res.data });
resolve(res)
})
.catch(e => {
console.error(e);
reject(e)
})
})
}
}
export function update(register){
return function(dispatch, getState) {
return new Promise((resolve, reject) => {
let headers = {}
headers['Authorization'] = `Bearer ${cookie.load('token')}`
headers['workspace-id'] = getState().workspaces.app.current.id
let body = {register: register.register}
axios.patch(`${API_URL}/${register.id}`, body, { headers: headers })
.then(res => {
resolve(res)
})
.catch(e => {
console.error("error: ", e);
reject(e)
})
})
}
}
export function destroy(id){
return function(dispatch, getState) {
return new Promise((resolve, reject) => {
let headers = {}
headers['Authorization'] = `Bearer ${cookie.load('token')}`
headers['workspace-id'] = getState().workspaces.app.current.id
axios.delete(`${API_URL}/${id}`, { headers: headers })
.then(res => {
dispatch({ type: 'REGISTER/DELETE', payload: id });
resolve(res)
})
.catch(id => {
console.error("error", id);
reject(id)
})
})
}
}
答案 0 :(得分:1)
在您发表评论之后,您已经解决了数据从页面消失的问题,但是现在您可以通过修改fetchRegisterOnScroll函数来解决数据重复问题。由于InfiniteScroll可能会反复调用loadMore函数,因此我们需要检查是否正在调用它。
下面的代码段可能会有所帮助。
fetchRegistersOnScroll() {
if (this.state.isFetching) return; // checking request has already been called or not.
const { actions, current, dispatch } = this.props
this.setState({ isFetching: true });
actions.fetchRegisters(current, page)
.then(res => {
dispatch({ type: 'REGISTER/SCROLL', payload: res.data });
if (res.data.items.length < 20)
this.setState({ hasMoreItems: false, isFetching: false })
else this.setState({ isFetching: true })
})
}
我认为这会有所帮助。谢谢!