2017-08-07 117 views
1

我幾乎還是react的新手。當我打開我的網頁控制檯顯示我:反應 - 太多的遞歸

太多的遞歸調用

我居然找不到在哪裏錯誤來自原因。 我已經確定的是,當我使用組件CreateFreightEntryModal時發生錯誤。如果我在FreightList組件中取消註釋,則錯誤消失。

這裏是兩個組件的代碼。也許你的某個人可以找到遞歸。

FreightList.js:

import React, { Component } from 'react'; 
import Freight from './Freight'; 
import CreateFreightEntryModal from './CreateFreightEntryModal'; 
import createFragment from 'react-addons-create-fragment'; // ES6 

class FreightList extends Component { 

    constructor(props) { 
     super(props); 
     this.state = { 
      search: "", 
      freights: [], 
      parent: props.parent, 
      updateZonesTable: props.updateZonesTable 
     }; 
     this.loadFreights(); 
    } 

    componentWillReceiveProps(nextProps) { 
    } 


    loadFreights() { 
     $.ajax({ 
      type: "POST", 
      context:this, 
      dataType: "json", 
      async: true, 
      url: "../data/get/json/freight", 
      data: ({ 
       _token : window.Laravel.csrfToken, 
      }), 
      success: function (data) { 

       var arr = $.map(data, function(el) { 
       return el; 
       }); 

       this.setState({ 
       freights: arr 
       }); 

      } 
     }); 
    } 

    handleFreightClick(freight, isChecked) { 
     if(isChecked) { 
      $('#freightListPanelBody').collapse(); 
      $.ajax({ 
       type: "POST", 
       context:this, 
       dataType: "json", 
       async: true, 
       url: "../data/post/json/zones/getZonesByFreightId", 
       data: ({ 
        _token : window.Laravel.csrfToken, 
        freightId: freight.id, 
       }), 
       success: function (data) { 
        this.props.updateZonesTable(data, freight); 
       } 
      }); 
     } 
    } 

    updateSearch(event) { 
     this.setState({ search: event.target.value.substr(0,20) }) 
    } 

    onClose(event) { 
     event.preventDefault(); 
    } 

    openCreateModal(event) { 
     $('#createFreightEntryModal').modal(); 
    } 


    onClick() { 

    } 

    render() { 
     return (
      <div className="panel-group"> 
       <div className="panel panel-default"> 
        <div className="panel-heading"> 
         <a className="accordion-toggle" data-toggle="collapse" href="#freightListPanelBody"><i className="glyphicon glyphicon-menu-down" aria-hidden="true"></i> Freights</a> 
        </div> 
        <div className="panel-body" id="freightListPanelBody" className="collapse in"> 
         <div className="row padding10px"> 
          <div className="col-xs-12 col-sm-12 col-md-9 col-lg-9"> 
           <div className="form-group"> 
            <button className="btn btn-default" onClick={this.openCreateModal.bind(this)}>Create new entry</button> 
            <CreateFreightEntryModal onClose={this.onClose.bind(this)} onClick={this.onClick.bind(this)} /> 
           </div> 
          </div> 
         </div> 

         <div className="row padding10px"> 
          <div className="col-xs-12 col-sm-12 col-md-12 col-lg-12"> 
           Search 
          </div> 
          <div className="col-xs-12 col-sm-12 col-md-9 col-lg-9"> 
           <div className="form-group"> 
            <input className="form-control" type="text" value={this.state.search} placeholder="Search" onChange={this.updateSearch.bind(this)} /> 
           </div> 
          </div> 
         </div> 
         <div className="row padding10px"> 
          <div className="col-xs-12 col-sm-12 col-md-12 col-lg-12"> 
           <div className="table-responsive list"> 
            <table className="table table-hover table-striped" id="freightListTable"> 
             <thead> 
              <tr> 
               ... 
              </tr> 
              <tr> 
               ... 
              </tr> 
             </thead> 
             <tbody> 
             { 
              this.state.freights.map((freight) => { 
               return (
               <Freight freight={freight} onClick={this.handleFreightClick.bind(this)} key={freight.id} /> 
              ); 
              }) 
             } 
             </tbody> 
            </table> 
           </div> 
          </div> 
         </div> 
        </div> 
       </div> 
      </div> 
     ); 
    } 
} 

export default FreightList 

Freight.js:

import React, { Component } from 'react'; 

class Freight extends Component { 

    constructor(props) { 
     super(props); 
     this.state = { 
      freight: props.freight, 
      onClick: props.onClick, 
      isChecked: false 
     }; 
    } 

    onClick(event) { 
     $('#freightListTable').find("input").removeAttr("checked"); 
     this.setState({isChecked: !this.state.isChecked}) 
     this.props.onClick(this.state.freight, !this.state.isChecked); 
    } 

