我有一个陷入无限循环且需要额外眼睛的组件,并帮助寻找摆脱似乎由设置状态触发的无限循环的方法。主要组件呈现数据,并在页面底部设置了分页。问题似乎在搜索中,数据已设置,但是在创建分页时,页面会进入无限循环,并不断调用相同的数据。
使该函数陷入无限循环的方法是:主页上的onChange
我尝试从似乎引起问题的功能中删除设置状态。
减速器片段
switch (action.type) {
case jobConstants.JOB_SUCCESS:
return {
...state,
error: null,
StartLoc: action.newStart,
EndLoc: action.newEnd,
initStart: action.initStart,
initEnd: action.initEnd,
pagMax: action.pagMax,
SearchStrtLoc: action.snewStart,
SearchEndLoc: action.snewEnd,
SearchIntStrt: action.sinitStart,
SearchIntEnd: action.sinitEnd,
searchOn: action.searchOn,
filterOn: action.filterOn
};
BOPagination片段触发了主要组件的变化
const { filterOn, searchOn, SearchEndLoc, SearchStrtLoc, StartLoc, EndLoc } = this.props;
var { items, pageSize, maxPages,pagMax } = this.props;
var pager = this.state.pager;
pager = paginate(items.length, page, pageSize, maxPages);
var pageOfItems = items.slice(pager.startIndex, pager.endIndex + 1);
var newStart = null;
var newEnd = null;
var initStart = this.props.initStart
var initEnd = this.props.initEnd;
var snewStart = null;
var snewEnd = null;
var sinitStart = null;
var sinitEnd = null;
if (searchOn) {
switch (page) {
case 0:
snewStart = SearchEndLoc + 59;
snewEnd = SearchStrtLoc - 1;
if (snewStart > sinitStart) {
this.setState({ doDisable: 'disabled' });
} else {
this.setState({ doDisable: '' });
this.setState({ pager: pager });
this.props.onChangePage(pageOfItems, initStart, initEnd, newStart, newEnd, snewStart, snewEnd, sinitStart, sinitEnd, searchOn, filterOn);
}
break;
case pagMax:
snewStart = SearchEndLoc + 1;
snewEnd = snewStart - 60;
if (snewStart < 0) {
this.setState({ doDisable: 'disabled' });
} else {
this.setState({ doDisable: '' });
this.setState({ pager: pager });
this.props.onChangePage(pageOfItems, initStart, initEnd, newStart, newEnd, snewStart, snewEnd, sinitStart, sinitEnd, searchOn, filterOn);
}
break;
default:
this.setState({ pager: pager });
this.props.onChangePage(pageOfItems, initStart, initEnd, newStart, newEnd, snewStart, snewEnd, sinitStart, sinitEnd, searchOn, filterOn);
break;
}
}
if (!searchOn) {
switch (page) {
case 0:
newStart = StartLoc + 59;
newEnd = StartLoc - 1;
if (newStart > initStart) {
this.setState({ doDisable: 'disabled' });
} else {
this.setState({ doDisable: '' });
this.setState({ pager: pager });
this.props.onChangePage(pageOfItems, initStart, initEnd, newStart, newEnd, snewStart, snewEnd, sinitStart, sinitEnd, searchOn, filterOn);
}
break;
case pagMax:
newStart = EndLoc + 1;
newEnd = newStart - 60;
if (newStart < 0) {
this.setState({ doDisable: 'disabled' });
} else {
this.setState({ doDisable: '' });
this.setState({ pager: pager });
this.props.onChangePage(pageOfItems, initStart, initEnd, newStart, newEnd, snewStart, snewEnd, sinitStart, sinitEnd, searchOn,filterOn);
}
break;
default:
this.setState({ pager: pager });
this.props.onChangePage(pageOfItems, initStart, initEnd, newStart, newEnd, snewStart, snewEnd, sinitStart, sinitEnd, searchOn, filterOn);
break;
}
}
}
进行渲染的主要组件
class LoadTable extends React.Component {
constructor(props) {
super(props);
this.state = {
selectedJName: 0,
filterCheck: 0,
Search: '',
selectedDRan: '',
selectedDStart: '',
selectedDEnd: '',
panelOpen: false,
data: [],
searchRNames: [],
jobNames: [],
searchRLogs: [],
pageOfItems: [],
fetchInProgress: true,
filterOn: false,
searchOn: false,
sort: {
column: null,
direction: 'desc',
},
}
this.clearSearch = this.clearSearch.bind(this);
this.handleSearch = this.handleSearch.bind(this);
this.doSort = this.doSort.bind(this);
this.runLog = this.runLog.bind(this);
this.openRunLog = this.openRunLog.bind(this);
this.onChangePage = this.onChangePage.bind(this);
this.handleJobName = this.handleJobName.bind(this);
this.handleDateRan = this.handleDateRan.bind(this);
this.handleDateEnd = this.handleDateEnd.bind(this);
this.handleDateStart = this.handleDateStart.bind(this);
this.onFilterChange = this.onFilterChange.bind(this);
this.onFilterClear = this.onFilterClear.bind(this);
}
componentDidMount() {
this.setState({ fetchInProgress: true });
this.props.getJobs(null, null)
.then((res) => {
if (res.results.response.length > 0){
var initStart = res.results.response[0].ID;
var initEnd = res.results.response[res.results.response.length - 1].ID;
var newStart = initStart;
var newEnd = initEnd;
var snewStart = null;
var snewEnd = null;
var sinitStart = null;
var sinitEnd = null;
var filterOn = false;
var searchOn = false;
var pagMax = (Math.ceil(res.results.response.length / 10) > 0) ? Math.ceil(res.results.response.length) / 10 : 0;
pagMax = pagMax + 1;
this.props.dispatch({ type: jobConstants.JOB_SUCCESS, newStart, newEnd, initStart, initEnd, pagMax, snewStart, snewEnd, sinitStart, sinitEnd, filterOn, searchOn});
}
this.setState({
fetchInProgress: false,
panelOpen:false,
data: res.results.response || []
})
});
}
handleSearch(e) {
const { name, value } = e.target;
const { SearchEndLoc, SearchStrtLoc, SearchIntStrt, SearchIntEnd, EndLoc, StartLoc } = this.props;
this.setState({ [name]: value });
var initStart;
var initEnd;
var newStart;
var newEnd;
var pagMax;
var snewStart;
var snewEnd;
var sinitStart;
var sinitEnd;
var searchOn;
var filterOn;
this.setState({ fetchInProgress: true });
if (value.length < 1) {
searchOn = false;
this.props.getJobs(EndLoc, StartLoc)
.then((res) => {
initStart = this.props.initStart;
initEnd = this.props.initEnd;
newStart = this.props.StartLoc;
newEnd = this.props.EndLoc;
snewStart = null;
snewEnd = null;
sinitStart = null;
sinitEnd = null;
searchOn = false;
filterOn = false;
pagMax = (Math.ceil(res.results.response.length / 10) > 0) ? Math.ceil(res.results.response.length / 10) : 0;
pagMax = pagMax + 1;
this.props.dispatch({ type: jobConstants.JOB_SUCCESS, newStart, newEnd, initStart, initEnd, pagMax, snewStart, snewEnd, sinitStart, sinitEnd,searchOn, filterOn});
this.setState({
data: res.results.response || [],
fetchInProgress: false,
pageOfItems: res.results.response || [],
Search: '',
panelOpen: false,
searchRNames: [],
sort: {
column: null,
direction: 'desc'
}
})
});
} else {
searchOn = true;
this.props.doSearch(value, SearchEndLoc, SearchStrtLoc)
.then((res) => {
if (res.results.response.length > 0) {
sinitStart = SearchIntStrt === null || SearchIntStrt === undefined ? res.results.response[0].ID : SearchIntStrt;
sinitEnd = SearchIntEnd === null || SearchIntEnd === undefined ? res.results.response[res.results.response.length - 1].ID : SearchIntEnd;
snewStart = sinitStart;
snewEnd = sinitEnd;
newStart = null;
newEnd = null;
initStart = null;
initEnd = null;
filterOn = false;
pagMax = (Math.ceil(res.results.response.length / 10) > 0) ? Math.ceil(res.results.response.length / 10) : 0;
pagMax = pagMax + 1;
this.props.dispatch({ type: jobConstants.JOB_SUCCESS, newStart, newEnd, initStart, initEnd, pagMax, snewStart, snewEnd, sinitStart, sinitEnd, searchOn, filterOn});
}
this.setState({
data: res.results.response || [],
searchRNames: res.results.response || [],
pageOfItems: res.results.response || [],
SearchOn: searchOn,
filterOn: filterOn,
panelOpen: true,
fetchInProgress: false,
Search: value,
sort: {
column: null,
direction: 'desc',
}
})
});
}
}
onChangePage(pageOfItems, initStart, initEnd, newStart, newEnd, snewStart, snewEnd, sinitStart, sinitEnd, searchOn, filterOn) {
var pagMax;
this.setState({ pageOfItems: pageOfItems });
if (searchOn) {
if ((snewStart === null) && (snewEnd === null)) {
this.setState({ fetchInProgress: true });
this.props.doSearch(this.state.Search, newEnd, newStart)
.then((res) => {
if (res.results.response.length > 0) {
sinitStart = res.results.response[0].ID;
sinitEnd = res.results.response[res.results.response.length - 1].ID;
snewStart = sinitStart;
snewEnd = sinitEnd;
pagMax = (Math.ceil(res.results.response.length / 10) > 0) ? Math.ceil(res.results.response.length / 10) : 0;
pagMax = pagMax + 1;
this.props.dispatch({ type: jobConstants.JOB_SUCCESS, newStart, newEnd, initStart, initEnd, pagMax, snewStart, snewEnd, sinitStart, sinitEnd, searchOn, filterOn });
}
this.setState({
fetchInProgress: false,
searchOn: searchOn,
filterOn: filterOn,
panelOpen: true,
data: res.results.response || [],
pageOfItems: res.results.response || [],
sort: {
column: null,
direction: 'desc',
}
})
console.log("ping");
});
}
if ((snewStart !== null) && (snewEnd !== null)){
console.log("stale");
this.setState({ fetchInProgress: true });
this.props.doSearch(this.state.Search, snewEnd, snewStart)
.then((res) => {
if (res.results.response.length > 0) {
snewStart = res.results.response[0].ID;
snewEnd = res.results.response[res.results.response.length - 1].ID;
pagMax = (Math.ceil(res.results.response.length / 10) > 0) ? Math.ceil(res.results.response.length / 10) : 0;
pagMax = pagMax + 1;
searchOn = false;
console.log("stale");
this.props.dispatch({ type: jobConstants.JOB_SUCCESS, newStart, newEnd, initStart, initEnd, pagMax, snewStart, snewEnd, sinitStart, sinitEnd, searchOn, filterOn });
}
this.setState({
data: res.results.response || [],
fetchInProgress: false,
searchOn: searchOn,
filterOn: filterOn,
panelOpen: true,
pageOfItems: res.results.response || [],
sort: {
column: null,
direction: 'desc',
}
})
});
}
}
if((!searchOn)){
console.log("Regular Load");
if ((newStart !== null) && (newEnd !== null)) {
this.setState({ fetchInProgress: true });
this.props.getJobs(newEnd, newStart)
.then((res) => {
if (res.results.response.length > 0) {
newStart = res.results.response[0].ID;
newEnd = res.results.response[res.results.response.length - 1].ID;
snewStart = null;
snewEnd = null;
sinitStart = null;
sinitEnd = null;
pagMax = (Math.ceil(res.results.response.length / 10) > 0) ? Math.ceil(res.results.response.length / 10) : 0;
pagMax = pagMax + 1;
this.props.dispatch({ type: jobConstants.JOB_SUCCESS, newStart, newEnd, initStart, initEnd, pagMax, snewStart, snewEnd, sinitStart, sinitEnd, searchOn, filterOn });
}
this.setState({
data: res.results.response || [],
fetchInProgress: false,
pageOfItems: res.results.response || [],
sort: {
column: null,
direction: 'desc',
}
})
});
}
}
}
render() {
const { data, Search, pageOfItems, searchRNames, fetchInProgress, jobNames, selectedDRan, selectedDStart, selectedDEnd, panelOpen} = this.state;
const { jobRun } = this.props;
let myLabels = document.querySelectorAll('.lbl-toggle');
Array.from(myLabels).forEach(label => {
label.addEventListener('keydown', e => {
// 32 === spacebar
// 13 === enter
if (e.which === 32 || e.which === 13) {
e.preventDefault();
label.click();
};
});
});
return(
data.length < 0 ? (
<div className="row row-centered">
<div className="col-lg-12 col-md-12 col-sm-12 col-xs-12 col-centered">
<div id="Search" className="row col-xs-6 col-lg-3">
<Autocomplete
getItemValue={(item) => item.Name}
items={searchRNames}
inputProps={{ className: 'form-control searchIte ms', placeholder: 'Search', name: 'Search', autoFocus: true }}
value={Search}
onSelect={(Search, item) => this.setState({ Search, searchRNames: item })}
renderItem={(item, isHighlighted) =>
<div></div>
}
onChange={this.handleSearch}
/>
</div>
</div>
<div className="searchNoContent"><h3>No Data to Display at the moment</h3></div>
</div>
) : (
<div className="row row-centered">
<div className="col-lg-12 col-md-12 col-sm-12 col-xs-12 col-centered">
{!IsEmpty(jobRun) && <Alert color="success">{jobRun}</Alert>}
<div className="wrap-collabsible">
<input id="collapsible" className="toggle tCheck" type="checkbox" {panelOpen} />
<label htmlFor="collapsible" className="lbl-toggle">Filter/Search Jobs</label>
<div className="collapsible-content">
<div className="content-inner">
<div id="Search" className="">
<div className="input-group">
<Autocomplete
getItemValue={(item) => item.Name}
items={searchRNames}
inputProps={{ className: 'form-control searchIte ms', placeholder: 'Search', name: 'Search', autoFocus: true }}
value={Search}
onSelect={(Search, item) => this.setState({ Search, searchRNames: item })}
renderItem={(item, isHighlighted) =>
<div></div>
}
onChange={this.handleSearch}
/>
</div>
</div>
<table className="table table-striped">
<thead>
<tr>
<th className="columnHeader" onClick={() => this.doSort('name')}>Name</th>
<th className="columnHeader" onClick={() => this.doSort('date')}>Date Ran</th>
<th className="columnHeader" onClick={() => this.doSort('job')}>Job</th>
<th className="columnHeader" onClick={() => this.doSort('start')}>Start</th>
<th className="columnHeader" onClick={() => this.doSort('end')}>End</th>
<th className="columnHeader" onClick={() => this.doSort('status')}>Status</th>
</tr>
</thead>
<tbody>
{
pageOfItems.map(dt => {
return (
<tr key={dt.ID}>
<td>{dt.Name}</td>
<td><Moment format="YYYY/MM/DD">{dt.DateRan}</Moment></td>
<td>{dt.Job}</td>
<td><Moment format="YYYY/MM/DD HH:mm">{dt.Start}</Moment></td>
<td><Moment format="YYYY/MM/DD HH:mm">{dt.End}</Moment></td>
{dt.Status ?
<td>
<div className="alert alert-success" role="alert">Done </div>
</td>
:
<td>
<div className="alert alert-danger" role="alert">Needs Attention {dt.Status}</div>
</td>
}
<td><button type="button" className="btn btn-primary" onClick={() => this.runLog(dt.ID)}>Run Job</button></td>
<td>
<Popup trigger={<button type="button" className="btn btn-info"> Preview Log </button>}
modal>
{close => (
<div className="">
<a className="close" onClick={close}>×</a>
<div className="header"> {dt.Name}<hr /></div>
<div className="content" style={popUp}>
<pre>{dt.Logs}</pre>
<hr />
</div>
<div className="actions">
<button type="button" className="btn btn-primary" onClick={() => { close() }} >Close</button>
<button type="button" className="btn btn-success" onClick={() => this.openRunLog(dt.Logs)} >View More</button>
</div>
</div>
)}
</Popup>
</td>
<td><button type="button" className="btn btn-success" onClick={() => this.openRunLog(dt.Logs)}>Open Run Log</button> </td>
</tr>
);
})
}
</tbody>
</table>
<BOPagination items={data} onChangePage={this.onChangePage.bind(this)} />
</div>
</div>
))}
</div>
);
}
}
function mapStateToProps(state) {
const { job } = state;
const { jobRun, StartLoc, EndLoc, initStart, initEnd, SearchEndLoc, SearchStrtLoc,SearchIntStrt,SearchIntEnd,SearchpagMax,searchOn,filterOn } = job;
return {
jobRun,
StartLoc,
EndLoc,
initStart,
initEnd,
SearchStrtLoc,
SearchEndLoc,
SearchIntStrt,
SearchIntEnd,
SearchpagMax,
searchOn,
filterOn
};
}
const mapDispatchToProps = dispatch => {
return {
doSearch: (value, StartLoc, EndLoc) => dispatch(jobActions.doSearch(value, StartLoc, EndLoc)),
filterJobs: (jobNames, selectedDRan, selectedDStart, selectedDEnd, newStart, newEnd) => dispatch(jobActions.filterJobs(jobNames, selectedDRan, selectedDStart, selectedDEnd, newStart, newEnd)),
getJobs: (newStart, newEnd) => dispatch(jobActions.getJobs(newStart, newEnd)),
getJobNames: () => dispatch(jobActions.getJobNames()),
findOutput: (logs) => dispatch(jobActions.findOutput(logs)),
runLog: (id)=> dispatch(jobActions.runLog(id)),
dispatch
}
我的目标是在尝试进行搜索时走出循环。任何帮助表示赞赏。