如何摆脱set State创建的无限循环?

时间:2019-07-26 18:38:55

标签: reactjs

我有一个陷入无限循环且需要额外眼睛的组件,并帮助寻找摆脱似乎由设置状态触发的无限循环的方法。主要组件呈现数据,并在页面底部设置了分页。问题似乎在搜索中,数据已设置,但是在创建分页时,页面会进入无限循环,并不断调用相同的数据。

使该函数陷入无限循环的方法是:主页上的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}>&times;</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
    }

我的目标是在尝试进行搜索时走出循环。任何帮助表示赞赏。

0 个答案:

没有答案