首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ReactJS - setState在unMounting和安装时的错误

ReactJS - setState在unMounting和安装时的错误
EN

Stack Overflow用户
提问于 2015-12-17 13:15:03
回答 3查看 2.2K关注 0票数 2

我是新的反应,所以我可能不理解正确的思维概念。

我想做自动更新数据组件,可以我挂载和卸载。

这是一个错误,当我卸载然后挂载组件时:

警告:setState(.):只能更新挂载或安装组件。这通常意味着在未挂载的组件上调用setState()。这是禁止行动。请检查MeasurementsDataTable组件的代码。

这是密码:

代码语言:javascript
复制
var getDataInretval;
var listenersService = new ListenersService();
var Data = [{}];

function ListenersService(){
    var listeners = {};
    this.addListener = function(callback){
        var id;
        if(typeof callback === 'function'){
            id = Math.random().toString(36).slice(2);
            listeners[id] = callback;
        }
        return id;
    }
    this.removeListener = function( id){
        if(listeners[id]){
            delete listeners[id];
            return true;
        }
        return false;
    }
    this.notifyListeners = function(data){
        for (var id in listeners) {
            if(listeners.hasOwnProperty(id)){
                listeners[id](data);
            }
        }
    }
}


var dataSevice = new DataMeasurementService(ListenersService);

function DataMeasurementService(ListenersService){

    Data.push( new MeasurementDataForTable("header1", "th", "Phase measurements", "L1", "L2", "L3", "Total", "Others") );
    var self = this;

    //var listenersService = new ListenersService();
    this.addListener = listenersService.addListener;
    this.removeListener = listenersService.removeListener;
    this.getData = function(){
        return Data;
    }

    $.ajax({
        url: "BL/getMeasurementsData.php",
        type: "GET",
        dataType: "html",
        async: false,
        success: function(res) {
            var parseData = parseMeasurementsData( res );
            Data = createOriginData( parseData );
        },
        error: function(request, status, error) {
            alert("error: " + request.responseText);
        }
    });
    listenersService.notifyListeners(Data);
}

var ThElement = React.createClass({
   render: function(){
       return <th  width={this.props.width}>{this.props.data}</th>;
   }
});

var TdElement = React.createClass({
    render: function(){
        return <td>{this.props.data}</td>;
    }
});

var MeasurementsDataTable = React.createClass({
    getInitialState: function() {
        return {
            data: this.props.dataService.getData()
        };
    },
    componentDidMount: function() {
        getDataInretval = setInterval(function(){
            $.ajax({
                url: "BL/getMeasurementsData.php",
                type: "GET",
                dataType: "html",
                async: false,
                success: function(res) {
                    var parseData = parseMeasurementsData( res );
                    Data = createOriginData( parseData );
                },
                error: function(request, status, error) {
                    alert("error: " + request.responseText);
                }
            });

            listenersService.notifyListeners(Data);
        }, 1000);


    },
    componentWillMount: function () {
        this.props.dataService.addListener(this.updateHandler);
    },
    componentWillUnmount: function () {
        this.removeListener = listenersService.removeListener;
        clearInterval(getDataInretval);
    },
    updateHandler: function(data) {
        this.setState({
            data: data
        });
    },
    render: function() {
        return (
            <div>
                <table>
                    {
                        this.state.data.map(function(item) {
                                if( item.element == "th" ){
                                    return (
                                        <thead><tr>
                                            <ThElement width="280" data={item.description}/>
                                            <ThElement width="150" data={item.L1}/>
                                            <ThElement width="150" data={item.L2}/>
                                            <ThElement width="150" data={item.L3}/>
                                            <ThElement width="150" data={item.total}/>
                                            <ThElement width="150" data={item.others}/>
                                        </tr></thead>
                                    )
                                }
                                else{
                                        return (
                                            <tr>
                                                <TdElement data={item.description}/>
                                                <TdElement data={item.L1}/>
                                                <TdElement data={item.L2}/>
                                                <TdElement data={item.L3}/>
                                                <TdElement data={item.total}/>
                                                <TdElement data={item.others}/>
                                            </tr>
                                        )
                                    }
                        })
                    }
               </table>
            </div>
        );
    }
});
ReactDOM.render( <MeasurementsDataTable dataService={dataSevice} />, document.getElementById("tablePlaceHolder") );

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-12-17 13:47:33

您必须确保组件没有继续侦听附加的事件侦听器,并试图在卸载后更新自己。

您需要在使用React时跟踪所有事件侦听器。如果事件侦听器中的数据导致组件更新,则必须将侦听器附加到生命周期方法componentWillMount(),并在componentWillUnmount()中分离所有侦听器。

侦听器可以是组件侦听并通过setState()方法自行更改的任何内容。它可以是来自套接字的数据、来自服务器的数据、关于窗口调整大小事件的数据、setInterval侦听器等。

票数 1
EN

Stack Overflow用户

发布于 2015-12-17 13:42:36

我相信问题出在你的componentWillMount上。

在挂载组件之前,请执行以下操作

componentWillMount中添加侦听器

代码语言:javascript
复制
componentWillMount: function () {
    this.props.dataService.addListener(this.updateHandler);
},

这意味着您运行这个函数。

代码语言:javascript
复制
DataMeasurementService(ListenersService)

在执行该函数的最后,您将运行

代码语言:javascript
复制
listenersService.notifyListeners(Data);

它依次运行您添加的任何侦听器,包括刚才添加的this.updateHandler,如下所示

代码语言:javascript
复制
updateHandler: function(data) {
    this.setState({
        data: data
    });
},

和威尔setState()

这一切都发生在组件挂载之前的,因为所有这些都发生在componentWillMount中,Will是这里的关键字。换句话说,错误消息到底是怎么说的。

这通常意味着在未挂载的组件上调用setState()。

您应该添加任何可能在componentDidMount中更改组件状态的内容,这是在组件挂载之后发生的,以确保组件不会卡在循环中或尝试更新未安装的组件。

记住,两次呈现组件是非常好的。第一次,您安装它并呈现类似于Loading...的内容。然后在componentDidMount中,您可以执行任何api获取、添加事件侦听器和其他需要完成的操作。最后,用它的实际内容更新(setState())组件。

票数 1
EN

Stack Overflow用户

发布于 2015-12-17 14:40:33

实际上,您正在设置componentDidMount中的间隔,这是在场景后面进行的,并试图设置组件的卸载状态。

检查一下你的间隔是否被清除了?在您的componentWillUnmount中,还有一件事是尝试删除所有具有特定id或清除all的侦听器,

现在您没有清除,您没有传递任何id,所以我认为问题在于侦听器。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34335525

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档