2017-10-14 73 views
2

我知道这个问题标题已被多次询问,但我的问题是不同的。我不知道如何解决使用componentWillUnmount警告:setState(...):只能更新已安装或挂载的组件,如何卸载?

我使用firebase的新FireStore添加数据。我也监视着变化

componentDidMount() { 
     fdb.collection(collectionName) 
      .onSnapshot({includeDocumentMetadataChanges: true}, function (querySnapshot) { 
      let items = []; 
      querySnapshot.forEach(function (doc) { 
       let source = doc.metadata.hasPendingWrites ? "[OF]" : "[ON]"; 
       items.push(source + " -> " + doc.data().title); 
       console.log(source, " data: ", doc && doc.data()); 
      }); 
      this.setState({"items": items}); 
     }.bind(this)); 
    } 

因此,这意味着,每一个新的变化被加载时,整个组件被刷新,这意味着当前人会垃圾桶,是一个正确的认识?

如果是,那就意味着我应该停止听这个快照,因为这个快要消失了。这种理解是否正确?

如果是的话,我不知道如何停止听这个正在进行的手表。
我的整个代码看起来像

import React from "react"; 
import {fdb} from "../mainPage/constants"; 

const collectionName = "todos"; 
export default class ToDos extends React.Component { 
    constructor(props) { 
     super(props); 
     this.state = { 
      items: [], 
      textBox: "", 
      loading: true 
     } 
    } 

    componentDidMount() { 
     fdb.collection(collectionName) 
      .onSnapshot({includeDocumentMetadataChanges: true}, function (querySnapshot) { 
      let items = []; 
      querySnapshot.forEach(function (doc) { 
       let source = doc.metadata.hasPendingWrites ? "[OF]" : "[ON]"; 
       items.push(source + " -> " + doc.data().title); 
       console.log(source, " data: ", doc && doc.data()); 
      }); 
      this.setState({"items": items}); 
     }.bind(this)); 
    } 


    handleTextBoxChange = (event) => { 
     this.setState({textBox: event.target.value}); 
    }; 

    handleAddItem =() => { 
     fdb.collection(collectionName).add({ 
      "title": this.state.textBox 
     }).then(function (docRef) { 
      console.log("added " + docRef.id , docRef.get()); 
     }.bind(this)); 
    }; 

    handleRemoveItem = (index) => { 
     let remainingItems = this.state.items; 
     remainingItems.splice(index, 1); 
     this.setState({items: remainingItems}); 
    }; 

    render() { 
     return (
      <div> 
       <div> 
        <input type="text" value={this.state.textBox} onChange={this.handleTextBoxChange}/> 
        <input type="submit" value="Add Item" onClick={this.handleAddItem}/> 
       </div> 
       <div>{this.state.items.map((item, index) => <Item key={index} 
                    index={index} 
                    item={item} 
                    onDeleteClick={this.handleRemoveItem}/>)}</div> 

      </div> 
     ) 
    } 
} 

const Item = ({index, item, onDeleteClick}) => { 
    return <div> 
     <input type="button" value="delete" onClick={() => onDeleteClick(index)}/> 
     <span>{item}</span> 

    </div> 
}; 

而我看到开发者控制台上

Warning: setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the ToDos component. 

是否有人可以帮助我?

+1

该文件清楚说明如何取消订阅。 https://cloud.google.com/nodejs/docs/reference/firestore/0.8.x/CollectionReference#onSnapshot –

+0

@BrahmaDev,谢谢。基于你的帮助,我解决了这个问题(不确定是否优雅) – daydreamer

回答

0

基于来自@Brahma Dev的评论,这就是我如何解决它的。

我在Component的状态下添加了对onSnapshot的引用,并在调用componentWillUnmount时调用它。

componentWillMount() { 
    let unsubscribe = fdb.collection(collectionName) 
     .onSnapshot({includeDocumentMetadataChanges: true}, function (querySnapshot) { 
     let items = []; 
     querySnapshot.forEach(function (doc) { 
      let source = doc.metadata.hasPendingWrites ? "[OF]" : "[ON]"; 
      items.push(source + " -> " + doc.data().title); 
      console.log(source, " data: ", doc && doc.data()); 
     }); 
     this.setState({"items": items}); 
    }.bind(this)); 
    this.setState({"unsubscribe": unsubscribe}); 
} 

componentWillUnmount() { 
    this.state.unsubscribe(); 
} 

如果有更好的方法ReactJS来处理这个问题,请让我知道。谢谢

+0

我建议不要将函数放入状态,因为它会使得响应的内部差异无用。而不是在componentWillMount中,执行this.unsubscribe = fdb ...并在componentWillUnmount内执行this.unsubscribe && this.unsubscribe() –

相关问题