查看后,数据将从页面上消失

时间:2018-08-13 11:35:16

标签: reactjs react-redux

我有一个寄存器列表,当我想查看它们时,如果有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}`}>
              &nbsp;({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)
        })
    })
  }
}

1 个答案:

答案 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 })
      })
  }

我认为这会有所帮助。谢谢!