I understand from this SO answer, that we must manually remove Firebase listeners.在以下用例中该如何做?我的成功尝试如下代码所示。
I tried to use some of the ideas from this answer too.,但未成功。
我在做什么错了?
import React, { Component } from 'react';
// redacted for brevity
import firebase from '@firebase/app';
import '@firebase/firestore';
class CRUDContainer extends Component {
state = {
items: [],
path: null,
isError: false,
isLoading: true,
};
componentWillUnmount () {
// cancel subscriptions and async tasks to stop memory leaks
this.unsubscribe(this.path);
}
unsubscribe = path => path && firebase.firestore().collection(path).onSnapshot(() => {})
getItems = path => {
const out = [];
const db = firebase.firestore();
if(!db) return;
db.collection(path)
.orderBy('timestamp', 'desc')
.get()
.then(querySnapshot => {
querySnapshot.forEach(doc => {
out.push(doc.data());
});
return out;
})
.then(result => {
const newState = {
path,
items: result,
isError: false,
isLoading: false,
};
this.setState(newState);
return result;
})
.then(() => {
this.unsubscribe(path);
return path;
})
.catch(error => {
console.error('Error getting documents: \n', error);
const newState = {
isError: true,
isLoading: false,
};
this.setState(newState);
});
};
Child = ({ match: { params: { id }}}) => {
// redacted for brevity
getItems(path);
return (
this.state.isLoading
?
<Loading/>
:
(
this.state.isError
?
<ErrorMessage/>
:
(items && (
<CRUDView items={items} />
)))
)
};
render() {
return <Route path="/:id" component={this.Child} />
}
}
export default CRUDContainer;