-
Notifications
You must be signed in to change notification settings - Fork 202
Description
📝 Description
I am building a React Native application that uses ViroReact for an Augmented Reality (AR) coin collection feature. The core AR view is wrapped in a within a child component (Viro.tsx/ObjectDetectionAR). This component is conditionally rendered in the parent component (App.tsx) based on a state variable (isNearby), which simulates a WebSocket response indicating proximity to a coin.
The issue is that every time the AR view is unmounted and then re-mounted (i.e., isNearby changes from truthy to falsy and back), memory consumption increases by approximately 200MB on iOS (observed via Xcode Memory Debugger). After 10-12 such state changes/re-renders, the memory usage reaches around 2GB, and the OS terminates the app.
This strongly suggests that the underlying native ViroARSceneNavigator view is not being completely destroyed or cleaned up when its React Native component unmounts, leading to a cumulative memory leak.
💻 Environment
React Native version: 0.81.1
ViroReact version: 2.44.2
Target Platform: iOS and Android
Development OS: MacOS 26.1 (25B78)
🔄 Reproduction
- Parent Component (App.tsx)
import Viro from './Viro';
import React, { useMemo } from 'react';
import { SafeAreaView } from 'react-native-safe-area-context';
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
function App() {
const [showAR, setShowAR] = React.useState<boolean>(false);
const ViroComp = useMemo(() => {
return <Viro />;
}, []);
return (
<SafeAreaView style={styles.container} edges={['top']}>
{showAR ? (
ViroComp
) : (
<View style={styles.innerContainer}>
<Text style={styles.text}>
Other Component Will be displayed here
</Text>
</View>
)}
<TouchableOpacity
style={styles.button}
onPress={() => setShowAR(!showAR)}
>
<Text style={styles.text}>Toggle AR</Text>
</TouchableOpacity>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'white',
},
innerContainer: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
text: {
fontSize: 30,
width: '80%',
color: 'black',
fontFamily: 'Arial',
textAlign: 'center',
textAlignVertical: 'center',
},
button: {
height: 80,
width: '100%',
alignItems: 'center',
backgroundColor: 'teal',
justifyContent: 'center',
},
});
export default App;
- Child Component (Viro.tsx)
import {
ViroARScene,
ViroARSceneNavigator,
ViroText,
ViroTrackingReason,
ViroTrackingStateConstants,
} from '@reactvision/react-viro';
import React, { useState } from 'react';
import { StyleSheet } from 'react-native';
const HelloWorldSceneAR = () => {
const [text, setText] = useState('Initializing AR...');
function onInitialized(state: any, reason: ViroTrackingReason) {
console.log('onInitialized', state, reason);
if (state === ViroTrackingStateConstants.TRACKING_NORMAL) {
setText('Hello World!');
} else if (state === ViroTrackingStateConstants.TRACKING_UNAVAILABLE) {
console.log('Tracking Unavailable');
}
}
return (
<ViroARScene onTrackingUpdated={onInitialized}>
<ViroText
text={text}
scale={[0.5, 0.5, 0.5]}
position={[0, 0, -1]}
style={styles.helloWorldTextStyle}
/>
</ViroARScene>
);
};
export default () => {
return (
<ViroARSceneNavigator
autofocus={true}
initialScene={{
scene: HelloWorldSceneAR,
}}
style={styles.f1}
/>
);
};
var styles = StyleSheet.create({
f1: { flex: 1 },
helloWorldTextStyle: {
fontFamily: 'Arial',
fontSize: 30,
color: '#ffffff',
textAlignVertical: 'center',
textAlign: 'center',
},
});
-
Steps to Reproduce
- Launch the application.
- Open Xcode and monitor the memory usage for the application process.
- Click the "Show AR" button to set isNearby to true, mounting the . Observe memory spike (~200MB).
- Click the "Hide AR" button to set isNearby to false, unmounting the . Observe memory drop, but the baseline remains elevated.
- Repeat steps 3 and 4 approximately 10-12 times.
- The app will be killed by the OS due to excessive memory usage.
💡 Expected Behavior
When the component is unmounted (i.e., isNearby becomes false), all associated native resources and memory (including the AR session, camera feed, and Viro framework state) should be completely released, and the baseline memory usage should return to its initial state.
❓ Potential Cause
The issue is likely that the native VRTARSceneNavigator view is not being properly deallocated, or its underlying ARSession is not being paused/destroyed, when the React Native component's lifecycle componentWillUnmount (or equivalent in functional components) is triggered.
Any guidance or potential workarounds to force the destruction of the native AR session upon unmount would be greatly appreciated.