@@ -72,6 +72,7 @@ export default function ProductSearch() {
7272 const [ currentCameraIndex , setCurrentCameraIndex ] = useState ( 0 ) ;
7373 const [ availableCameras , setAvailableCameras ] = useState < MediaDeviceInfo [ ] > ( [ ] ) ;
7474 const videoRef = useRef < HTMLVideoElement > ( null ) ;
75+ const cameraControlsRef = useRef < { stop : ( ) => void } | null > ( null ) ;
7576 const router = useRouter ( ) ;
7677 const { setNavigating } = useTopBar ( ) ;
7778
@@ -126,7 +127,6 @@ export default function ProductSearch() {
126127 if ( pageLoading ) return ; // Don't start camera until page is loaded
127128
128129 let active = true ;
129- let controls : { stop : ( ) => void } | null = null ;
130130
131131 const startCamera = async ( ) => {
132132 try {
@@ -136,17 +136,19 @@ export default function ProductSearch() {
136136 if ( devices . length > 0 && videoRef . current && active ) {
137137 const selectedDevice = devices [ currentCameraIndex ] || devices [ 0 ] ;
138138 const codeReader = new BrowserMultiFormatReader ( ) ;
139- controls = await codeReader . decodeFromVideoDevice (
139+ const controls = await codeReader . decodeFromVideoDevice (
140140 selectedDevice . deviceId ,
141141 videoRef . current ,
142142 ( result , _err , c ) => {
143143 if ( result && active ) {
144144 router . push ( `/product/${ result . getText ( ) } ` ) ;
145145 c . stop ( ) ;
146+ cameraControlsRef . current = null ;
146147 active = false ;
147148 }
148149 }
149150 ) ;
151+ cameraControlsRef . current = controls ;
150152 }
151153 } catch ( error ) {
152154 console . error ( 'Failed to start camera:' , error ) ;
@@ -159,12 +161,31 @@ export default function ProductSearch() {
159161 return ( ) => {
160162 active = false ;
161163 clearTimeout ( timer ) ;
162- if ( controls ) controls . stop ( ) ;
164+ if ( cameraControlsRef . current ) {
165+ cameraControlsRef . current . stop ( ) ;
166+ cameraControlsRef . current = null ;
167+ }
163168 } ;
164169 } , [ router , pageLoading , currentCameraIndex ] ) ;
165170
171+ // Cleanup camera when component unmounts
172+ useEffect ( ( ) => {
173+ return ( ) => {
174+ if ( cameraControlsRef . current ) {
175+ cameraControlsRef . current . stop ( ) ;
176+ cameraControlsRef . current = null ;
177+ }
178+ } ;
179+ } , [ ] ) ;
180+
166181 const flipCamera = ( ) => {
167182 if ( availableCameras . length > 1 ) {
183+ // Stop current camera before switching
184+ if ( cameraControlsRef . current ) {
185+ cameraControlsRef . current . stop ( ) ;
186+ cameraControlsRef . current = null ;
187+ }
188+
168189 setCurrentCameraIndex ( ( prevIndex ) =>
169190 ( prevIndex + 1 ) % availableCameras . length
170191 ) ;
0 commit comments