Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,7 @@
## $(date +%Y-%m-%d) - Avoiding redundant normalization computations
**Learning:** Functions like `normalizeText` which rely on `.normalize('NFD')` and regular expressions `.replace(/[\u0300-\u036f]/g, '')` are computationally expensive, and in large lists or during data mapping they can be called thousands of times on the same few strings (e.g., destinations like 'AUBIÈRE' or 'GERZAT'). This redundant computation causes CPU bottlenecks and garbage collection overhead.
**Action:** Use a simple module-level `Map` to cache the results of computationally expensive string operations like `normalizeText`. For fields like transit destinations, the number of unique strings is very small, making a cache highly memory-efficient while significantly reducing CPU work.

## 2026-07-28 - String Split and Map Anti-Pattern in React Render Loop
**Learning:** Found an anti-pattern in `SplitFlapDisplay.tsx` where `text.split('').map(...)` was used inside a highly reused memoized component's render function. This causes the JavaScript engine to allocate an intermediate array of single-character strings on every render, leading to unnecessary memory churn and garbage collection pressure, particularly when rendering many list items or table rows.
**Action:** Replace `text.split('').map(...)` with a `for` loop (e.g. `for (let idx = 0; idx < text.length; idx++)`) and directly push the mapped JSX elements to a pre-allocated array. This avoids the intermediate string array allocation completely.
36 changes: 23 additions & 13 deletions src/components/SplitFlapDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,32 @@ interface SplitFlapDisplayProps {
color?: string;
}

// ⚑ Bolt: Removed text.split('').map() which creates an intermediate array of strings
// on every render. Replaced with a single-pass loop over the string characters to reduce
// memory allocation and garbage collection overhead, especially important as this component
// is rendered heavily in lists and tables.
const SplitFlapDisplay = memo(function SplitFlapDisplay({ text, size = 'xl', color = 'text-yellow-500' }: SplitFlapDisplayProps) {
const chars = text.split('');
const chars = [];
for (let idx = 0; idx < text.length; idx++) {
// eslint-disable-next-line security/detect-object-injection
const char = text[idx];
chars.push(
<span
key={`${idx}-${char}`}
className={`split-flap-char ${char === ':' ? 'colon' : ''
} ${char === ' ' ? 'space' : ''
} ${char === '-' ? 'dash' : ''
} ${char === "'" ? 'apos' : ''
}`}
>
{char}
</span>
);
}

return (
<div className={`split-flap-container split-flap-${size} ${color} flex`}>
{chars.map((char, idx) => (
<span
key={`${idx}-${char}`}
className={`split-flap-char ${char === ':' ? 'colon' : ''
} ${char === ' ' ? 'space' : ''
} ${char === '-' ? 'dash' : ''
} ${char === "'" ? 'apos' : ''
}`}
>
{char}
</span>
))}
{chars}
</div>
);
});
Expand Down
Loading