警告:setState(...):只能更新已安装或挂载的组件,如何卸载?
问题描述:
我知道这个问题标题已被多次询问,但我的问题是不同的。我不知道如何解决使用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.
是否有人可以帮助我?
答
基于来自@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() –
该文件清楚说明如何取消订阅。 https://cloud.google.com/nodejs/docs/reference/firestore/0.8.x/CollectionReference#onSnapshot –
@BrahmaDev,谢谢。基于你的帮助,我解决了这个问题(不确定是否优雅) – daydreamer