удаление строки на второй странице разбивки на страницы с помощью ReactJS выдает ошибку

#javascript #jquery #reactjs #pagination

#javascript #jquery #reactjs #разбивка на страницы

Вопрос:

 import React from 'react';
import { Link } from 'react-router-dom';
import { connect } from 'react-redux';
import { snapshotActions } from '../_actions';
import { organizationActions } from '../_actions';
import { businessunitActions } from '../_actions';
import { lineofbusinessActions } from '../_actions';
import { AlertDismissable } from '../_components';
import {ConfirmModal} from '../_components';
import { FormattedDate, FormattedRelative, FormattedNumber, FormattedMessage, intlShape, injectIntl, defineMessages} from 'react-intl';

const cellEditProp = {
  mode: 'click',
  blurToSave: true
};

class ListSnapshotsPage extends React.Component {

	constructor(props) {
        super(props);

        this.state = {
	      	row: [],
	      	sortName: undefined,
      		sortOrder: undefined,
      		isModalOpen: false
	    };

	    this.onRowSelect = this.onRowSelect.bind(this);
	    this.onSortChange = this.onSortChange.bind(this);
	    this.onAllSelect = this.onAllSelect.bind(this);
    	this.renderShowsTotal = this.renderShowsTotal.bind(this) ;
    	this.openModal = this.openModal.bind(this);
    	this.closeModal = this.closeModal.bind(this);
    	this.getNames = this.getNames.bind(this);
    }

	componentDidMount() {
		this.props.dispatch(snapshotActions.getAllSnapshots());
        this.props.dispatch(organizationActions.getAllOrganizations());
        this.props.dispatch(businessunitActions.getAllBusinessUnits());
        this.props.dispatch(lineofbusinessActions.getAllLinesOfBusiness());
		$(".alert-dismissable").hide();
    }


 	handleDeleteSnapshot(ids) {
		var names = [] ;
		for(var i = 0 ; i < this.state.row.length ; i   ) {
			names.push(this.state.row[i].name) ;
		}
		this.state.row = [];
		// this.props.dispatch(snapshotActions.deleteSnapshot(snapshots));
		this.props.dispatch(snapshotActions.deleteSnapshotByName(names));
		this.setState({ isModalOpen: false })
		//setTimeout(function(){ window.location.reload(); }, 3000);
		//setTimeout(function(){ snapShotDisplayData.push(snapData);	 }, 3000);
    }

	format(cell, row) {
		let name = ""  ;
		if(cell) {
			name = cell.name;
		}
    	return name ;
	}

	
	
	organizationValidator(value, row) {
		if(value == null) {
			return 'Organization Required!';
		} 
  		return true;
	}

	createCustomButtonGroup(props) {
		var role = this.props.user.role.name;
		if(role == 'superuser' || role == 'admin' || role == 'manager') {
 			return (
		    	<ButtonGroup className='my-custom-class' sizeClass='btn-group-md'>
			        	{ props.deleteBtn }
		    	</ButtonGroup>
			);
		}
	}

    createCustomSearchField(props) {
        <FormattedMessage id="listsnapshots.search_field" defaultMessage="Search... " description="Snapshot list search field placeholder"/>
        var searchFieldText = this.props.intl.formatMessage({id: "listsnapshots.search_field"});
 
        return (
          <SearchField
            placeholder={ searchFieldText }/>
        );
      }

    createCustomDeleteButton(){
        <FormattedMessage id="listsnapshots.list_button_delete" defaultMessage="Delete " description="Snapshot list button Delete"/>
        var deleteButtonText = this.props.intl.formatMessage({id: "listsnapshots.list_button_delete"});
 
            return (
                  <DeleteButton
                      btnText={deleteButtonText}
                    // btnContextual='btn-danger'
                      // className='btn btn-danger react-bs-table-del-btn '
                      // btnGlyphicon='fa glyphicon glyphicon-trash fa-trash'
                      // onClick={ this.customConfirm(onBtnClick) }
                  />
              );
       }
    
