Add error handling and fallbacks for API failures
- Add try-catch blocks to all page components - Provide empty data fallbacks when API calls fail - Use optional chaining for safer property access - Log errors for debugging Fixes 'Cannot read properties of undefined' errors. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -29,29 +29,43 @@ export default async function ComparePage({ searchParams }: ComparePageProps) {
|
|||||||
const urns = urnsParam?.split(',').map(Number).filter(Boolean) || [];
|
const urns = urnsParam?.split(',').map(Number).filter(Boolean) || [];
|
||||||
const selectedMetric = metricParam || 'rwm_expected_pct';
|
const selectedMetric = metricParam || 'rwm_expected_pct';
|
||||||
|
|
||||||
// Fetch comparison data if URNs provided
|
try {
|
||||||
let comparisonData = null;
|
// Fetch comparison data if URNs provided
|
||||||
if (urns.length > 0) {
|
let comparisonData = null;
|
||||||
try {
|
if (urns.length > 0) {
|
||||||
const response = await fetchComparison(urnsParam!);
|
try {
|
||||||
comparisonData = response.comparison;
|
const response = await fetchComparison(urnsParam!);
|
||||||
} catch (error) {
|
comparisonData = response.comparison;
|
||||||
console.error('Failed to fetch comparison:', error);
|
} catch (error) {
|
||||||
|
console.error('Failed to fetch comparison:', error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fetch available metrics
|
||||||
|
const metricsResponse = await fetchMetrics();
|
||||||
|
|
||||||
|
// Convert metrics object to array
|
||||||
|
const metricsArray = Object.values(metricsResponse?.metrics || {});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ComparisonView
|
||||||
|
initialData={comparisonData}
|
||||||
|
initialUrns={urns}
|
||||||
|
metrics={metricsArray}
|
||||||
|
selectedMetric={selectedMetric}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching data for compare page:', error);
|
||||||
|
|
||||||
|
// Return error state with empty metrics
|
||||||
|
return (
|
||||||
|
<ComparisonView
|
||||||
|
initialData={null}
|
||||||
|
initialUrns={urns}
|
||||||
|
metrics={[]}
|
||||||
|
selectedMetric={selectedMetric}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch available metrics
|
|
||||||
const metricsResponse = await fetchMetrics();
|
|
||||||
|
|
||||||
// Convert metrics object to array
|
|
||||||
const metricsArray = Object.values(metricsResponse.metrics);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ComparisonView
|
|
||||||
initialData={comparisonData}
|
|
||||||
initialUrns={urns}
|
|
||||||
metrics={metricsArray}
|
|
||||||
selectedMetric={selectedMetric}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,24 +30,36 @@ export default async function HomePage({ searchParams }: HomePageProps) {
|
|||||||
const page = parseInt(searchParams.page || '1');
|
const page = parseInt(searchParams.page || '1');
|
||||||
const radius = searchParams.radius ? parseInt(searchParams.radius) : undefined;
|
const radius = searchParams.radius ? parseInt(searchParams.radius) : undefined;
|
||||||
|
|
||||||
// Fetch data on server
|
// Fetch data on server with error handling
|
||||||
const [schoolsData, filtersData] = await Promise.all([
|
try {
|
||||||
fetchSchools({
|
const [schoolsData, filtersData] = await Promise.all([
|
||||||
search: searchParams.search,
|
fetchSchools({
|
||||||
local_authority: searchParams.local_authority,
|
search: searchParams.search,
|
||||||
school_type: searchParams.school_type,
|
local_authority: searchParams.local_authority,
|
||||||
postcode: searchParams.postcode,
|
school_type: searchParams.school_type,
|
||||||
radius,
|
postcode: searchParams.postcode,
|
||||||
page,
|
radius,
|
||||||
page_size: 50,
|
page,
|
||||||
}),
|
page_size: 50,
|
||||||
fetchFilters(),
|
}),
|
||||||
]);
|
fetchFilters(),
|
||||||
|
]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HomeView
|
<HomeView
|
||||||
initialSchools={schoolsData}
|
initialSchools={schoolsData}
|
||||||
filters={filtersData.filters}
|
filters={filtersData?.filters || { local_authorities: [], school_types: [], years: [] }}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching data for home page:', error);
|
||||||
|
|
||||||
|
// Return error state with empty data
|
||||||
|
return (
|
||||||
|
<HomeView
|
||||||
|
initialSchools={{ schools: [], pagination: { page: 1, page_size: 50, total: 0, pages: 0 } }}
|
||||||
|
filters={{ local_authorities: [], school_types: [], years: [] }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,29 +30,45 @@ export default async function RankingsPage({ searchParams }: RankingsPageProps)
|
|||||||
const metric = metricParam || 'rwm_expected_pct';
|
const metric = metricParam || 'rwm_expected_pct';
|
||||||
const year = yearParam ? parseInt(yearParam) : undefined;
|
const year = yearParam ? parseInt(yearParam) : undefined;
|
||||||
|
|
||||||
// Fetch rankings data
|
// Fetch rankings data with error handling
|
||||||
const [rankingsResponse, filtersResponse, metricsResponse] = await Promise.all([
|
try {
|
||||||
fetchRankings({
|
const [rankingsResponse, filtersResponse, metricsResponse] = await Promise.all([
|
||||||
metric,
|
fetchRankings({
|
||||||
local_authority,
|
metric,
|
||||||
year,
|
local_authority,
|
||||||
limit: 100,
|
year,
|
||||||
}),
|
limit: 100,
|
||||||
fetchFilters(),
|
}),
|
||||||
fetchMetrics(),
|
fetchFilters(),
|
||||||
]);
|
fetchMetrics(),
|
||||||
|
]);
|
||||||
|
|
||||||
// Convert metrics object to array
|
// Convert metrics object to array
|
||||||
const metricsArray = Object.values(metricsResponse.metrics);
|
const metricsArray = Object.values(metricsResponse?.metrics || {});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RankingsView
|
<RankingsView
|
||||||
rankings={rankingsResponse.rankings}
|
rankings={rankingsResponse?.rankings || []}
|
||||||
filters={filtersResponse.filters}
|
filters={filtersResponse?.filters || { local_authorities: [], school_types: [], years: [] }}
|
||||||
metrics={metricsArray}
|
metrics={metricsArray}
|
||||||
selectedMetric={metric}
|
selectedMetric={metric}
|
||||||
selectedArea={local_authority}
|
selectedArea={local_authority}
|
||||||
selectedYear={year}
|
selectedYear={year}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching data for rankings page:', error);
|
||||||
|
|
||||||
|
// Return error state with empty data
|
||||||
|
return (
|
||||||
|
<RankingsView
|
||||||
|
rankings={[]}
|
||||||
|
filters={{ local_authorities: [], school_types: [], years: [] }}
|
||||||
|
metrics={[]}
|
||||||
|
selectedMetric={metric}
|
||||||
|
selectedArea={local_authority}
|
||||||
|
selectedYear={year}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user