我是React的新手,所以我可能不理解正确的思维概念。
我想做可以安装和卸载的自动更新数据组件。
这是我在卸载然后安装组件时得到的错误:
警告:setState(...):只能更新已安装或已安装 零件。这通常意味着您在已卸载时调用了setState() 零件。这是一个无操作。请检查代码 MeasurementsDataTable组件。
这是代码:
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") );
&#13;
答案 0 :(得分:1)
我认为问题出在您的componentWillMount
。
在安装组件之前,请执行以下操作
在componentWillMount
componentWillMount: function () {
this.props.dataService.addListener(this.updateHandler);
},
这意味着你运行这个功能
DataMeasurementService(ListenersService)
在执行该功能的最后,你运行
listenersService.notifyListeners(Data);
反过来运行你添加的任何听众,包括刚添加的this.updateHandler
,看起来像这样
updateHandler: function(data) {
this.setState({
data: data
});
},
并setState()
。
这一切都发生在之前组件安装,因为这一切都发生在componentWillMount
,Will
是关键字。换句话说,正是错误信息所说的内容。
这通常意味着您在未安装的组件上调用了setState()。
你应该添加任何可能会改变componentDidMount
中组件状态的任何内容,这是在组件安装后发生的,以确保它不会陷入循环或尝试更新未安装的组件。
请记住,将组件渲染两次完全没问题。第一次,你安装它并渲染类似Loading...
的东西。然后在componentDidMount
中,你做任何api抓取,添加事件监听器和其他需要完成的事情。最后,您使用它的实际内容更新(setState()
)组件。
答案 1 :(得分:1)
您必须确保您的组件仍未侦听附加的事件侦听器,并在卸载后尝试自行更新。
使用React时,您需要跟踪所有事件侦听器。如果来自事件侦听器的数据导致组件更新,则必须将侦听器附加到Lifecycle方法componentWillMount()
并将所有侦听器分离到componentWillUnmount()
。
侦听器可以是组件侦听的任何内容,并通过setState()
方法自行更改。它可以是来自套接字的数据,来自服务器的数据,窗口大小调整事件,setInterval监听器等。
答案 2 :(得分:0)
实际上你是在 componentDidMount 中设置间隔,这是在场景后面进行的,并试图设置卸载的组件的状态。
所以请检查您的间隔是否成功清除? 您的 componentWillUnmount 中的一件事会尝试删除具有特定ID的所有侦听器或全部清除,
现在你没有清除你没有传递任何身份证明所以我认为问题在于听众。