状态变更时重置navigation addListener无效,返回remove仍未解决
问题修复方案
你的代码核心问题是清理函数的位置错误,导致旧的监听器没有在依赖变更时被正确移除,同时依赖数组不完整也会引发闭包问题。以下是修正后的代码及说明:
错误原因分析
原代码中,你把移除监听器的return () => remove()写在了navigation.addListener的回调函数内部,而不是作为useEffect的返回值。这意味着这个清理逻辑永远不会被执行,旧的监听器会一直存在,状态变更时多个监听器同时触发,导致功能异常。
修正后的代码
useEffect(() => { const { page, pageIdx, tab } = pageInfo; // 定义监听器回调 const handleStateChange = ({ data: { state: { routes, index } } }) => { if (routes?.[index]?.name === name) { // 加可选链避免潜在报错 if (pageIdx) { getMatchItem(`usr/goods/match/buy/history/${tab}/${page}`); } else { getItem(`usr/goods/auction/bid/${tab}/${page}`); } } }; // 添加监听器并获取移除函数 const removeListener = navigation.addListener('state', handleStateChange); // 作为useEffect的返回值,在依赖变更/组件卸载时移除监听器 return removeListener; }, [pageInfo, navigation, name, getMatchItem, getItem]); // 补全所有依赖项
关键修正点
- 调整清理函数位置:将移除监听器的逻辑作为
useEffect的返回值,确保React在合适时机(依赖变更、组件卸载)执行清理。 - 补全依赖数组:把
navigation、name、getMatchItem、getItem都加入依赖数组,避免闭包导致的旧值引用问题。如果getMatchItem和getItem是组件内部定义的函数,建议用useCallback包裹,防止不必要的重渲染。 - 添加可选链:在访问
routes[index].name时使用?.,避免状态未初始化时的TypeError。
内容的提问来源于stack exchange,提问作者Youngsung Choi
相关产品推荐
相关产品推荐

