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

合并Firebase实时监听unsubscribe函数触发栈溢出错误的技术求助

问题分析与修复

问题根源

你遇到的RangeError: Maximum call stack size exceeded是因为在onScrollToBottom里重写unsubscribe函数时触发了无限递归:

unsubscribe = () => {
    this.state.unsubscribe()
    unsubscribe() // 此处的unsubscribe就是当前新定义的函数,会无限调用自身
}

另外直接依赖this.state.unsubscribe存在风险,因为setState是异步操作,可能无法获取到最新的状态值。

修复方案

不要每次替换单个unsubscribe函数,而是维护一个数组统一存储所有的unsubscribe函数,便于批量管理:

componentDidMount = async () => {
    // 初始化存储unsubscribe的数组
    this.unsubscribeList = []
    const unsubscribe = await getDocsRealtime()
    this.unsubscribeList.push(unsubscribe)

    window.addEventListener('scroll', this.onScrollToBottom)
}

onScrollToBottom = async () => {
    if (window.scrollY > placeholderTop) {
        const unsubscribe = await getDocsRealtime()
        // 将新的unsubscribe加入数组
        this.unsubscribeList.push(unsubscribe)
    }
}

componentWillUnmount = () => {
    // 遍历执行所有unsubscribe函数
    this.unsubscribeList.forEach(unsubscribe => unsubscribe())
    window.removeEventListener('scroll', this.onScrollToBottom)
}

额外优化(用state管理)

如果组件内其他逻辑需要依赖该状态,也可以用数组类型的state来维护:

componentDidMount = async () => {
    const unsubscribe = await getDocsRealtime()
    this.setState({ unsubscribeList: [unsubscribe] })
    window.addEventListener('scroll', this.onScrollToBottom)
}

onScrollToBottom = async () => {
    if (window.scrollY > placeholderTop) {
        const unsubscribe = await getDocsRealtime()
        this.setState(prevState => ({
            unsubscribeList: [...prevState.unsubscribeList, unsubscribe]
        }))
    }
}

componentWillUnmount = () => {
    this.state.unsubscribeList?.forEach(unsubscribe => unsubscribe())
    window.removeEventListener('scroll', this.onScrollToBottom)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 06:05:19