-
Notifications
You must be signed in to change notification settings - Fork 38
fix(weather-alerts): resolve iOS screen freeze on navigation #2499
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
a612c8f
d2398f6
0597212
7918928
a465f69
7e80eac
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| import * as Sentry from '@sentry/react-native'; | ||
| import { getWeatherData } from 'expo-app/features/weather/lib/weatherService'; | ||
| import { useAtomValue } from 'jotai'; | ||
| import { useEffect, useState } from 'react'; | ||
|
|
@@ -232,40 +233,63 @@ export function generateAlerts({ | |
| export function useWeatherAlerts() { | ||
| const activeLocation = useAtomValue(activeLocationAtom); | ||
|
|
||
| // Use primitive values as effect dependencies to avoid re-running on new | ||
| // object references emitted by the derived Jotai atom's .find() call. | ||
| const locationId = activeLocation?.id; | ||
| const locationName = activeLocation?.name; | ||
|
|
||
| const [alerts, setAlerts] = useState<WeatherAlert[]>([]); | ||
| const [loading, setLoading] = useState(true); | ||
| const [error, setError] = useState<string | null>(null); | ||
|
|
||
| useEffect(() => { | ||
| if (!activeLocation?.id) { | ||
| if (!locationId) { | ||
| setLoading(false); | ||
| return; | ||
| } | ||
|
|
||
| const locationId = activeLocation.id; | ||
| let cancelled = false; | ||
|
|
||
| async function fetchAlerts() { | ||
| setLoading(true); | ||
| setError(null); | ||
|
|
||
| Sentry.addBreadcrumb({ | ||
| category: 'weather', | ||
| message: 'Fetching weather alerts', | ||
| level: 'info', | ||
| data: { locationId, locationName }, | ||
| }); | ||
|
|
||
| try { | ||
| const data = await getWeatherData(locationId); | ||
| if (cancelled) return; | ||
|
|
||
| const formatted = generateAlerts({ | ||
| // safe-cast: getWeatherData returns WeatherApiForecastResponse; WeatherApiData is a structural subset used only by this alert generator. | ||
| data: data as unknown as WeatherApiData, | ||
| activeLocation, | ||
| activeLocation: { name: locationName }, | ||
| }); | ||
| setAlerts(formatted); | ||
| } catch (err) { | ||
| if (cancelled) return; | ||
| console.error('Weather alerts error:', err); | ||
| setError('Failed to fetch weather alerts'); | ||
| Sentry.captureException(err, { | ||
| tags: { feature: 'weatherAlerts', action: 'fetchAlerts' }, | ||
| extra: { locationId, locationName }, | ||
| }); | ||
| } finally { | ||
| setLoading(false); | ||
| if (!cancelled) setLoading(false); | ||
| } | ||
| } | ||
|
|
||
| fetchAlerts(); | ||
| }, [activeLocation]); | ||
|
|
||
| return () => { | ||
| cancelled = true; | ||
| }; | ||
| }, [locationId, locationName]); | ||
|
|
||
|
Comment on lines
241
to
293
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Verify this hook is using manual server-state management instead of TanStack Query.
fd -a "useWeatherAlert.ts" | xargs -I{} rg -n "useQuery|`@tanstack/react-query`|useEffect\\(|useState\\(|getWeatherData\\(" "{}"Repository: PackRat-AI/PackRat Length of output: 197 🏁 Script executed: #!/bin/bash
set -euo pipefail
# Locate the file and print the relevant section with line numbers
FILE="apps/expo/features/weather/hooks/useWeatherAlert.ts"
if [ ! -f "$FILE" ]; then
echo "Missing: $FILE" >&2
exit 1
fi
echo "=== Imports (first 120 lines) ==="
sed -n '1,120p' "$FILE" | nl -ba
echo "=== Hook implementation (220-320) ==="
sed -n '220,320p' "$FILE" | nl -ba
echo "=== Search within file for react-query usage ==="
rg -n "`@tanstack/react-query`|useQuery|useMutation|useInfiniteQuery" "$FILE" || true
echo "=== Search within file for manual fetch lifecycle ==="
rg -n "useEffect\\(|useState\\(|getWeatherData\\(|cancelled|setLoading\\(|setError\\(" "$FILE"Repository: PackRat-AI/PackRat Length of output: 158 🏁 Script executed: #!/bin/bash
set -euo pipefail
# Locate the file and print the relevant section with line numbers
FILE="apps/expo/features/weather/hooks/useWeatherAlert.ts"
if [ ! -f "$FILE" ]; then
echo "Missing: $FILE" >&2
exit 1
fi
echo "=== Imports (first 120 lines) ==="
sed -n '1,120p' "$FILE" | nl -ba
echo "=== Hook implementation (220-320) ==="
sed -n '220,320p' "$FILE" | nl -ba
echo "=== Search within file for react-query usage ==="
rg -n "`@tanstack/react-query`|useQuery|useMutation|useInfiniteQuery" "$FILE" || true
echo "=== Search within file for manual fetch lifecycle ==="
rg -n "useEffect\\(|useState\\(|getWeatherData\\(|cancelled|setLoading\\(|setError\\(" "$FILE"Repository: PackRat-AI/PackRat Length of output: 158 🏁 Script executed: #!/bin/bash
set -euo pipefail
FILE="apps/expo/features/weather/hooks/useWeatherAlert.ts"
test -f "$FILE" || { echo "Missing: $FILE" >&2; exit 1; }
echo "=== Imports (first 140 lines) ==="
sed -n '1,140p' "$FILE" | cat -n
echo "=== Hook implementation (200-330) ==="
sed -n '200,330p' "$FILE" | cat -n
echo "=== react-query usage in file ==="
rg -n "`@tanstack/react-query`|useQuery|useMutation|useInfiniteQuery" "$FILE" || true
echo "=== manual lifecycle usage in file ==="
rg -n "useEffect\\(|useState\\(|getWeatherData\\(|cancelled|setLoading\\(|setError\\(" "$FILE"Repository: PackRat-AI/PackRat Length of output: 8565 Refactor 🤖 Prompt for AI Agents |
||
| return { | ||
| alerts, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clear stale alerts when location is missing or fetch fails.
The hook can keep showing previous-location alerts when
locationIdbecomes falsy or when a fetch errors.That exposes incorrect alert data to users.
Suggested fix
useEffect(() => { if (!locationId) { + setAlerts([]); + setError(null); setLoading(false); return; } @@ } catch (err) { if (cancelled) return; console.error('Weather alerts error:', err); + setAlerts([]); setError('Failed to fetch weather alerts'); Sentry.captureException(err, { tags: { feature: 'weatherAlerts', action: 'fetchAlerts' }, extra: { locationId, locationName }, });Also applies to: 275-281
🤖 Prompt for AI Agents