RxJS Subject订阅内调用setState触发React内存泄漏报错排查
问题原因
- 你声明的
testSubject是全局的Subject实例,配套的setInterval会每2秒触发一次next推送新值,不会随页面卸载自动终止 - 你在
useFocusEffect中调用了testSubject.subscribe,但没有在返回的清理函数中取消这个订阅:页面第一次离开TestPage时组件已经卸载,但之前绑定的订阅回调仍然存活,当Subject推送新值时,回调里的setData就会触发「已卸载组件更新状态」的警告 - 第二次进入页面时会新增一个订阅,此时内存里同时存在两个订阅回调:旧回调对应已经卸载的组件实例,新回调对应新挂载的实例,旧回调触发时就会抛出你遇到的警告
修复方案
订阅会返回一个Subscription对象,调用它的unsubscribe方法即可取消当前订阅,将清理逻辑替换为取消订阅即可解决问题,修复后代码如下:
export const testSubject = new Subject<any>(); setInterval(() => { testSubject.next({ dest: 'any', msg: [] }); }, 2000); function TestPage({ route, navigation }) { const [data, setData] = useState<any[]>([]); useFocusEffect( useCallback(() => { // 保存订阅实例 const subscription = testSubject.subscribe(({ dest, msg }) => { setData(msg); }); // 页面失焦/卸载时取消订阅 return () => subscription.unsubscribe(); }, []), ); return ( <View> <Text>{JSON.stringify(data)}</Text> <Button onPress={() => { navigation.navigate('home'); }} title="back" /> </View> ); } export default TestPage;
内容的提问来源于stack exchange,提问作者Plochie
相关产品推荐
相关产品推荐

