【问题标题】:React - too much recursionReact - 太多的递归
【发布时间】:2018-01-14 09:00:12
【问题描述】:

我对@9​​87654325@ 还是个新手。当我打开网页时,控制台会显示:

递归太多

我实际上找不到错误的原因。 我已经确定的是,当我使用组件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请求加载的。这是一个货运条目的示例:

完整的货运清单由 539 个货运条目组成。

行号是这样的:

【问题讨论】:

  • 任何来自错误的指示——比如行号——发生这种情况的地方
  • 通常,当componentDidUpdate中有setState时会出现这种情况。并且 setState 会导致递归更新(没有停止条件)。
  • 我已经用行号更新了原始帖子,但我不确定这是否有帮助......
  • 代码太多了,我们甚至无法尝试重现您的问题。这实际上是不可能的,因为您非常依赖远程服务。请尝试将您的代码减少到仍然会导致此错误的最小。 – 出于调试目的,您应该将日志记录添加到您的方法中,这样您就可以看到哪些代码仍然可以正常运行,以及哪些代码在错误之前最后运行。这样您就可以确定问题所在。
  • CreateFreightEntryModal 中,为什么要在构造函数中将this.state 分配给prop 值,然后立即在componentWillMount 中将所有这些都替换为空值?

标签: javascript laravel reactjs


【解决方案1】:

我发现了错误。它在SelectOption 组件中。 就像@vijayst 说的componentDidUpdate 递归。 感谢您的提示!

【讨论】:

    猜你喜欢
    • 2011-11-11
    • 1970-01-01
    • 2020-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-03
    • 2021-11-02
    • 1970-01-01
    相关资源
    最近更新 更多