Skip to content

How to Fix React Performance Issues with Vercel's React Best Practices Skill

I was reviewing my React components and kept finding the same issues: missing dependencies in useEffect, components re-rendering unnecessarily, and hooks being used incorrectly. The code worked, but it had technical debt piling up.

Then I discovered Vercel’s React best practices skill. Now Claude automatically catches these issues before they become problems.

The Problem: React Code Works But Isn’t Correct

React makes it easy to write code that runs. But writing code that follows best practices is harder. I kept making these mistakes:

  • Forgetting dependencies in useEffect hooks
  • Creating components that re-render on every parent update
  • Using useState for values that never change
  • Not memoizing expensive calculations

Here’s what my typical workflow looked like:

My old workflow
1. Write React component
2. Test it - works fine
3. Ship to production
4. Later: discover performance issues
5. Debug and find the root cause
6. Fix and deploy again

Each issue took hours to track down. I wanted Claude to catch these problems immediately, not after deployment.

What Is the Vercel React Best Practices Skill?

The vercel-react-best-practices skill is an official Vercel skill with 109.8K installs. It gives Claude Code deep knowledge of React performance optimization, hooks rules, and component design patterns.

The difference is clear:

Without the skill:
Claude: "Your component looks good, it should work"
Result: Functional code with hidden issues
With the skill:
Claude: "Your useEffect is missing 'userId' in dependencies"
Result: Correct code that follows React best practices

Installation: One Command

Install the skill globally:

Terminal
npx skills add vercel-labs/agent-skills@vercel-react-best-practices -y -g

The -g flag is essential. Without it, the skill installs locally and Claude Code won’t find it.

Verify the installation:

Terminal
npx skills list -g

You should see:

Installed Skills (global):
1. vercel-react-best-practices
Description: React code standards and performance optimization
Location: ~/.claude/skills/vercel-react-best-practices
Status: Active

Restart Claude Code to activate the skill.

My First Attempt: Missing Dependencies

I tested the skill on a component I wrote last week:

UserDashboard.jsx
function UserDashboard({ userId }) {
const [data, setData] = useState(null);
useEffect(() => {
fetchUserData(userId).then(setData);
}, []); // Problem: missing userId dependency
return <div>{data?.name}</div>;
}

I asked Claude to review it. Here’s what I got:

Claude's feedback
[vercel-react-best-practices skill activated]
Issue found in UserDashboard.jsx:
The useEffect hook is missing 'userId' in its dependency array.
This means the effect won't re-run when userId changes.
Current:
useEffect(() => {
fetchUserData(userId).then(setData);
}, []);
Recommended:
useEffect(() => {
fetchUserData(userId).then(setData);
}, [userId]);
Why this matters:
If the userId prop changes, the dashboard won't fetch new data.
This creates a stale data bug that's hard to track down.

The skill caught the issue immediately. I didn’t have to remember to check dependencies.

The Trial-and-Error Process

I spent time testing the skill with different React patterns. Here’s what I learned.

Mistake 1: Unnecessary Re-renders

I wrote a component that re-rendered constantly:

ExpensiveList.jsx
function ExpensiveList({ items, onItemClick }) {
// This function is recreated on every render
const handleClick = (id) => {
onItemClick(id);
};
return (
<ul>
{items.map(item => (
<li key={item.id} onClick={() => handleClick(item.id)}>
{item.name}
</li>
))}
</ul>
);
}

Claude with the skill pointed out:

Claude's analysis
Performance issue in ExpensiveList.jsx:
The handleClick function is recreated on every render.
This causes all list items to re-render unnecessarily.
Solutions:
1. Use useCallback for the handler
2. Or define it outside if it doesn't need props
Option 1 - useCallback:
const handleClick = useCallback((id) => {
onItemClick(id);
}, [onItemClick]);
Option 2 - Inline function in parent:
Pass a stable reference from parent with useCallback

Mistake 2: State for Constants

I used useState for a value that never changed:

ConfigPanel.jsx
function ConfigPanel({ config }) {
// Wrong: state for a computed value
const [formattedConfig, setFormattedConfig] = useState(() => {
return JSON.stringify(config, null, 2);
});
return <pre>{formattedConfig}</pre>;
}

Claude’s feedback:

Correction
Issue in ConfigPanel.jsx:
Using useState for a value that depends only on props.
This adds unnecessary state management overhead.
Better approach - use useMemo:
const formattedConfig = useMemo(() => {
return JSON.stringify(config, null, 2);
}, [config]);
Or even simpler - compute directly:
const formattedConfig = JSON.stringify(config, null, 2);
The value only needs to change when config changes.
State is for values that change independently.

Mistake 3: Incorrect Hook Order

I conditionally called a hook:

ConditionalHook.jsx
function ConditionalHook({ user, showDetails }) {
if (showDetails) {
const [details, setDetails] = useState(null);
}
// Hook called after conditional return
useEffect(() => {
loadDetails(user.id);
}, [user.id]);
return <div>{user.name}</div>;
}

