From 1c1e7e4a3ff21ff824a2ef2fe5b877f94912b8d2 Mon Sep 17 00:00:00 2001 From: Nuwan Date: Tue, 24 Feb 2026 23:19:31 +0530 Subject: [PATCH] fix(25-01): add async cleanup in JKSessionRecordingModal - Add ignore flag pattern to audio preference useEffect - Add ignore flag pattern to video sources useEffect - Guard state updates with !ignore check - Prevents "state update on unmounted component" warnings --- .../client/JKSessionRecordingModal.js | 72 ++++++++++++------- 1 file changed, 46 insertions(+), 26 deletions(-) diff --git a/jam-ui/src/components/client/JKSessionRecordingModal.js b/jam-ui/src/components/client/JKSessionRecordingModal.js index 67cc0537f..61101908a 100644 --- a/jam-ui/src/components/client/JKSessionRecordingModal.js +++ b/jam-ui/src/components/client/JKSessionRecordingModal.js @@ -52,50 +52,70 @@ const JKSessionRecordingModal = ({ isOpen, toggle }) => { //On mount get the audio store type from backend and set the radio button accordingly using jamClient.GetAudioRecordingPreference() useEffect(() => { + let ignore = false; + const fetchAudioStoreType = async () => { try { if (jamClient) { const pref = await jamClient.GetAudioRecordingPreference(); - if (AUDIO_STORE_TYPE_MIX_AND_STEMS['backendValues'].includes(pref)) { - setAudioStoreType(AUDIO_STORE_TYPE_MIX_AND_STEMS['key']); - } else if (AUDIO_STORE_TYPE_MIX_ONLY['backendValues'].includes(pref)) { - setAudioStoreType(AUDIO_STORE_TYPE_MIX_ONLY['key']); + if (!ignore) { + if (AUDIO_STORE_TYPE_MIX_AND_STEMS['backendValues'].includes(pref)) { + setAudioStoreType(AUDIO_STORE_TYPE_MIX_AND_STEMS['key']); + } else if (AUDIO_STORE_TYPE_MIX_ONLY['backendValues'].includes(pref)) { + setAudioStoreType(AUDIO_STORE_TYPE_MIX_ONLY['key']); + } } } } catch (error) { - console.error('Error fetching audio store type preference:', error); + if (!ignore) { + console.error('Error fetching audio store type preference:', error); + } } }; - + fetchAudioStoreType(); + + return () => { + ignore = true; + }; }, [jamClient]); // Load available video sources when modal opens useEffect(() => { - if (isOpen && jamClient) { - loadAvailableVideoSources(); - } - }, [isOpen, jamClient]); + let ignore = false; - const loadAvailableVideoSources = async () => { - try { - if (jamClient && jamClient.getOpenVideoSources) { - const openSources = await jamClient.getOpenVideoSources(); - console.log('Available video sources:', openSources); + const loadSources = async () => { + if (isOpen && jamClient) { + try { + if (jamClient.getOpenVideoSources) { + const openSources = await jamClient.getOpenVideoSources(); + if (!ignore) { + console.log('Available video sources:', openSources); - // Map backend sources to frontend options - const sources = []; - if (openSources?.webcam1) sources.push(1); // WebCamRecordActive - if (openSources?.webcam2) sources.push(3); // WebCam2RecordActive - if (openSources?.screen_capture) sources.push(4); // DesktopRecordActive - if (openSources?.session_video) sources.push(2); // ScreenRecordActive + // Map backend sources to frontend options + const sources = []; + if (openSources?.webcam1) sources.push(1); // WebCamRecordActive + if (openSources?.webcam2) sources.push(3); // WebCam2RecordActive + if (openSources?.screen_capture) sources.push(4); // DesktopRecordActive + if (openSources?.session_video) sources.push(2); // ScreenRecordActive - setAvailableVideoSources(sources); + setAvailableVideoSources(sources); + } + } + } catch (error) { + if (!ignore) { + console.error('Error loading video sources:', error); + } + } } - } catch (error) { - console.error('Error loading video sources:', error); - } - }; + }; + + loadSources(); + + return () => { + ignore = true; + }; + }, [isOpen, jamClient]); const handleStartStopRecording = async () => { setIsLoading(true);