    render() { 
     return (

       <tr className="cursorPointer" onClick={this.onClick.bind(this)}> 
       ... 

       </tr> 

     ); 
    } 
} 

export default Freight 

CreateFreightEntryModal:

import React, { Component } from 'react'; 
import SelectOption from './SelectOption'; 

class CreateFreightEntryModal extends Component { 

    constructor(props) { 
     super(props); 
     this.state = { 
      freights: props.freights, 
      onClose: props.onClose, 
      onClick: props.onClick, 
      companies: [], 
      freighttypes: [], 
      transportmodes: [], 
      hauliers: [], 
      warehouses: [], 
      countries: [], 
      placesOfDeparture: [], 
      products: [], 
      productgroups: [], 
      suppliers: [], 
      currencies: [], 
     }; 
    } 

    componentWillMount() { 
     this.state = { 
      companies: [], 
      freighttypes: [], 
      transportmodes: [], 
      hauliers: [], 
      warehouses: [], 
      countries: [], 
      placesOfDeparture: [], 
      products: [], 
      productgroups: [], 
      suppliers: [], 
      currencies: [] 
     } 
    } 

    componentWillUpdate(nextProps,nextState) { 
     /* 
     if(nextState.companies) { 
      this.setState({ 
       companies: nextState.companies, 
      }, this.render); 
      $('.selectpicker').selectpicker('render'); 
     } 
     */ 
    } 

    loadCompanies(event) { 
     if(this.state.companies == undefined || this.state.companies.length == 0) { 
      $.ajax({ 
       type: "POST", 
       context:this, 
       dataType: "json", 
       async: true, 
       url: "../data/get/json/companies", 
       data: ({ 
        _token : window.Laravel.csrfToken, 
       }), 
       success: data => { 
        var arr = $.map(data, function(el) { return el; }); 
        this.setState({ 
         companies: arr 
        }); 
       } 
      }); 
     } 
     $('.selectpicker').selectpicker('toggle'); 
     $('.selectpicker').selectpicker('render'); 
     $('.selectpicker').selectpicker('refresh'); 
    } 

    loadFreightTypes() { 
     $.ajax({ 
      type: "POST", 
      context:this, 
      dataType: "json", 
      async: true, 
      url: "../data/get/json/freightTypes", 
      data: ({ 
       _token : window.Laravel.csrfToken, 
      }), 
      success: function (data) { 
       var arr = $.map(data, function(el) { return el; }); 
       this.setState({ 
        freighttypes: arr 
       }) 
      } 
     }); 
    } 

    loadTransportModes() { 
     $.ajax({ 
      type: "POST", 
      context:this, 
      dataType: "json", 
      async: true, 
      url: "../data/get/json/transportModes", 
      data: ({ 
       _token : window.Laravel.csrfToken, 
      }), 
      success: function (data) { 
       var arr = $.map(data, function(el) { return el; }); 
       this.setState({ 
        transportmodes: arr 
       }) 
      } 
     }); 
    } 

    loadHauliers() { 
     $.ajax({ 
      type: "POST", 
      context:this, 
      dataType: "json", 
      async: true, 
      url: "../data/get/json/haulier", 
      data: ({ 
       _token : window.Laravel.csrfToken, 
       filter: "noStopFlag", 
       value: "0", 
      }), 
      success: function (data) { 
       var arr = $.map(data, function(el) { return el; }); 
       this.setState({ 
        hauliers: arr 
       }) 
      } 
     }); 
    } 

    loadWarehouses() { 
     $.ajax({ 
      type: "POST", 
      context:this, 
      dataType: "json", 
      async: true, 
      url: "../data/get/json/warehouses", 
      data: ({ 
       _token : window.Laravel.csrfToken, 
       filter: "noStopFlag", 
       value: "0", 
      }), 
      success: function (data) { 
       var arr = $.map(data, function(el) { return el; }); 
       this.setState({ 
        warehouses: arr 
       }) 
      } 
     }); 
    } 

    loadCountries() { 
     $.ajax({ 
      type: "POST", 
      context:this, 
      dataType: "json", 
      async: true, 
      url: "../data/get/json/countries", 
      data: ({ 
       _token : window.Laravel.csrfToken, 
      }), 
      success: function (data) { 
       var arr = $.map(data, function(el) { return el; }); 
       this.setState({ 
        countries: arr 
       }) 
      } 
     }); 
    } 

    loadPlacesOfDeparture() { 
     $.ajax({ 
      type: "POST", 
      context:this, 
      dataType: "json", 
      async: true, 
      url: "../data/get/json/placesOfDeparture", 
      data: ({ 
       _token : window.Laravel.csrfToken, 
      }), 
      success: function (data) { 
       var arr = $.map(data, function(el) { return el; }); 
       this.setState({ 
        placesOfDeparture: arr 
       }) 
      } 
     }); 
    } 