Claude caught this immediately:

React rules violation
CRITICAL: Hooks rule violation in ConditionalHook.jsx
React hooks must be called in the same order on every render.
Conditional hooks break React's state management.
Problem: The useState inside the if statement may or may not run.
This causes React to lose track of hook state.
Fix: Always call hooks at the top level:
function ConditionalHook({ user, showDetails }) {
const [details, setDetails] = useState(null);
useEffect(() => {
loadDetails(user.id);
}, [user.id]);
if (!showDetails) {
return <div>{user.name}</div>;
}
return (
<div>
{user.name}
<Details data={details} />
</div>
);
}

What Works: Asking for Reviews

The skill shines when I explicitly ask for React best practices reviews:

Effective prompt
"Review this React component for:
- Missing useEffect dependencies
- Unnecessary re-renders
- Hook rule violations
- Performance optimizations"

The skill provides structured feedback with specific line numbers and fixes.

Common Patterns the Skill Catches

I tested the skill extensively. Here are the issues it consistently catches:

1. Missing Dependencies

Before fix
useEffect(() => {
fetchUser(id);
}, []);
After skill suggestion
useEffect(() => {
fetchUser(id);
}, [id]);

2. Object Dependencies in useEffect

Problem code
useEffect(() => {
fetchData(options);
}, [options]); // options is recreated every render

The skill suggests:

Skill feedback
The 'options' object is recreated on every render.
This causes the effect to run on every render.
Solutions:
1. Memoize the object: useMemo(() => options, [dep1, dep2])
2. Use individual primitive values as dependencies
3. Disable the eslint rule if truly intentional

3. Missing useCallback for Props

Parent.jsx
function Parent() {
const handleClick = () => { // New function every render
doSomething();
};
return <Child onClick={handleClick} />;
}
After fix
function Parent() {
const handleClick = useCallback(() => {
doSomething();
}, []); // Stable reference
return <Child onClick={handleClick} />;
}

4. Expensive Calculations Without Memoization

SlowList.jsx
function SlowList({ items }) {
// Runs on every render
const sorted = items.sort((a, b) => a.name.localeCompare(b.name));
return <List data={sorted} />;
}
Optimized version
function SlowList({ items }) {
const sorted = useMemo(() => {
return items.sort((a, b) => a.name.localeCompare(b.name));
}, [items]);
return <List data={sorted} />;
}

Comparison: With vs Without the Skill

AspectWithout SkillWith Skill
Dependency warningsManual review requiredAutomatic detection
Re-render issuesFound in productionCaught during development
Hook violationsRuntime errorsImmediate feedback
Performance tipsGeneric adviceSpecific to your code
Learning curveTrial and errorGuided improvements
Time to fix issuesHours after deploymentMinutes during coding

How I Integrated It Into My Workflow

I added this to my CLAUDE.md:

CLAUDE.md
## React Development
This project uses React with strict best practices.
Always check for:
- Missing useEffect dependencies
- Unnecessary re-renders
- Memoization opportunities
- Hook rule violations
Use the vercel-react-best-practices skill for all React code reviews.

Now my workflow is:

New workflow
1. Write React component
2. Ask Claude to review for React best practices
3. Apply suggested fixes
4. Ship with confidence

Common Mistakes to Avoid

1. Ignoring the Suggestions

The skill gives specific feedback. Ignoring it leads to the same bugs you had before.

2. Over-optimizing

Not every suggestion needs immediate action. The skill flags everything, but some issues are low priority:

Skill warning
This component could benefit from React.memo
Your decision:
- Is this a hot path? Consider memo.
- Is it rendered once? Skip optimization.

3. Not Restarting Claude Code

After installing, restart Claude Code. The skill won’t activate until you do.

4. Installing Too Many React Skills

I tried installing multiple React skills. They conflicted and gave inconsistent advice. Stick with one authoritative source: Vercel’s skill.

When the Skill Falls Short

The skill is helpful but has limits:

Complex State Machines: For complex state logic with many transitions, the skill suggests simplification but can’t fully understand the business requirements.

Legacy Code Refactors: When refactoring old class components to hooks, the skill helps with syntax but may miss context about why the old code exists.

Application-Specific Patterns: The skill knows React best practices, not your team’s specific conventions or architectural decisions.

Summary

Vercel’s React best practices skill transformed my React development workflow. Instead of shipping code with hidden issues, I now get immediate feedback on:

  • Missing useEffect dependencies
  • Unnecessary re-renders
  • Hook rule violations
  • Memoization opportunities

Key takeaways:

  1. Install globally: Use -g flag so Claude Code can find the skill
  2. Ask for reviews: Explicitly request React best practices checks
  3. Trust but verify: The skill is right most of the time, but understand why
  4. Integrate into workflow: Make code review with the skill a standard step

For React developers using Claude Code, this skill is essential. It catches issues that would otherwise become production bugs or performance problems. The 109.8K installs prove many developers trust Vercel’s expertise.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments