mirror of
https://github.com/Dimillian/Skills.git
synced 2026-03-25 08:55:54 +00:00
chore: update skills
This commit is contained in:
parent
9826f404c3
commit
527d60383c
3 changed files with 179 additions and 0 deletions
47
github/SKILL.md
Normal file
47
github/SKILL.md
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
---
|
||||
name: github
|
||||
description: "Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries."
|
||||
---
|
||||
|
||||
# GitHub Skill
|
||||
|
||||
Use the `gh` CLI to interact with GitHub. Always specify `--repo owner/repo` when not in a git directory, or use URLs directly.
|
||||
|
||||
## Pull Requests
|
||||
|
||||
Check CI status on a PR:
|
||||
```bash
|
||||
gh pr checks 55 --repo owner/repo
|
||||
```
|
||||
|
||||
List recent workflow runs:
|
||||
```bash
|
||||
gh run list --repo owner/repo --limit 10
|
||||
```
|
||||
|
||||
View a run and see which steps failed:
|
||||
```bash
|
||||
gh run view <run-id> --repo owner/repo
|
||||
```
|
||||
|
||||
View logs for failed steps only:
|
||||
```bash
|
||||
gh run view <run-id> --repo owner/repo --log-failed
|
||||
```
|
||||
|
||||
## API for Advanced Queries
|
||||
|
||||
The `gh api` command is useful for accessing data not available through other subcommands.
|
||||
|
||||
Get PR with specific fields:
|
||||
```bash
|
||||
gh api repos/owner/repo/pulls/55 --jq '.title, .state, .user.login'
|
||||
```
|
||||
|
||||
## JSON Output
|
||||
|
||||
Most commands support `--json` for structured output. You can use `--jq` to filter:
|
||||
|
||||
```bash
|
||||
gh issue list --repo owner/repo --json number,title --jq '.[] | "\(.number): \(.title)"'
|
||||
```
|
||||
44
react-component-performance/SKILL.md
Normal file
44
react-component-performance/SKILL.md
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
---
|
||||
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 with profiling; avoid speculative changes.
|
||||
|
||||
## 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/animation into a child component so the parent list does not re-render every tick.
|
||||
- **Stabilize callbacks**: prefer `useCallback` for handlers passed to memoized rows.
|
||||
- **Split rows**: extract list rows into memoized components with narrow props.
|
||||
- **Defer heavy rendering**: lazy-render or collapse expensive content until expanded.
|
||||
- **Prefer derived data outside render**: compute summaries with `useMemo` or helper functions when inputs are stable.
|
||||
|
||||
## Example Reference
|
||||
|
||||
Load `references/examples.md` when the user wants a concrete refactor example.
|
||||
88
react-component-performance/references/examples.md
Normal file
88
react-component-performance/references/examples.md
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
# Examples
|
||||
|
||||
## Isolate a ticking timer from a long list
|
||||
|
||||
**Scenario:** A message list re-renders every second because a timer (`elapsedMs`) lives in the parent component. This causes visible jank on large lists.
|
||||
|
||||
**Goal:** Keep UI identical but limit re-renders to the timer area.
|
||||
|
||||
**Before (problematic pattern):**
|
||||
|
||||
```tsx
|
||||
function Messages({ items, isThinking, processingStartedAt }) {
|
||||
const [elapsedMs, setElapsedMs] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isThinking || !processingStartedAt) {
|
||||
setElapsedMs(0);
|
||||
return;
|
||||
}
|
||||
setElapsedMs(Date.now() - processingStartedAt);
|
||||
const interval = window.setInterval(() => {
|
||||
setElapsedMs(Date.now() - processingStartedAt);
|
||||
}, 1000);
|
||||
return () => window.clearInterval(interval);
|
||||
}, [isThinking, processingStartedAt]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
{items.map((item) => (
|
||||
<MessageRow key={item.id} item={item} />
|
||||
))}
|
||||
<div>{formatDurationMs(elapsedMs)}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
**After (isolated ticking state):**
|
||||
|
||||
```tsx
|
||||
type WorkingIndicatorProps = {
|
||||
isThinking: boolean;
|
||||
processingStartedAt?: number | null;
|
||||
};
|
||||
|
||||
const WorkingIndicator = memo(function WorkingIndicator({
|
||||
isThinking,
|
||||
processingStartedAt = null,
|
||||
}: WorkingIndicatorProps) {
|
||||
const [elapsedMs, setElapsedMs] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isThinking || !processingStartedAt) {
|
||||
setElapsedMs(0);
|
||||
return;
|
||||
}
|
||||
setElapsedMs(Date.now() - processingStartedAt);
|
||||
const interval = window.setInterval(() => {
|
||||
setElapsedMs(Date.now() - processingStartedAt);
|
||||
}, 1000);
|
||||
return () => window.clearInterval(interval);
|
||||
}, [isThinking, processingStartedAt]);
|
||||
|
||||
return <div>{formatDurationMs(elapsedMs)}</div>;
|
||||
});
|
||||
|
||||
function Messages({ items, isThinking, processingStartedAt }) {
|
||||
return (
|
||||
<div>
|
||||
{items.map((item) => (
|
||||
<MessageRow key={item.id} item={item} />
|
||||
))}
|
||||
<WorkingIndicator
|
||||
isThinking={isThinking}
|
||||
processingStartedAt={processingStartedAt}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
**Why it helps:** Only the `WorkingIndicator` subtree re-renders every second. The list remains stable unless its props change.
|
||||
|
||||
**Optional follow-ups:**
|
||||
|
||||
- Wrap `MessageRow` in `memo` if props are stable.
|
||||
- Use `useCallback` for handlers passed to rows to avoid re-render churn.
|
||||
- Consider list virtualization if the list is very large.
|
||||
Loading…
Reference in a new issue