2015-12-17 6 views
2

Я новичок в React, поэтому я не могу понять правильную концепцию мышления.ReactJS - setState error when unMounting and Mounting

Я хочу сделать компонент данных автоматического обновления, который можно смонтировать и размонтировать.

Это ошибка, которую я получаю, когда я демонтирована, а затем компонент установлен:

Предупреждение: SetState (...): Можно только обновить установленную или монтажную компонента. Обычно это означает, что вы вызывали setState() на незамонтированном компоненте . Это не-op. Проверьте код для компонента 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"));

+0

Я не эксперт, но вы можете попробовать переместить 'addListener' из' componentWillMount' в 'componentDidMount'? –

ответ

1

Вы должны убедиться, что ваш компонент еще не прослушивает подключенный прослушиватель событий и пытается обновить себя после размонтирования.

Вам необходимо отслеживать ВСЕ прослушиватели событий при использовании React. Если данные из прослушивателей событий заставляют ваш компонент обновляться, вы должны присоединить слушателя к методу Lifecycle componentWillMount() и отсоединить всех ваших слушателей в componentWillUnmount().

Слушатели могут быть любыми, что ваш компонент слушает и изменяет себя на setState() метод. Он может представлять собой данные из сокета, данные с сервера, на окно изменения размера событии, setInterval слушатель и т.д.

+0

Я добавляю идентификатор к слушателю, а затем удаляю его в 'componentWillMount'. Оно работает. Спасибо. – Jan

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 вы делаете все, что хотите, добавляете прослушиватели событий и другие вещи, которые необходимо выполнить. Наконец, вы обновляете (setState()) компонент с его фактическим содержимым.

+0

согласно реакции docs вы можете установить состояние в 'componentWillMount' –

0

На самом деле вы устанавливаете интервал в componentDidMount, который происходит за сценой и пытаетесь установить состояние компоненты, которые получают демонтирована.

Так что просто проверьте. Успешно ли ваш интервал очищается или нет? И еще одно в вашем componentWillUnmount попытаться удалить все слушатель с конкретным идентификатором или очистить все,

Теперь вы не очищая вы не проходя ИН Поэтому я думаю, что проблема со слушателями.

 Смежные вопросы

  • Нет связанных вопросов^_^