    loadProducts() { 
     $.ajax({ 
      type: "POST", 
      context:this, 
      dataType: "json", 
      async: true, 
      url: "../data/get/json/products", 
      data: ({ 
       _token : window.Laravel.csrfToken, 
       filter: "noStopFlag", 
       value: "0", 
      }), 
      success: function (data) { 
       var arr = $.map(data, function(el) { return el; }); 
       this.setState({ 
        products: arr 
       }) 
      } 
     }); 
    } 

    loadProductGroups() { 
     $.ajax({ 
      type: "POST", 
      context:this, 
      dataType: "json", 
      async: true, 
      url: "../data/get/json/productgroups", 
      data: ({ 
       _token : window.Laravel.csrfToken, 
       filter: "noStopFlag", 
       value: "0", 
      }), 
      success: function (data) { 
       var arr = $.map(data, function(el) { return el; }); 
       this.setState({ 
        productgroups: arr 
       }) 
      } 
     }); 
    } 

    loadSuppliers() { 
     $.ajax({ 
      type: "POST", 
      context:this, 
      dataType: "json", 
      async: true, 
      url: "../data/get/json/suppliers", 
      data: ({ 
       _token : window.Laravel.csrfToken, 
       filter: "byBrancheAndStopFlag", 
       branche: "2", 
       stopFlag: "0", 
      }), 
      success: function (data) { 
       var arr = $.map(data, function(el) { return el; }); 
       this.setState({ 
        suppliers: arr 
       }) 
      } 
     }); 
    } 

    loadCurrencies() { 
     $.ajax({ 
      type: "POST", 
      context:this, 
      dataType: "json", 
      async: true, 
      url: "../data/get/json/currencies", 
      data: ({ 
       _token : window.Laravel.csrfToken, 
      }), 
      success: function (data) { 
       var arr = $.map(data, function(el) { return el; }); 
       this.setState({ 
        currencies: arr 
       }) 
      } 
     }); 
    } 

    add(event) { 

    } 

    render() { 
     return (
      <div className="modal fade" id="createFreightEntryModal" tabIndex="-1" role="dialog"> 
       <div className="modal-dialog" role="document"> 
        <div className="modal-content"> 
         <div className="modal-header"> 
          <button type="button" className="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button> 
          <h4 className="modal-title">New freight entry</h4> 
         </div> 
         <div className="modal-body"> 
          <div> 
           <div> 
            <form onSubmit={this.add.bind(this)}> 
             <div className="row"> 
              <div className="col-xs-12 col-sm-12 col-md-12 col-lg-12"> 
               <strong>Create a new freight entry:</strong> 
              </div> 
             </div> 
             <div className="row"> 
              <div className="col-xs-4 col-sm-4 col-md-4 col-lg-4"> 
               Company 
              </div> 
              <div className="col-xs-8 col-sm-8 col-md-8 col-lg-8"> 
               <div className="form-group" onClick={this.loadCompanies.bind(this)}> 
                <select className="selectpicker show-tick form-control" data-id="selectBoxCompany" data-live-search="true" data-title="Please select" ref="Firma" required> 
                { 
                 this.state.companies.map((company)=> { 
                  return (
                  <SelectOption value={company.Nummer} displayValue={company.Bezeichnung} key={company.id} /> 
                 ); 
                 }) 
                } 
                </select> 
               </div> 
              </div> 
             </div> 

             ... 

             <div className="row"> 
              <div className="col-xs-12 col-sm-12 col-md-12 col-lg-12"> 
               <div className="form-group"> 
                <button type="submit" className="btn btn-success"><span className="glyphicon glyphicon-floppy-disk"></span> Save </button> 
               </div> 
              </div> 
             </div> 
            </form> 
           </div> 
          </div> 
         </div> 
         <div className="modal-footer"> 
          <button type="button" className="btn btn-default" data-dismiss="modal">Close</button> 
         </div> 
        </div> 
       </div> 
      </div> 
     ); 
    } 
} 

export default CreateFreightEntryModal 

Ť他的運費清單是通過ajax請求加載的。這裏有一個貨運項的樣本:

freight entries list

完整的貨運清單包括539項貨運。

的行數是這樣的:

enter image description here

+0

錯誤的任何指示 - 像行號 - 發生這種情況 –

+1

通常,這發生在componentDidUpdate中存在setState時發生。 setState引起遞歸更新(無停止條件)。 – vijayst

+0

我已經更新了原始文章的行號,但我不確定這是否有幫助... –

回答

0

我發現了錯誤。它在SelectOption組件中。 有人像@vijayst說遞歸componentDidUpdate遞歸。 感謝您的提示!