mirror of
https://github.com/Dimillian/Skills.git
synced 2026-04-26 14:47:48 +00:00
Hullo @dimillian 👋 I ran your skills through `tessl skill review` at work and found some targeted improvements. Here's the before/after: | Skill | Before | After | Change | |-------|--------|-------|--------| | swiftui-ui-patterns | 81% | 100% | +19% | | github | 85% | 100% | +15% | | macos-spm-app-packaging | 86% | 100% | +14% | | react-component-performance | 86% | 100% | +14% | | swift-concurrency-expert | 88% | 100% | +12% | | app-store-changelog | 93% | 100% | +7% | | ios-debugger-agent | 94% | 100% | +6% | | swiftui-view-refactor | 93% | 95% | +2% | | swiftui-liquid-glass | 100% | 100% | — | | swiftui-performance-audit | 100% | 100% | — | <details> <summary>Changes made</summary> **swiftui-ui-patterns** — Expanded description with additional trigger terms (VStack/HStack, @State, @Binding, navigation hierarchies, custom view modifiers). Added explicit build validation checkpoints and error recovery guidance to the workflow steps. **github** — Added explicit "Use when..." clause with natural trigger terms (check CI status, create PR, list issues). Added a structured "Debugging a CI Failure" numbered workflow organizing existing commands into a clear investigation sequence. **macos-spm-app-packaging** — Added a minimum end-to-end example (bootstrap to running app). Added validation checkpoints after packaging, signing, and notarization with specific verification commands (codesign, spctl, stapler). Added a common notarization failures troubleshooting table. **react-component-performance** — Added three concrete before/after code examples (isolate ticking state, stabilize callbacks with useCallback + memo, derived data with useMemo). Expanded profiling validation with explicit React DevTools Profiler steps. **swift-concurrency-expert** — Expanded description with concrete actions (adding Sendable conformance, @MainActor annotations, resolving actor isolation warnings). Added verification step to workflow. Added three before/after Swift code examples covering @MainActor, protocol conformance isolation, and @concurrent. **app-store-changelog** — Added commit-to-bullet transformation examples showing how raw commits map to user-facing App Store bullets, plus examples of internal-only commits that get dropped. Added a complete example "What's New" output block. **ios-debugger-agent** — Added build failure handling and post-launch verification checkpoints to the core workflow (verify app launched via describe_ui or screenshot before proceeding to UI interaction). **swiftui-view-refactor** — Tightened prose in sections 3, 3b, and large-view handling. Removed a redundant example. Converted workflow list to clean numbered format. </details> Honest disclosure — I work at @tesslio where we build tooling around skills like these. Not a pitch - just saw room for improvement and wanted to contribute. If you want to run reviews, evals and optimizations yourself, just `npm install @tessl/cli` then run `tessl skill review path/to/your/SKILL.md`, and click here (https://tessl.io/registry/skills/submit) to find out more. Thanks in advance 🙏
127 lines
4.6 KiB
Markdown
127 lines
4.6 KiB
Markdown
---
|
||
name: react-component-performance
|
||
description: Analyze and optimize React component performance issues (slow renders, re-render thrash, laggy lists, expensive computations). Use when asked to profile or improve a React component, reduce re-renders, or speed up UI updates in React apps.
|
||
---
|
||
|
||
# React Component Performance
|
||
|
||
## Overview
|
||
|
||
Identify render hotspots, isolate expensive updates, and apply targeted optimizations without changing UI behavior.
|
||
|
||
## Workflow
|
||
|
||
1. Reproduce or describe the slowdown.
|
||
2. Identify what triggers re-renders (state updates, props churn, effects).
|
||
3. Isolate fast-changing state from heavy subtrees.
|
||
4. Stabilize props and handlers; memoize where it pays off.
|
||
5. Reduce expensive work (computation, DOM size, list length).
|
||
6. **Validate**: open React DevTools Profiler → record the interaction → inspect the Flamegraph for components rendering longer than ~16 ms → compare against a pre-optimization baseline recording.
|
||
|
||
## Checklist
|
||
|
||
- Measure: use React DevTools Profiler or log renders; capture baseline.
|
||
- Find churn: identify state updated on a timer, scroll, input, or animation.
|
||
- Split: move ticking state into a child; keep heavy lists static.
|
||
- Memoize: wrap leaf rows with `memo` only when props are stable.
|
||
- Stabilize props: use `useCallback`/`useMemo` for handlers and derived values.
|
||
- Avoid derived work in render: precompute, or compute inside memoized helpers.
|
||
- Control list size: window/virtualize long lists; avoid rendering hidden items.
|
||
- Keys: ensure stable keys; avoid index when order can change.
|
||
- Effects: verify dependency arrays; avoid effects that re-run on every render.
|
||
- Style/layout: watch for expensive layout thrash or large Markdown/diff renders.
|
||
|
||
## Optimization Patterns
|
||
|
||
### Isolate ticking state
|
||
|
||
Move a timer or animation counter into a child so the parent list never re-renders on each tick.
|
||
|
||
```tsx
|
||
// ❌ Before – entire parent (and list) re-renders every second
|
||
function Dashboard({ items }: { items: Item[] }) {
|
||
const [tick, setTick] = useState(0);
|
||
useEffect(() => {
|
||
const id = setInterval(() => setTick(t => t + 1), 1000);
|
||
return () => clearInterval(id);
|
||
}, []);
|
||
return (
|
||
<>
|
||
<Clock tick={tick} />
|
||
<ExpensiveList items={items} /> {/* re-renders every second */}
|
||
</>
|
||
);
|
||
}
|
||
|
||
// ✅ After – only <Clock> re-renders; list is untouched
|
||
function Clock() {
|
||
const [tick, setTick] = useState(0);
|
||
useEffect(() => {
|
||
const id = setInterval(() => setTick(t => t + 1), 1000);
|
||
return () => clearInterval(id);
|
||
}, []);
|
||
return <span>{tick}s</span>;
|
||
}
|
||
|
||
function Dashboard({ items }: { items: Item[] }) {
|
||
return (
|
||
<>
|
||
<Clock />
|
||
<ExpensiveList items={items} />
|
||
</>
|
||
);
|
||
}
|
||
```
|
||
|
||
### Stabilize callbacks with `useCallback` + `memo`
|
||
|
||
```tsx
|
||
// ❌ Before – new handler reference on every render busts Row memo
|
||
function List({ items }: { items: Item[] }) {
|
||
const handleClick = (id: string) => console.log(id); // new ref each render
|
||
return items.map(item => <Row key={item.id} item={item} onClick={handleClick} />);
|
||
}
|
||
|
||
// ✅ After – stable handler; Row only re-renders when its own item changes
|
||
const Row = memo(({ item, onClick }: RowProps) => (
|
||
<li onClick={() => onClick(item.id)}>{item.name}</li>
|
||
));
|
||
|
||
function List({ items }: { items: Item[] }) {
|
||
const handleClick = useCallback((id: string) => console.log(id), []);
|
||
return items.map(item => <Row key={item.id} item={item} onClick={handleClick} />);
|
||
}
|
||
```
|
||
|
||
### Prefer derived data outside render
|
||
|
||
```tsx
|
||
// ❌ Before – recomputes on every render
|
||
function Summary({ orders }: { orders: Order[] }) {
|
||
const total = orders.reduce((sum, o) => sum + o.amount, 0); // runs every render
|
||
return <p>Total: {total}</p>;
|
||
}
|
||
|
||
// ✅ After – recomputes only when orders changes
|
||
function Summary({ orders }: { orders: Order[] }) {
|
||
const total = useMemo(() => orders.reduce((sum, o) => sum + o.amount, 0), [orders]);
|
||
return <p>Total: {total}</p>;
|
||
}
|
||
```
|
||
|
||
### Additional patterns
|
||
|
||
- **Split rows**: extract list rows into memoized components with narrow props.
|
||
- **Defer heavy rendering**: lazy-render or collapse expensive content until expanded.
|
||
|
||
## Profiling Validation Steps
|
||
|
||
1. Open **React DevTools → Profiler** tab.
|
||
2. Click **Record**, perform the slow interaction, then **Stop**.
|
||
3. Switch to **Flamegraph** view; any bar labeled with a component and time > ~16 ms is a candidate.
|
||
4. Use **Ranked chart** to sort by self render time and target the top offenders.
|
||
5. Apply one optimization at a time, re-record, and compare render counts and durations against the baseline.
|
||
|
||
## Example Reference
|
||
|
||
Load `references/examples.md` when the user wants a concrete refactor example.
|