You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中如何在ComponentWillUnmount中正确调用Firestore的unsubscribe函数?

解决ComponentWillUnmount中调用unsubscribe时报错的问题

你遇到的问题很明确——你在componentWillUnmount里错误地从props中获取unsubscribe,但实际上你把这个函数存在了组件的state里,所以拿到的是undefined,调用undefined()自然会抛出Uncaught TypeError: unsubscribe is not a function的错误。

下面是具体的修正方案:

1. 修正ComponentWillUnmount的逻辑

把从props获取改成从state获取,并且增加类型检查(防止组件卸载时unsubscribe还没存入state的情况):

componentWillUnmount(){
  const { unsubscribe } = this.state;
  // 先判断是否是函数再调用,避免不必要的报错
  if (typeof unsubscribe === 'function') {
    unsubscribe();
  }
}

2. 优化getNotes方法的写法

你的getNotes里用了that = this来绑定上下文,其实因为用了箭头函数,直接用this就行,同时可以用map简化数组生成的逻辑:

getNotes = () => {
  const db = this.props.firestore;
  const colRef = db.collection("users").doc(this.props.uid)
    .collection("notes");
  
  // 保存监听取消函数到变量
  const unsubscribe = colRef.orderBy("timestamp", "asc")
    .onSnapshot((querySnapshot) => {
      // 用map替代forEach+push,更简洁高效
      const notes = querySnapshot.docs.map(doc => ({ 
        id: doc.id, 
        body: doc.data().body 
      }));
      this.setState({ notes });
    });
  
  // 将unsubscribe存入state
  this.setState({ unsubscribe });
}

为什么原来的代码会报错?

你在componentWillUnmount中写了var unsubscribe = this.props.unsubscribe;,但你的组件props里并没有传递unsubscribe这个属性,而你实际是在getNotes里把unsubscribe存入了组件自己的state中,所以这里拿到的unsubscribe是undefined,调用一个非函数的值就会触发类型错误。

另外补充一个小细节:setState是异步操作,但在这个场景下,因为componentDidMount在组件挂载后只执行一次,getNotes里的unsubscribe会被正确存入state,后续组件卸载时就能获取到这个函数了。

内容的提问来源于stack exchange,提问作者ViktorMS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:30:51