fix: Prevent frontend TypeError from undefined array access

Fix undefined variable crashes when accessing property 'length' on undefined:
- "can't access property 'length', e is undefined"

CHANGES:
1. Election detail page ([id]/page.tsx):
   - Ensure candidates array exists when fetching election data
   - Default to empty array if API returns undefined candidates

2. Active elections list page (active/page.tsx):
   - Validate API response is an array before processing
   - Ensure each election has candidates array with fallback

3. Blockchain visualizer (blockchain-visualizer.tsx):
   - Add optional chaining check before accessing data.blocks
   - Prevent crashes when data prop is undefined

All changes follow defensive programming practices:
- No more direct property access without null checks
- Array fallbacks ensure predictable behavior
- Optional chaining used consistently

This fixes the error that occurred when navigating to election pages.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Alexis Bruneteau 2025-11-07 19:06:34 +01:00
parent b1103a420a
commit 1c5851d053
3 changed files with 14 additions and 4 deletions

View File

@ -52,7 +52,12 @@ export default function VoteDetailPage() {
} }
const data = await response.json() const data = await response.json()
setElection(data) // Ensure candidates array exists, default to empty array if undefined
const election = {
...data,
candidates: data.candidates || []
}
setElection(election)
} catch (err) { } catch (err) {
const message = err instanceof Error ? err.message : "Erreur lors du chargement" const message = err instanceof Error ? err.message : "Erreur lors du chargement"
setError(message) setError(message)

View File

@ -39,7 +39,12 @@ export default function ActiveVotesPage() {
} }
const data = await response.json() const data = await response.json()
setElections(data || []) // Ensure elections is an array and each has candidates
const elections = Array.isArray(data) ? data.map(e => ({
...e,
candidates: e.candidates || []
})) : []
setElections(elections)
} catch (err) { } catch (err) {
const message = err instanceof Error ? err.message : "Erreur lors du chargement" const message = err instanceof Error ? err.message : "Erreur lors du chargement"
setError(message) setError(message)

View File

@ -54,14 +54,14 @@ export function BlockchainVisualizer({
// Animate blocks on load // Animate blocks on load
useEffect(() => { useEffect(() => {
if (data.blocks.length > 0) { if (data?.blocks && data.blocks.length > 0) {
data.blocks.forEach((_, index) => { data.blocks.forEach((_, index) => {
setTimeout(() => { setTimeout(() => {
setAnimatingBlocks((prev) => [...prev, index]) setAnimatingBlocks((prev) => [...prev, index])
}, index * 100) }, index * 100)
}) })
} }
}, [data.blocks]) }, [data?.blocks])
const toggleBlockExpand = (index: number) => { const toggleBlockExpand = (index: number) => {
setExpandedBlocks((prev) => setExpandedBlocks((prev) =>