React DevExpress Grid触发onCurrentPageChange两次

时间:2018-06-18 20:08:56

标签: reactjs react-redux devexpress

我对改变devexpress网格页面的行为感到困惑。我失去了一天寻找我的错误,但我找不到。

我的环境

  • " @ devexpress / dx-core":" ^ 1.3.0"
  • " @ devexpress / dx-grid-core":" ^ 1.3.0"
  • " @ devexpress / dx-react-core":" ^ 1.3.0"
  • " @ devexpress / dx-react-grid":" ^ 1.3.0"
  • " @devexpress / dx-react-grid-bootstrap3":" ^ 1.3.0"
  • " appcache-webpack-plugin":" ^ 1.4.0"
  • " bootstrap":" 3.3.7"
  • "反应":" ^ 16.4.0"
  • " react-bootstrap":" ^ 0.32.1"
  • " react-dom":" ^ 16.4.0"
  • " react-redux":" ^ 5.0.7"
  • " react-router":" 3.0.5"
  • " react-router-redux":" 4.0.8"
  • " redux":" ^ 3.7.2"
  • " redux-thunk":" 2.2.0"

我已经创建了一个通用组件,可以在我的系统中有网格的所有页面上使用。

MyComponent的

import * as React from 'react';
import * as DxGrid from '@devexpress/dx-react-grid';
import * as DxGridBootstrap from '@devexpress/dx-react-grid-bootstrap3';
import * as MaterialUI from 'material-ui';
import PropTypes from 'prop-types';
import Moment from '../../utils/Moment'

const DateFormatter = ({ value }) => <Moment date={value} 
format="DD/MM/YYYY" />;
const CurrencyFormatter = ({ value }) => {
  var formatter = new Intl.NumberFormat('pt-BR', {
    style: 'decimal',
    minimumFractionDigits: 2,
    maximumFractionDigits: 2
  });

  return formatter.format(value);
};

const DateTypeProvider = props => (
  <DxGrid.DataTypeProvider
    formatterComponent={DateFormatter}
    {...props}
  />
);

const CurrencyTypeProvider = props => (
  <DxGrid.DataTypeProvider
    formatterComponent={CurrencyFormatter}
    {...props}
  />
);

export default class GridMotor extends React.Component {
  render() {
    const {
     rows, columns, totalRows, filterControls, filter, sort, 
     sortControls, groupControl, columnReorder,
     selection, selectionAll, chooser, paging, pageSizes, 
     defaultPageSize, currentPage, resizing, 
     defaultColumnWidths, search, dateColumns, currencyColumns, 
     iconColumns, iconFormatter, 
     tableColumnExtensions
  } = this.props;

  return [
    (rows.length > 0) && 
    <DxGridBootstrap.Grid 
      rows={rows}
      columns={columns}>

      {dateColumns && <DateTypeProvider for={dateColumns} />}
      {currencyColumns && <CurrencyTypeProvider for={currencyColumns} />}         
      {iconColumns && <DxGrid.DataTypeProvider for={iconColumns} 
        formatterComponent={iconFormatter} />}

      {search && <DxGrid.SearchState />}

      {filter && <DxGrid.FilteringState />}
      {filter && <DxGrid.IntegratedFiltering />}

      {sort && <DxGrid.SortingState />}
      {sort && <DxGrid.IntegratedSorting />}

      {selection && <DxGrid.SelectionState />}
      {selection && <DxGrid.IntegratedSelection />}

      {paging && <DxGrid.PagingState 
        currentPage={currentPage}
        onCurrentPageChange={this.props.changePage}
        pageSize={defaultPageSize} 
        onPageSizeChange={this.props.changePageSize}  />}

      {paging && <DxGrid.IntegratedPaging />}

      {groupControl && <DxGrid.GroupingState />}                
      {groupControl && <DxGrid.IntegratedGrouping />}

      {paging && <DxGrid.CustomPaging totalCount={totalRows} />}

      {tableColumnExtensions && <DxGridBootstrap.Table columnExtensions= 
      {tableColumnExtensions} />}
      {!tableColumnExtensions && <DxGridBootstrap.Table />}

      {columnReorder && <DxGridBootstrap.TableColumnReordering 
        defaultOrder={columns.map(column => column.name)} />}
      <DxGridBootstrap.DragDropProvider />

      {resizing && <DxGridBootstrap.TableColumnResizing 
        defaultColumnWidths={defaultColumnWidths}/>}

      {!sort && !sortControls && <DxGridBootstrap.TableHeaderRow />}
      {sort && sortControls && <DxGridBootstrap.TableHeaderRow 
        showSortingControls />}

      {filter && filterControls && <DxGridBootstrap.TableFilterRow 
        showFilterSelector />}
      {filter && !filterControls && <DxGridBootstrap.TableFilterRow />}

      {selection && selectionAll && <DxGridBootstrap.TableSelection 
        showSelectAll />}
      {selection && !selectionAll && <DxGridBootstrap.TableSelection />}

      {groupControl && <DxGridBootstrap.TableGroupRow />}
      {groupControl && <DxGridBootstrap.Toolbar />}

      {groupControl && sort && sortControls && 
      <DxGridBootstrap.GroupingPanel showSortingControls />}
      {groupControl && !sortControls && <DxGridBootstrap.GroupingPanel/>}

      {chooser && <DxGridBootstrap.TableColumnVisibility />}
      {chooser && <DxGridBootstrap.ColumnChooser />}

      {search && <DxGridBootstrap.SearchPanel />}

      {paging && <DxGridBootstrap.PagingPanel pageSizes={pageSizes}/>}
    </DxGridBootstrap.Grid>
  ]
  }
}

