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