    openModal() {
        this.setState({ isModalOpen: true })
    }

    closeModal() {
        this.setState({ isModalOpen: false })
    }

    acceptDelete(next) {
        this.handleDeleteSnapshot(next) ;
    }

    getNames() {
        let snapshotNames = []  ;
        for(var i =0; i< this.state.row.length; i  ) {
            snapshotNames.push(this.state.row[i].name) ;
        }
        let sNames = snapshotNames.join(',') ;

        return ' ' sNames   '?';
    }
    
    customConfirm(next, dropRowKeys) {
        
        const fadeIn = this.state.open ? 'in' : '';
        const display = this.state.open ? 'block' : 'none';
        var selectStyle = {
            backgroundColor: "white"
        } ;

        this.setState({ isModalOpen: true }) ;
    }

	onRowSelect(row, isSelected, e) {
    	if(isSelected) {
    		this.state.row.push(row);
    	} else {
    		for(var i =0; i< this.state.row.length;) {
    			if(this.state.row[i].name == row.name) {
    				this.state.row.splice(i,1) ;
    				i = 0 ;
    			} else {
    				i  ;
    			}
    		}
    	}
	}

	onAllSelect(isSelected, rows, e) {
    	if(isSelected) {
    		this.state.row = rows;
    	} else {
    		this.state.row = [];
    	}
	}

	onSortChange(sortName, sortOrder) {
    	this.setState({
      		sortName,
      		sortOrder
    	});
  	}

  	remote(remoteObj) {
   		// Only cell editing, insert and delete row will be handled by remote store
    	remoteObj.cellEdit = true;
    	remoteObj.insertRow = true;
    	remoteObj.dropRow = true;
    	return remoteObj;
  	}

  	customSort(a, b, order, field) {
  		var fieldA = "" ;
  		var fieldB = "" ;
  		if(field == 'managers') {
			fieldA = a[field][0].firstName ;
  			fieldB = b[field][0].firstName ;
  		} else {
  			fieldA = a[field].name ;
  			fieldB = b[field].name ;
  		}
		if (order === 'desc') {
	    	if (fieldA > fieldB) {
	       		return -1;
	    	} else if (fieldA < fieldB) {
	      		return 1;
	    	}
	    	return 0;
	  	}
	 	 if (fieldA < fieldB) {
	    	return -1;
	  	} else if (fieldA > fieldB) {
	   		return 1;
	  	}
	  	return 0;
	}

	renderShowsTotal(start, to, total) {
	    <FormattedMessage id="listsnapshots.list_from" defaultMessage="From " description="Snapshot list from text"/>
        var fromText = this.props.intl.formatMessage({id: "listsnapshots.list_from"});

        <FormattedMessage id="listsnapshots.list_to" defaultMessage=" to " description="Snapshot list to text"/>
        var toText = this.props.intl.formatMessage({id: "listsnapshots.list_to"});

        <FormattedMessage id="listsnapshots.list_of" defaultMessage=" of " description="Snapshot list of text"/>
        var ofText = this.props.intl.formatMessage({id: "listsnapshots.list_of"});
    	return (
      		<div style={ { color: 'black', fontSize: 20 } }>
    	        {fromText} { start } {toText} { to }  {ofText} { total }
      		</div>
    	);
    }

