agentleFS
WhatIfWeDigDeeperWhatIfWeDigDeeper/application-tracker/.claude/skills/add-react-hook/SKILL.md

add-react-hook

Skill1 starsChanged 9 months agoMITView on GitHub

Create a custom React hook with TypeScript and tests. Use when: extracting reusable stateful logic into a custom hook for a React or Next.js frontend (useState, useEffect, useCallback patterns). Only for React-based stacks — for Vue composables, Svelte stores, or Angular services, read the existing code for that stack instead.

We split this skill into the rules it gives an agent

1 rule. About 0 are common, 1 is distinctive, and 0 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈1

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 0

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Create a custom React hook with proper typing and tests.

    line 13

≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Add React Hook: $ARGUMENTS

Create a custom React hook with proper typing and tests.

Process

1. Plan the Hook

Determine:

  • What state does it manage?
  • What side effects does it handle?
  • What does it return?

2. Create Hook File

Location: hooks/use[HookName].ts

import { useState, useEffect, useCallback } from 'react';

interface UseHookNameOptions {
  // configuration options
  initialValue?: string;
}

interface UseHookNameReturn {
  // return type
  value: string;
  setValue: (value: string) => void;
  isLoading: boolean;
  error: Error | null;
}

export function useHookName(options: UseHookNameOptions = {}): UseHookNameReturn {
  const { initialValue = '' } = options;

  const [value, setValue] = useState(initialValue);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState<Error | null>(null);

  const handleSetValue = useCallback((newValue: string) => {
    setValue(newValue);
  }, []);

  useEffect(() => {
    // Side effects here
  }, []);

  return {
    value,
    setValue: handleSetValue,
    isLoading,
    error,
  };
}

3. Add to Exports

// hooks/index.ts
export { useHookName } from './useHookName';

4. Create Tests

// hooks/useHookName.test.ts
import { renderHook, act } from '@testing-library/react';
import { useHookName } from './useHookName';

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

  test('updates value', () => {
    const { result } = renderHook(() => useHookName());
    act(() => {
      result.current.setValue('new value');
    });
    expect(result.current.value).toBe('new value');
  });

  test('accepts initial value option', () => {
    const { result } = renderHook(() =>
      useHookName({ initialValue: 'custom' })
    );
    expect(result.current.value).toBe('custom');
  });
});

5. Validate

npm run build
npm run lint
npm test

Common Hook Patterns

Data fetching:

export function useFetch<T>(url: string) {
  const [data, setData] = useState<T | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<Error | null>(null);
  // ...
}

Local storage:

export function useLocalStorage<T>(key: string, initialValue: T) {
  const [value, setValue] = useState<T>(() => {
    const stored = localStorage.getItem(key);
    return stored ? JSON.parse(stored) : initialValue;
  });
  // ...
}

Debounce:

export function useDebounce<T>(value: T, delay: number): T {
  const [debouncedValue, setDebouncedValue] = useState(value);
  // ...
}

Media query:

export function useMediaQuery(query: string): boolean {
  const [matches, setMatches] = useState(false);
  // ...
}

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

Reviews can't be read right now.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.