From adlc-react-frontend
Bug diagnosis protocol for React applications including reproduce-first workflow, React-specific debugging, and common bug patterns.
npx claudepluginhub sumanpapanaboina1983/adlc-accelerator-kit-pluginsThis skill uses the workspace's default tool permissions.
| Gate | Threshold | Status |
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Guides MCP server integration in Claude Code plugins via .mcp.json or plugin.json configs for stdio, SSE, HTTP types, enabling external services as tools.
| Gate | Threshold | Status |
|---|---|---|
| TypeScript | 0 type errors | REQUIRED |
| Tests | 100% pass (0 failures) | REQUIRED |
| Coverage | ≥ 80% line coverage | REQUIRED |
| ESLint | 0 errors (warnings OK) | REQUIRED |
| Build | must pass | REQUIRED |
⛔ BLOCKING: Bug fix is NOT complete until ALL gates pass.
Before fixing ANY bug, verify Vitest coverage is configured:
grep -l "thresholds" vitest.config.ts
If NOT configured, update vitest.config.ts first (see react-testing skill for full configuration):
// vitest.config.ts - coverage section
coverage: {
provider: 'v8',
reporter: ['text', 'text-summary', 'html', 'lcov'],
thresholds: {
lines: 80,
branches: 70,
functions: 80,
statements: 80,
},
}
┌─────────────────────────────────────────────────────────────┐
│ STEP 0: VERIFY COVERAGE CONFIGURATION │
│ - Check: grep "thresholds" vitest.config.ts │
│ - If missing → Configure coverage thresholds FIRST │
│ - ⛔ Do NOT proceed without coverage configuration │
│ │
│ STEP 1: UNDERSTAND │
│ - Read bug report / error description / Jira ticket │
│ - Identify: EXPECTED behavior vs ACTUAL behavior │
│ - Note: browser, screen size, user actions, console errors │
│ │
│ STEP 2: REPRODUCE │
│ - Write a test that exercises the exact bug scenario │
│ - Run the test → it MUST FAIL │
│ - If it passes → you haven't reproduced the bug yet │
│ - The failing test IS your proof the bug exists │
│ │
│ STEP 3: DIAGNOSE │
│ - Identify component and state involved │
│ - Classify: RENDER / STATE / EVENT / ASYNC / TYPE issue │
│ - Use React DevTools patterns │
│ - Form hypothesis → verify → don't guess │
│ │
│ STEP 4: FIX │
│ - Fix the ROOT CAUSE (not the symptom) │
│ - Minimal change that addresses the actual problem │
│ │
│ STEP 5: VERIFY │
│ - Run reproducing test → must now PASS │
│ - Run FULL test suite → zero regressions │
│ - All existing tests must still pass │
│ │
│ STEP 6: COVERAGE VERIFICATION ⚠️ MANDATORY │
│ - Run: npm test -- --coverage --run │
│ - Check coverage ≥ 80% │
│ - If < 80% → add more tests → repeat │
│ - ⛔ Do NOT mark complete if coverage < 80% │
└─────────────────────────────────────────────────────────────┘
Symptoms:
Diagnosis:
// Add debug output
console.log('Render data:', data);
console.log('Render condition:', shouldShow);
// Check in test
screen.debug(); // prints DOM
// Check if element exists
expect(screen.queryByText('Content')).not.toBeInTheDocument();
Common causes:
Symptoms:
Diagnosis:
// Add state logging
useEffect(() => {
console.log('State changed:', state);
}, [state]);
// Check for stale closures
const handleClick = useCallback(() => {
console.log('Current value:', value); // Is this stale?
}, [value]); // Missing dependency?
Common causes:
Symptoms:
Diagnosis:
// Log event firing
const handleClick = (e) => {
console.log('Click event:', e.target);
console.log('Current target:', e.currentTarget);
};
// Check event propagation
onClick={(e) => {
e.stopPropagation();
handleClick(e);
}}
Common causes:
Symptoms:
Diagnosis:
// Log async flow
useEffect(() => {
console.log('Effect starting fetch');
let cancelled = false;
async function fetchData() {
console.log('Fetch started');
const data = await api.get();
console.log('Fetch completed, cancelled:', cancelled);
if (!cancelled) {
setData(data);
}
}
fetchData();
return () => {
console.log('Cleanup running');
cancelled = true;
};
}, []);
Common causes:
Symptoms:
Diagnosis:
// Check prop types at runtime
console.log('Props received:', typeof value, value);
// Add type guards
if (typeof value !== 'string') {
console.error('Expected string, got:', typeof value);
}
Common causes:
// BUG: count is always 0 in the callback
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
console.log(count); // Always 0!
setCount(count + 1); // Always sets to 1
}, 1000);
return () => clearInterval(interval);
}, []); // Empty deps = stale closure
}
// FIX: Use functional update
useEffect(() => {
const interval = setInterval(() => {
setCount(c => c + 1); // Uses current value
}, 1000);
return () => clearInterval(interval);
}, []);
// BUG: List items don't update correctly
{items.map((item, index) => (
<Item key={index} {...item} /> // index key = bugs!
))}
// FIX: Use stable unique ID
{items.map((item) => (
<Item key={item.id} {...item} /> // stable ID
))}
// BUG: Infinite re-renders
function Component() {
const [data, setData] = useState([]);
useEffect(() => {
setData([...data, newItem]); // data in effect body
}, [data]); // data in deps = infinite loop
}
// FIX: Use functional update
useEffect(() => {
setData(current => [...current, newItem]);
}, [newItem]); // Only depend on newItem
// BUG: Shows wrong user data
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
useEffect(() => {
fetchUser(userId).then(setUser);
// If userId changes fast, old request might resolve after new one
}, [userId]);
}
// FIX: Cancel stale requests
useEffect(() => {
let cancelled = false;
fetchUser(userId).then(user => {
if (!cancelled) setUser(user);
});
return () => { cancelled = true; };
}, [userId]);
// BUG: New function every render, breaks memo
function Parent() {
return <Child onClick={() => doSomething()} />;
}
// FIX: Use useCallback
function Parent() {
const handleClick = useCallback(() => doSomething(), []);
return <Child onClick={handleClick} />;
}
// BUG: Warning about switching from uncontrolled to controlled
function Input() {
const [value, setValue] = useState(); // undefined initially!
return <input value={value} onChange={e => setValue(e.target.value)} />;
}
// FIX: Initialize with empty string
function Input() {
const [value, setValue] = useState(''); // controlled from start
return <input value={value} onChange={e => setValue(e.target.value)} />;
}
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { describe, it, expect, vi } from 'vitest';
describe('BugFix: [bug description]', () => {
it('should [expected behavior] when [condition]', async () => {
// Given - setup that reproduces the bug
const user = userEvent.setup();
// When - the action that triggers the bug
render(<Component />);
await user.click(screen.getByRole('button'));
// Then - the expected behavior (fails before fix)
await waitFor(() => {
expect(screen.getByText('Success')).toBeInTheDocument();
});
});
});
describe('BugFix: Counter shows stale value', () => {
it('should increment correctly when clicked rapidly', async () => {
const user = userEvent.setup();
render(<Counter />);
// Click 5 times rapidly
const button = screen.getByRole('button', { name: /increment/i });
await user.click(button);
await user.click(button);
await user.click(button);
await user.click(button);
await user.click(button);
// Should be 5, not 1 (stale closure would show 1)
expect(screen.getByText('5')).toBeInTheDocument();
});
});
1. Components tab:
- Check component tree
- Inspect props
- Inspect state
- Check hooks values
2. Profiler tab:
- Record renders
- Find unnecessary re-renders
- Check render times
3. Console filtering:
- Filter by "React" for React-specific messages
- Look for warnings about keys, effects, etc.
1. Elements tab:
- Check if element exists in DOM
- Check computed styles
- Check event listeners
2. Console:
- console.log for debugging
- console.trace for call stack
3. Network tab:
- Check API requests
- Verify response data