2016-05-24 2 views
1

Я получаю это предупреждение с помощью setState в functin ниже, может ли кто-нибудь рассказать мне, как мне нужно структурировать код, чтобы избавиться от него?React Warning, setState (...) в ComponentDidMount

warning.js: 46 Предупреждение: setState (...): Может обновлять только установленный или монтажный компонент. Обычно это означает, что вы вызывали setState() на немонтированном компоненте. Это не-op. Проверьте код для компонента FileInput.

componentDidMount: function() { 
    var self = this; 
    this.initUploader(); 

    this.uploader.init(); 

    EVENTS.forEach(function (event) { 
     var handler = self.props['on' + event]; 
     if (typeof handler === 'function') { 
      self.uploader.bind(event, handler); 
     } 
    }); 


    this.uploader.bind('FileUploaded', function (up, file, res) { 
     var objResponse = JSON.parse(res.response); 
     console.log(objResponse.reference); 
     self.props.getFileRef(objResponse.reference); 


     var stateFiles = self.state.files; 
     _.map(stateFiles, function (val, key) { 
      if (val.id === file.id) { 
       val.uploaded = true; 
       stateFiles[key] = val; 
      } 
     }); 
     // setState causing warning 
     self.setState({ files: stateFiles }, function() { 
      self.removeFile(file.id); 
     }); 
    }); 
+0

Где определяется 'self'? –

+0

Спасибо за ответ, обновленное сообщение – Bomber

ответ

2

Обработчик события FileUploaded является вызов setState с помощью укупорочных self ссылки. Это приводит к утечкам, когда компонент был размонтирован, а затем триггеры события FileUploaded и setState вызывается на несмонтированном компоненте. Подробнее об этом вы можете прочитать в этой статье, которая несколько связана с ней - https://facebook.github.io/react/blog/2015/12/16/ismounted-antipattern.html.

Теперь, как исправить это, зависит от того, позволяет ли ваш объект uploader развязать обработчик событий. Если это разрешено, вы можете это сделать -

  1. Определите код обработчика FileUploaded как именованную функцию (вместо анонимной). Вам нужно сделать это, чтобы потом отвязать его.
  2. Измените код в componentDidMount, чтобы связать именованную функцию как обработчик события FileUploaded.
  3. Добавьте обработчик события componentWillUnmount к вашему компоненту и вызовите механизм отвинчивания uploader, передав ему ссылку на именованный обработчик.

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

PS: Вы должны удалить (отвязать) всех обработчиков вы регистрируетесь в коде выше, в противном случае вы будете протечками ссылки повсюду и что более важно, останетесь целой массой осиротевших обработчиков событий.

== UPDATE ==

По Вашему Fiddle, вы можете -

  1. Объявите эти новые методы в компоненте -

    registerHandler: function(uploader, event, handler){ 
        this.handlers = this.handlers || []; 
        this.handlers.push({e: event, h: handler}); 
        uploader.bind(event, handler); 
    }, 
    
    unregisterAllHandlers : function(uploader){ 
        for (var i = 0; i < this.handlers.length; i++){ 
         var handler = this.handlers[i], 
         e = handler.e, 
         h = handler.h; 
         // REPLACE with the actual event unbinding method 
         // of uploader. 
         uploader.unbind(e, h); 
         delete this.handlers[i]; 
        } 
    }, 
    
    componentWillUnmount: function(){ 
        this.unregisterAllHandlers(this.uploader); 
    } 
    
  2. Использование registerHandler во всех тех местах, где вы вызываете uploader.bind -

    self.registerHandler(self.uploader, event, handler);

    ИЛИ

    this.registerHandler(this.uploader,'FilesAdded', function (up, files) { if (_.get(self.props, 'multi_selection') === false) {...});

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

+0

Спасибо за ответ, есть ли у вас какие-либо примеры кода, как я это сделал бы? – Bomber

+0

Связанная статья содержит хорошие образцы кода. Если вы можете создать jsfiddle, я могу изменить его с помощью предлагаемого подхода. – hazardous

+0

У меня здесь есть скрипка, я уже привязываюсь к компонентуDidMount, https://jsfiddle.net/69z2wepo/43248/ – Bomber

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