From 29e9d36f368ffce34e1de0e35625ade14045510d Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 30 Mar 2026 16:19:17 +0000 Subject: [PATCH 1/2] Fix: null-guard API callbacks to prevent TypeError on network failure When _getJSON fails it calls callback(null). Three callers were reading properties on that null value, causing unhandled TypeErrors in production: - ZEEGUU-WEB-BX (80 events, 62 users): App.js getUserPreferences callback reading preferences["audio_exercises"] on null - ZEEGUU-WEB-BP (75 events, 53 users): ProgressContext.js getDailyStreak callback reading data.daily_streak on null - ZEEGUU-WEB-DN: useSelectInterest.js spreading null availableTopics / subscribedTopics into newAllTopics Fix: add early-return guard (if !data/preferences) in each callback, and prevent null from entering state for the topics arrays. Fixes ZEEGUU-WEB-BX, ZEEGUU-WEB-BP, ZEEGUU-WEB-DN https://claude.ai/code/session_01KZumy5REz1to8tCJEmuD5s --- src/App.js | 1 + src/contexts/ProgressContext.js | 1 + src/hooks/useSelectInterest.js | 4 ++-- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/App.js b/src/App.js index c2d032160..2db6545c7 100644 --- a/src/App.js +++ b/src/App.js @@ -263,6 +263,7 @@ function App() { // TODO: Should this be moved to Settings.loadUsrePreferences? api.getUserPreferences((preferences) => { + if (!preferences) return; SessionStorage.setAudioExercisesEnabled( preferences["audio_exercises"] === undefined || preferences["audio_exercises"] === "true", ); diff --git a/src/contexts/ProgressContext.js b/src/contexts/ProgressContext.js index 65099cbda..22173ec23 100644 --- a/src/contexts/ProgressContext.js +++ b/src/contexts/ProgressContext.js @@ -20,6 +20,7 @@ function ProgressProvider({ children }) { useEffect(() => { if (!userDetails?.learned_language) return; api.getDailyStreak((data) => { + if (!data) return; setDaysPracticed(data.daily_streak); }); }, [userDetails?.learned_language]); diff --git a/src/hooks/useSelectInterest.js b/src/hooks/useSelectInterest.js index 39a06d1c7..643ba1904 100644 --- a/src/hooks/useSelectInterest.js +++ b/src/hooks/useSelectInterest.js @@ -10,11 +10,11 @@ export default function useSelectInterest(api) { useEffect(() => { api.getAvailableTopics((data) => { - setAvailableTopics(data); + if (data) setAvailableTopics(data); }); api.getSubscribedTopics((data) => { - setSubscribedTopics(data); + if (data) setSubscribedTopics(data); }); //custom interest filters From b4f80044ea80b29190024e750a7722c0cdfbe98c Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 30 Mar 2026 16:20:17 +0000 Subject: [PATCH 2/2] Refactor: null-guard remaining callback and simplify isSubscribed (boy scout rule) - Guard getSubscribedSearchers callback against null for consistency with the other two topic callbacks fixed in the previous commit - Simplify isSubscribed: replace .map().includes() + ternary with .some() https://claude.ai/code/session_01KZumy5REz1to8tCJEmuD5s --- src/hooks/useSelectInterest.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/hooks/useSelectInterest.js b/src/hooks/useSelectInterest.js index 643ba1904..d7e7c21d6 100644 --- a/src/hooks/useSelectInterest.js +++ b/src/hooks/useSelectInterest.js @@ -19,7 +19,7 @@ export default function useSelectInterest(api) { //custom interest filters api.getSubscribedSearchers((data) => { - setSubscribedSearches(data); + if (data) setSubscribedSearches(data); }); }, [api]); @@ -68,11 +68,7 @@ export default function useSelectInterest(api) { } function isSubscribed(topic) { - return subscribedTopics - .map((subscribedTopic) => subscribedTopic.id) - .includes(topic.id) - ? true - : false; + return subscribedTopics.some((t) => t.id === topic.id); } function subscribeToEmail(search) {