    render() {
        const propTypes = {
            intl: intlShape.isRequired,
        };


    	const selectRowProp = {
			mode: 'checkbox',
			onSelect: this.onRowSelect,
			onSelectAll: this.onAllSelect,
			bgColor: 'lightsteelblue',
			clickToSelect: true  // enable click to select
		};

        const { user, users, snapshots, organizations, businessunits, linesofbusiness} = this.props;

        const snapshotData = snapshots.items ? snapshots.items : [] ;


		let options = {} ;
		if(snapshotData) {
	        options = {
				onDeleteRow: this.handleDeleteSnapshot.bind(this),  // A hook for after droping rows.
		  		btnGroup: this.createCustomButtonGroup.bind(this),
		  		handleConfirmDeleteRow: this.customConfirm.bind(this),
		  		sortName: this.state.sortName,
	      		sortOrder: this.state.sortOrder,
	      		onSortChange: this.onSortChange, 

	      		page: 1,  // which page you want to show as default
				sizePerPageList: [ {
				   	text: '5', value: 5
				}, {
				   	text: '10', value: 10
				}, {
				  	text: '25', value: 25
				}, {
				    text: 'All', value: snapshotData.length
				} ], // you can change the dropdown list for size per page
				sizePerPage: 10,  // which size per page you want to locate as default
				pageStartIndex: 1, // where to start counting the pages
				paginationSize: 5,  // the pagination bar size.
				prePage: 'Prev', // Previous page button text
				nextPage: 'Next', // Next page button text
				firstPage: 'First', // First page button text
				lastPage: 'Last', // Last page button text
				paginationShowsTotal: this.renderShowsTotal,
				deleteBtn: this.createCustomDeleteButton.bind(this),
                searchField: this.createCustomSearchField .bind(this),
			};
		}

		let organizationOptions = organizations.items amp;amp; organizations.items.map(organization => (
			{ name: organization.name, id: organization.id }
    	));

		var role = this.props.user.role.name;
    	var editable = (role == 'superuser' || role == 'admin') ;
    	var orgEdit = editable ? { type: 'select', validator: this.organizationValidator.bind(this) }: false ;
    	// var departmentEdit  = editable ? { validator: this.departmentValidator.bind(this) }: false ;

    	let defaultOrg = {} ;
        if(role != 'superuser') {
        	defaultOrg = { name: user.organization.name, id: user.organization.id } ;
        }

        let snapShotDisplayData = [] ;
        if(businessunits.items amp;amp; linesofbusiness.items) {
		    for(var i=0; i < snapshotData.length ; i  ) {
		    	let snap = snapshotData[i] ;

				let level =  snap.level;
		    	let levelId = snap.levelId
		    	let levelString =  'CallCenter' ;
		    	if( level == 2) {
		    		for(var buIdx = 0; buIdx < businessunits.items.length; buIdx  ) {
		    			let bu = businessunits.items[buIdx]  ;
		    			if(levelId = bu.id) {
		    				levelString =  'Business Unit ('   bu.name   ')' ;		
		    			}
		    		}
		    	} else if (level == 3) {
		    		for(var lobIdx = 0; lobIdx < linesofbusiness.items.length; lobIdx  ) {
		    			let lob = linesofbusiness.items[lobIdx]  ;
		    			if(levelId = lob.id) {
		    				levelString =  'Line Of Business ('   lob.businessunit.name   ' -> '   lob.name   ')' ;		
		    			}
		    		}
		    	}

		    	let snapData = {
	    			id 			: snap.id,
	    			name 		: snap.name,
	    			level       : levelString,
	    			callcenter 	: snap.callcenter.name,
	    			teams 		: snap.teams
				}
				snapShotDisplayData.push(snapData);	    		
	    	}
	    }
        
        <FormattedMessage id="listsnapshots.delete_title" defaultMessage="Delete Snapshot" description="Snapshot list delete Confirm Dialog"/>
        var deleteNameText = this.props.intl.formatMessage({id: "listsnapshots.delete_title"});

        <FormattedMessage id="listsnapshots.delete_message" defaultMessage="Are you sure you want to delete Snapshot - " description="Snapshot list delete message"/>
        var deleteText = this.props.intl.formatMessage({id: "listsnapshots.delete_message"});
        
        let confirmModal = <ConfirmModal 
            isOpen = { this.state.isModalOpen } 
            onOpen = {() => this.getNames() }
            onClose={() => this.setState({ isModalOpen: false }) }
            onAccept={() => this.acceptDelete() }
            validateState={ false }
            ignoreEditable={ false }
            nameText={ deleteNameText }
            deleteText={deleteText}
            dispatch={this.props.dispatch }/>

        return (
        	<div>
        		<div className="wrapper">
	        		<div className="content-wrapper">
                        {confirmModal}
	        			{snapshots.loading amp;amp; <div className="loader"></div>}
	        			{snapshots.error amp;amp; <AlertDismissable alertprops={{content:snapshots.error, bsStyle: "danger" }} />}
	        			{snapshots.success amp;amp; <AlertDismissable alertprops={{content:snapshots.success, bsStyle: "success" }} />}
	        			<section className="content-header">
							<h1>
	        			        <FormattedMessage id="listsnapshots.list_title" defaultMessage="Snapshots" description="Snapshots header greeting" />
							</h1>
							<ol className="breadcrumb">
								<li><i className="fa fa-dashboard"></i> <FormattedMessage id="listsnapshots.breadcrumb_home" defaultMessage="Home" description="Snapshot list breadcrumb Home" /></li>
								<li className="active"><FormattedMessage id="listsnapshots.breadcrumb_snapshot_configuration" defaultMessage="Snapshots" description="Snapshots breadcrumb" /></li>
							</ol>
						</section>	
	        		 	<section className="content">
		        		 	<BootstrapTable className="table" style={ {marginTop: '150px'} } remote={ this.remote } pagination={ true } search={ true }  multiColumnSearch={ true } cellEdit={ cellEditProp } data={snapShotDisplayData} insertRow={ true } deleteRow={ true } selectRow={ selectRowProp } options={ options } striped hover>
		        		 		<TableHeaderColumn isKey dataField='id' editable={ false } hidden = {true} hiddenOnInsert={ true } autoValue={ true } >
	        			            <FormattedMessage id="listsnapshots.list_id" defaultMessage="Id" description="snapshot list Id table header" />
	        			        </TableHeaderColumn>
		  						<TableHeaderColumn autoFocus dataSort editable={ false } dataField='name' editable={ false }>
	        			            <FormattedMessage id="listsnapshots.list_snapshot" defaultMessage="Snapshot Name" description="snapshot list name table header" />
        			            </TableHeaderColumn>
		  						<TableHeaderColumn autoFocus dataSort editable={ false } dataField='callcenter' editable={ false }>
	        			            <FormattedMessage id="listsnapshots.list_callcenter" defaultMessage="Call Center" description="snapshot list Call Center table header" />
        			            </TableHeaderColumn>
		  						<TableHeaderColumn autoFocus dataSort editable={ false } dataField='level' editable={ false }>
	        			            <FormattedMessage id="listsnapshots.list_level" defaultMessage="Level" description="snapshot list Level table header" />
        			            </TableHeaderColumn>
		  						{/*
		  						<TableHeaderColumn autoFocus dataSort editable={ false } dataField='teamName' editable={ false }>Team Name</TableHeaderColumn>
		  						*/}

							</BootstrapTable>
	           		 	</section>
		            </div>
		        	}
		        </div>
           	</div>
        );
        ListSnapshotsPage.propTypes = propTypes; 
    }
}


function mapStateToProps(state) {
    let returnObj = {}

	const { users, organizations, snapshots, authentication, businessunits, linesofbusiness} = state;
	const { user } = authentication;
    
    returnObj = { user, users, snapshots, organizations, businessunits, linesofbusiness }; 

  	return returnObj ;
}

const connectedListSnapshotsPage = connect(mapStateToProps)(injectIntl(ListSnapshotsPage));
export { connectedListSnapshotsPage as ListSnapshotsPage };  

я использую ReactJS с нумерацией страниц, здесь, если на второй странице есть только строка, когда я попытался удалить эту строку, она выдает ошибку, например

 > `Uncaught TypeError: Cannot read property 'id' of undefined`  at TableBody.eval (TableBody.js?975a:246)
  

Комментарии:

1. можете ли вы добавить фрагмент кода?

2. добавлено, проверьте один раз @Harish

3. Вы пытаетесь отобразить элемент, которого больше нет, это также произойдет, если у вас есть только один элемент на первой странице и удалите его. При удалении элементов проверьте, остались ли какие-либо элементы для этой страницы, если нет, вернитесь на одну страницу назад.