new-hook · git:20260430.17a2444 · 2026-04-30 · sha256 d2b58bea351e03a1

new-hook git:20260430.17a2444A

Immutable. This exact content is served forever at /api/v1/blob/d2b58bea351e03a1.

---
name: new-hook
description: Scaffold a new custom React hook with a Vitest test file. Use this skill whenever the user asks to "create a hook", "make a useFoo hook", "scaffold a custom React hook", "add a hook under app/hooks", or describes a piece of reusable React state/effect logic that warrants extraction into a named `use*` hook.
---

Scaffold a new custom React hook with a test file.

## Step 1: Gather user input

Ask the user these questions using AskUserQuestion:

- Hook name (e.g. `useDebounce`, `useLocalStorage`) — will add `use` prefix if missing
- Brief description of what the hook does
- Parameters (name, type, and whether optional — e.g. `delay: number, callback: () => void`)
- Return type (e.g. `boolean`, `[value, setValue]`, `{data, isLoading, error}`)

## Step 2: Create hook file

Create `app/hooks/{hookName}.ts` following the useBreakpoint/useTimeout patterns:

```ts
import {useEffect, useState} from 'react';

export const {
  hookName,
} = ({params}): {returnType} => {
  // implementation based on description
};
```

Key conventions from the reference hooks:

- Named export (not default)
- Import only needed React hooks
- Use `useRef` for mutable values that shouldn't trigger re-renders (timers, previous values)
- Clean up side effects in `useEffect` return
- Type parameters explicitly

## Step 3: Create test file

Create `app/hooks/tests/{hookName}.test.ts`:

```ts
import {renderHook, act} from '@testing-library/react';
import {describe, expect, test} from 'vitest';
import {{hookName}} from '../{hookName}';

describe('{hookName}', () => {
  test('returns initial value', () => {
    const {result} = renderHook(() => {hookName}({defaultParams}));
    expect(result.current).toBe({expectedInitialValue});
  });

  test('updates on change', () => {
    // test the hook's behavior
  });
});
```

- Use `renderHook` from `@testing-library/react`
- Use `act` when testing state changes
- Use `vi.useFakeTimers()` / `vi.advanceTimersByTime()` for time-dependent hooks
- Test edge cases (unmount cleanup, parameter changes, etc.)

## Step 4: Verify

Run these commands sequentially, stopping if any fails:

```bash
pnpm typecheck && pnpm lint && pnpm test --run
```

Fix any issues before reporting to the user.