GridMotor.propTypes = {
 filter: PropTypes.bool,
 filterControls: PropTypes.bool,
 sort: PropTypes.bool,
 sortingControls: PropTypes.bool,
 groupControl: PropTypes.bool,
 selection: PropTypes.bool,
 selectionAll: PropTypes.bool,
 chooser: PropTypes.bool,
 paging: PropTypes.bool,
 pageSizes: PropTypes.array,
 resizing: PropTypes.bool,
 columnWidths: PropTypes.array,
 search: PropTypes.bool,
 dateColumns: PropTypes.array,
 currencyColumns: PropTypes.array,
 iconColumns: PropTypes.array,
 tableColumnExtensions: PropTypes.array,
 defaultPageSize: PropTypes.number,
 changePage: PropTypes.func,
 currentPage: PropTypes.number,
 changePageSize: PropTypes.func,
}

当我点击&#34;按钮&#34;和#34; Grid.PagingState&#34;的onPageSizeChange;数据获取成功,devexpress网格也已成功渲染数据。

错误发生在&#34; Grid.PagingState&#34;的onCurrentPageChange上,使用正确的currentPage值触发props传递的函数,但是一旦更新了props,网格组件再次触发我的页面自定义函数使用默认currentPage(0)更改为重置状态,但我无法理解为什么会这样。

我确实尝试通过redux删除抓取数据。

我遵循这种模式(https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html)。

提前感谢您的帮助 威廉

MyPage - 使用我的网格组件

import React from 'react'
import GridMotor from "../../../components/grid/devexpress/GridMotor";
import { smallError, smallInfo, SmartMessageBox } from "../../../components/utils/actions/MessageActions";
import UiDatepicker from '../../../components/forms/inputs/UiDatepicker';
import { Stats, BigBreadcrumbs, WidgetGrid, JarvisWidget } from '../../../components';
import { defaultDate, formatDate } from "../../../components/utils/DateFormat";
import { Loading } from '../../../components/utils/Loading';
import { service } from "../../../config/service";
import { fetchData, fetchGridBegin } from "../../../components/grid/actions/GridMotorActions";
import { connect } from 'react-redux';

const IconFormatter = ({column, row}) => {
var descriptor = Object.getOwnPropertyDescriptor(row, column.name);
if (descriptor.configurable &&  descriptor.value === "Completed")
return <i className="fa fa-check-circle"></i>;
else if (descriptor.configurable &&  descriptor.value === "Uncompleted")
return <i className="fa fa-times-circle"></i>;
else if (descriptor.configurable &&  descriptor.value === "Exception")
return <i className="fa fa-exclamation-triangle"></i>;
else
return <i className="fa fa-clock-o"></i>;
};

