agentsclimarketplace

Dev react perf

Skill christopherlouet/claude-base/.claude/skills/dev-react-perf

React/Next.js performance optimization. Trigger when the user wants to optimize rendering, reduce re-renders, or improve Core Web Vitals.From its SKILL.md

Install
npx -y skills add christopherlouet/claude-base --skill dev-react-perf

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

3 things to look at

  • 5 stars5 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
  • runs commandsInstructs the agent to run 3 commands, including `npm run build -- --analyze` and 2 more.
  • fetches URLsInstructs the agent to fetch 1 URL, including https://example.com.

SKILL.md

4.5 KB, ~1.1k tokens by cl100k_base, as published. Nobody here has run it

React Performance Optimization

Avoid unnecessary re-renders

useMemo - Memoize expensive computations

const expensiveValue = useMemo(() => {
  return computeExpensiveValue(items);
}, [items]);

useCallback - Memoize functions

const handleClick = useCallback(() => {
  onSubmit(formData);
}, [formData, onSubmit]);

React.memo - Memoize components

const UserCard = memo(({ user }: Props) => {
  return <div>{user.name}</div>;
});

Lazy Loading

// Components
const HeavyComponent = lazy(() => import('./HeavyComponent'));

<Suspense fallback={<Loading />}>
  <HeavyComponent />
</Suspense>

// Routes (Next.js)
const DynamicComponent = dynamic(() => import('./Component'), {
  loading: () => <Skeleton />,
  ssr: false,
});

Virtualization

import { FixedSizeList } from 'react-window';

<FixedSizeList
  height={400}
  itemCount={items.length}
  itemSize={50}
>
  {({ index, style }) => (
    <div style={style}>{items[index].name}</div>
  )}
</FixedSizeList>

Images (Next.js)

import Image from 'next/image';

<Image
  src="/photo.jpg"
  alt="Description"
  width={800}
  height={600}
  priority={isAboveFold}
  placeholder="blur"
/>

Core Web Vitals

MetricTargetOptimization
LCP< 2.5sPreload hero image, SSR
FID< 100msCode splitting, defer JS
CLS< 0.1Explicit dimensions

Composition Patterns

Avoid excessive boolean props

// BAD: boolean props explosion
<Button primary large rounded disabled loading />

// GOOD: composition with variants
<Button variant="primary" size="large" shape="rounded" state="loading" />

// BETTER: compound components
<Button.Primary size="large">
  <Button.Spinner /> Loading...
</Button.Primary>

Compound Components

// Compound component pattern
function Tabs({ children }: { children: React.ReactNode }) {
  const [active, setActive] = useState(0);
  return (
    <TabsContext.Provider value={{ active, setActive }}>
      {children}
    </TabsContext.Provider>
  );
}

Tabs.List = function TabList({ children }) { /* ... */ };
Tabs.Tab = function Tab({ index, children }) { /* ... */ };
Tabs.Panel = function TabPanel({ index, children }) { /* ... */ };

// Usage
<Tabs>
  <Tabs.List>
    <Tabs.Tab index={0}>Tab 1</Tabs.Tab>
    <Tabs.Tab index={1}>Tab 2</Tabs.Tab>
  </Tabs.List>
  <Tabs.Panel index={0}>Content 1</Tabs.Panel>
  <Tabs.Panel index={1}>Content 2</Tabs.Panel>
</Tabs>

State Colocation (push state down)

// BAD: state in the parent (re-renders everything)
function Page() {
  const [search, setSearch] = useState('');
  return (
    <div>
      <SearchBar value={search} onChange={setSearch} />
      <ExpensiveList /> {/* Unnecessary re-render! */}
      <Footer />       {/* Unnecessary re-render! */}
    </div>
  );
}

// GOOD: state in the component that uses it
function Page() {
  return (
    <div>
      <SearchSection />     {/* Internal state */}
      <ExpensiveList />     {/* Not affected */}
      <Footer />            {/* Not affected */}
    </div>
  );
}

Children as Props (avoid re-renders)

// GOOD: children do not re-render when the parent changes
function ScrollTracker({ children }: { children: React.ReactNode }) {
  const [scrollY, setScrollY] = useState(0);
  useEffect(() => {
    const handler = () => setScrollY(window.scrollY);
    window.addEventListener('scroll', handler);
    return () => window.removeEventListener('scroll', handler);
  }, []);

  return (
    <div>
      <ScrollIndicator position={scrollY} />
      {children} {/* Does NOT re-render when scrollY changes */}
    </div>
  );
}

Render Props vs Hooks

// PREFER hooks over render props
// BAD: render prop (verbose, nested)
<WindowSize render={({ width }) => (
  <div>{width > 768 ? <Desktop />: <Mobile />}</div>
)} />

// GOOD: custom hook (simple, composable)
function ResponsiveLayout() {
  const { width } = useWindowSize();
  return width > 768 ? <Desktop />: <Mobile />;
}

Tools

# Analyze the bundle
npm run build -- --analyze

# Lighthouse
npx lighthouse https://example.com

# React DevTools Profiler
# Why did you render? (debug re-renders)
npm install @welldone-software/why-did-you-render

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.