React Native Router Flux切换场景时如何停止摄像头运行?
Hey, I’ve run into exactly this issue before when building a QR scanner with React Native Router Flux! The problem is that the Tabs container preloads all its child Scenes by default—so even when you’re on Scene1, the QR scanner component in Scene2 is already mounted and running the camera in the background, which is why your device is overheating. Here are a few solid fixes you can try:
1. Enable Lazy Loading for Tabs (Simplest Fix)
React Native Router Flux’s Tabs component has a lazy prop that tells it to only mount a Scene when you actually navigate to it. When you switch away, the component unmounts automatically, which will stop the camera without extra code.
Just update your router setup like this:
<Router> <Scene tabs lazy={true} // Add this line // Keep your existing Tabs props here > <Scene key="scene1" component={Scene1} title="Scene 1" /> <Scene key="scene2" component={QRScannerScene} title="Scanner" /> </Scene> </Router>
This is my go-to solution for this scenario—it’s clean and requires minimal changes. The only tradeoff is a tiny initial load delay when switching to Scene2, but that’s negligible for most scanner use cases.
2. Control Camera via Route Focus/Blur Events
If lazy loading isn’t an option (e.g., you need to preload some data for Scene2), you can listen for when the scene gains or loses focus, then manually start/stop the camera.
First, update your Scene2 route to pass focus state:
<Scene key="scene2" component={QRScannerScene} onFocus={() => Actions.refresh({ isSceneFocused: true })} onBlur={() => Actions.refresh({ isSceneFocused: false })} />
Then in your QRScannerScene component:
import React, { Component } from 'react'; import QRCodeScanner from 'react-native-qrcode-scanner'; // Adjust to your scanner library class QRScannerScene extends Component { scannerRef = null; componentDidMount() { // Only start camera if the scene is focused initially if (this.props.isSceneFocused) { this.startCamera(); } } componentDidUpdate(prevProps) { // Toggle camera when focus state changes if (this.props.isSceneFocused !== prevProps.isSceneFocused) { this.props.isSceneFocused ? this.startCamera() : this.stopCamera(); } } componentWillUnmount() { this.stopCamera(); } startCamera = () => { this.scannerRef?.startCamera(); }; stopCamera = () => { this.scannerRef?.stopCamera(); }; handleScanResult = (result) => { // Handle your scan logic here }; render() { return ( <QRCodeScanner ref={ref => this.scannerRef = ref} onRead={this.handleScanResult} // Your scanner config props /> ); } }
3. Listen for Global Route Changes
Another approach is to set up a global listener for route changes in your scanner component, then check if the current scene is Scene2 before keeping the camera running.
Here’s how that would look:
import React, { Component } from 'react'; import { Actions } from 'react-native-router-flux'; import QRCodeScanner from 'react-native-qrcode-scanner'; class QRScannerScene extends Component { scannerRef = null; routeChangeListener = null; componentDidMount() { this.routeChangeListener = Actions.addListener('refresh', () => { const currentScene = Actions.currentScene; // Start/stop camera based on active scene currentScene === 'scene2' ? this.startCamera() : this.stopCamera(); }); // Initial check if (Actions.currentScene !== 'scene2') { this.stopCamera(); } } componentWillUnmount() { // Clean up the listener to avoid memory leaks this.routeChangeListener?.remove(); this.stopCamera(); } // startCamera, stopCamera, and render methods same as above }
Final Recommendation
Stick with the lazy loading approach (Option 1) if it works for your app—it’s the most straightforward and avoids adding extra event listeners or state management. If you need to keep Scene2 preloaded for some reason, Option 2 is the next best choice since it directly ties camera state to the scene’s focus.
内容的提问来源于stack exchange,提问作者Dmitry Yakov