class Pagamentos extends React.Component {
constructor(props) {
super(props);
this.state = {
defaultPageSize: 10,
columns: [
{name: 'ContractNumber', title: 'Contrato'},
{name: 'ContractType', title: 'Tipo'},
{name: 'ContractDate', title: 'Data do Contrato'},
{name: 'ForeignSettlementDate', title: 'Liquidação'},
{name: 'Currency', title: 'Moeda'},
{name: 'ExternalEntity', title: 'Pagador/Recebedor'},
{name: 'Customer', title: 'Cliente'},
{name: 'ForeignSettlementMethod', title: 'Método'},
{name: 'AccountNumber', title: 'Conta'},
{name: 'LocalAmount', title: 'Valor MN'},
{name: 'ForeignAmount', title: 'Valor ME'},
{name: 'FlagCriticalPendency', title: 'Pendência Crítica'},
{name: 'FlagExternalEntity', title: 'Cadastro Pagador/Recebedor'},                
{name: 'FlagEndorsement', title: 'Abono'},
{name: 'FlagTax', title: 'Impostos'},
{name: 'FlagBcSettlement', title: 'Liquidação BC'},
{name: 'FlagBalance', title: 'Saldo CC'},                
{name: 'FlagCash', title: 'Saldo Caixa'},
],
columnWidths:[
{columnName: 'ContractNumber', width: 90}, 
{columnName: 'ContractType', width: 80},
{columnName: 'ContractDate', width: 110},
{columnName: 'ForeignSettlementDate', width: 110},
{columnName: 'Currency', width: 70},
{columnName: 'ExternalEntity', width: 200},
{columnName: 'Customer', width: 200},
{columnName: 'ForeignSettlementMethod', width: 70},
{columnName: 'AccountNumber', width: 100},
{columnName: 'LocalAmount', width: 100},
{columnName: 'ForeignAmount', width: 100},
{columnName: 'FlagCriticalPendency', width: 100},
{columnName: 'FlagExternalEntity', width: 100},
{columnName: 'FlagEndorsement', width: 100},
{columnName: 'FlagTax', width: 100},
{columnName: 'FlagBcSettlement', width: 100},
{columnName: 'FlagBalance', width: 100},
{columnName: 'FlagCash', width: 100}
],
dateColumns: ['ContractDate', 'ForeignSettlementDate'],
currencyColumns: ['LocalAmount', 'ForeignAmount'],
iconColumns: ['FlagCriticalPendency','FlagExternalEntity','FlagEndorsement','FlagTax','FlagBcSettlement','FlagBalance', 'FlagCash'],
tableColumnExtensions: [
{columnName: 'LocalAmount', align: 'right'},
{columnName: 'ForeignAmount', align: 'right'},
{columnName: 'FlagCriticalPendency', align: 'center'},
{columnName: 'FlagExternalEntity', align: 'center'},
{columnName: 'FlagEndorsement', align: 'center'},
{columnName: 'FlagTax', align: 'center'},
{columnName: 'FlagBcSettlement', align: 'center'},
{columnName: 'FlagBalance', align: 'center'},
{columnName: 'FlagCash', align: 'center'}
]
};
}

handleSearchClick() {
const { defaultPageSize } = this.state;
var startRange = formatDate(this.dtpStartRange.refs.input.value);
var endRange = formatDate(this.dtpEndRange.refs.input.value);
let uri = `${service.Exchange.PaymentOrders}?startRange=${startRange}&endRange=${endRange}&search=&pageSize=${defaultPageSize}&page=0`
this.props.dispatch(fetchData(uri, "GET"));
//this.fetchData(uri, "GET")
}

changeCurrentPage(currentPage) {   
const { defaultPageSize } = this.state;
var startRange = formatDate(this.dtpStartRange.refs.input.value);
var endRange = formatDate(this.dtpEndRange.refs.input.value);
let uri = `${service.Exchange.PaymentOrders}?startRange=${startRange}&endRange=${endRange}&search=&pageSize=${defaultPageSize}&page=${currentPage}`
this.props.dispatch(fetchData(uri, "GET"));         
//this.fetchData(uri, "GET")
}

changePageSize(pageSize) {
this.setState({
defaultPageSize: pageSize
});
const { currentPage } = this.props;
var startRange = formatDate(this.dtpStartRange.refs.input.value);
var endRange = formatDate(this.dtpEndRange.refs.input.value);
let uri = `${service.Exchange.PaymentOrders}?startRange=${startRange}&endRange=${endRange}&search=&pageSize=${pageSize}&page=${currentPage}`
//this.fetchData(uri, "GET")
}

render() {
const { columns, columnWidths, dateColumns, currencyColumns, iconColumns, 
tableColumnExtensions, defaultPageSize } = this.state;
const { loading, rows, totalRows, error, currentPage } = this.props.grid;

return(
<div id="content">
<WidgetGrid>
<div className="row marginTop15">
<article className="col-sm-12">
<JarvisWidget colorbutton={false} editbutton={false} fullscreenbutton={false} 
deletebutton={false} color={"blue"}>
<header>
<span className="widget-icon"> 
<i className="fa fa-search" /> 
</span>
<h2>Módulo de Pagamento - Consulta</h2>
</header>
<div className="widget-body">
<form>
<fieldset>
<div className="form-group">
<div className="row">
<div className="col-sm-3">
<label>Período:</label>
</div>                                                        
</div>
</div>
</fieldset>
<fieldset>
<div className="form-group">
<div className="col-sm-3">
<div className="input-group">
<UiDatepicker className="form-control" id="from"
minRestrict="#to"                                                                            
defaultDate="+1w"
placeholder="Data Inicial"
dateFormat="dd/mm/yy"
ref={(uidatepicker) => { this.dtpStartRange = uidatepicker; }}/>
<span className="input-group-addon">
<i className="fa fa-calendar"/>
</span>
</div>
</div>
<div className="col-sm-3">
<div className="input-group">
<UiDatepicker className="form-control" id="to"
maxRestrict="#from"
defaultDate="+1w"
placeholder="Data Final"
dateFormat="dd/mm/yy"
ref={(uidatepicker) => { this.dtpEndRange = uidatepicker; }}/>
<span className="input-group-addon">
<i className="fa fa-calendar"/>
</span>
</div>
</div>
</div>
</fieldset>
<div className="form-actions">                                                    
<button type="button" className="btn btn-primary" onClick={this.handleSearchClick.bind(this)}>
<i className="fa fa-search" >&nbsp;</i>
Pesquisar
</button>&nbsp;                                                        
<button type="button" className="btn btn-primary" disabled>
<i className="fa fa-file-text-o" >&nbsp;</i>
Gerar Swift
</button>&nbsp;
</div>                                                
</form>                                       
</div>
</JarvisWidget>
</article>
</div>
</WidgetGrid>
{(rows.length > 0) && <WidgetGrid>
<div className="row marginTop15">
<article className="col-sm-12">
<JarvisWidget colorbutton={false} editbutton={false} fullscreenbutton={true} 
deletebutton={false} color={"blue"}>
<header>
<span className="widget-icon"> 
<i className="fa fa-dollar" /> 
</span>
<h2>Ordens de Pagamento</h2>
</header>        
<div className="widget-body">                                
<div style={{ position: 'relative' }}>
<GridMotor 
columns={columns}
rows={rows}
totalRows={totalRows}
dateColumns={dateColumns}
currencyColumns= 
{currencyColumns}
iconColumns={iconColumns}
iconFormatter={IconFormatter}
tableColumnExtensions={tableColumnExtensions}
sort={true}
sortingControls={true}
filter={false}
filterControls={false}
groupControl={true}
columnReorder={true}
chooser={true}
paging={true}
pageSizes={[10,20,30]}
changePage={this.changeCurrentPage.bind(this)}
defaultPageSize={defaultPageSize}
selection={false}
selectionAll={false}
resizing={true}
columnWidths={columnWidths}
search={true}
currentPage={currentPage}
changePageSize={this.changePageSize.bind(this)}
/>                
</div>
</div>
</JarvisWidget>
</article>
</div>                
</WidgetGrid>}
{loading && <Loading />}
{error && smallError(error)}
</div>
);
}
}

const mapStateToProps = (state) => (state);
export default connect(mapStateToProps)(Pagamentos)

0 个答案:

没有答案