agentsclimarketplace

Dev react perf

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

Opinionated Claude Code foundation — Explore → TDD → Audit workflow, auto-detected stack presets (nextjs, fastapi, astro, ...), curl | bash install. MIT.

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.

One thing 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.

What its author says it does

Copied from the file, not written here

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

SKILL.md

4.5 KB, 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

Keep looking

Skills are one crate of 328,083. 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.