# Hooks

### <mark style="color:red;">Installation</mark>

```bash
pnpm add @akinon/hooks
```

### <mark style="color:red;">useDebounce</mark>

Debounces a value that changes over time. Delays updating the value until after a specified wait time has elapsed since the last change.

#### <mark style="color:red;">Usage</mark>

```tsx
import { useDebounce } from '@akinon/hooks';

const SearchInput = () => {
  const [searchTerm, setSearchTerm] = useState('');
  const debouncedSearchTerm = useDebounce(searchTerm, 500);

  useEffect(() => {
    if (debouncedSearchTerm) {
      // API call only fires 500ms after user stops typing
      searchProducts(debouncedSearchTerm);
    }
  }, [debouncedSearchTerm]);

  return (
    <Input
      value={searchTerm}
      onChange={(e) => setSearchTerm(e.target.value)}
      placeholder="Search products..."
    />
  );
};
```

#### Parameters

| Parameter | Type     | Description           |
| --------- | -------- | --------------------- |
| `value`   | `T`      | The value to debounce |
| `delay`   | `number` | Delay in milliseconds |

#### Returns

| Type | Description         |
| ---- | ------------------- |
| `T`  | The debounced value |

***

### <mark style="color:red;">useThrottle</mark>

Throttles a value that changes over time. Limits how frequently the value can update.

#### Usage

```tsx
import { useThrottle } from '@akinon/hooks';

const ScrollTracker = () => {
  const [scrollY, setScrollY] = useState(0);
  const throttledScrollY = useThrottle(scrollY, 100);

  useEffect(() => {
    const handleScroll = () => setScrollY(window.scrollY);
    window.addEventListener('scroll', handleScroll);
    return () => window.removeEventListener('scroll', handleScroll);
  }, []);

  // Only updates every 100ms, preventing performance issues
  return <div>Scroll position: {throttledScrollY}px</div>;
};
```

#### Parameters

| Parameter | Type     | Description                       |
| --------- | -------- | --------------------------------- |
| `value`   | `T`      | The value to throttle             |
| `delay`   | `number` | Throttle interval in milliseconds |

#### Returns

| Type | Description         |
| ---- | ------------------- |
| `T`  | The throttled value |

***

### <mark style="color:red;">useLocalStorage</mark>

Persists state to localStorage with automatic serialization/deserialization.

#### Usage

```tsx
import { useLocalStorage } from '@akinon/hooks';

const ThemeSettings = () => {
  const [theme, setTheme, removeTheme] = useLocalStorage('theme', 'light');

  return (
    <div>
      <p>Current theme: {theme}</p>
      <Button onClick={() => setTheme('dark')}>Dark Mode</Button>
      <Button onClick={() => setTheme('light')}>Light Mode</Button>
      <Button onClick={removeTheme}>Reset</Button>
    </div>
  );
};
```

#### With Objects

```tsx
interface UserPreferences {
  language: string;
  notifications: boolean;
}

const [preferences, setPreferences] = useLocalStorage<UserPreferences>(
  'user-preferences',
  { language: 'en', notifications: true }
);

// Update nested values
setPreferences(prev => ({
  ...prev,
  notifications: false
}));
```

#### Raw Mode

```tsx
// Store value as raw string without JSON serialization
const [token, setToken] = useLocalStorage('auth-token', '', { raw: true });
```

#### Parameters

| Parameter      | Type            | Description                        |
| -------------- | --------------- | ---------------------------------- |
| `key`          | `string`        | localStorage key                   |
| `initialValue` | `T`             | Initial value if key doesn't exist |
| `options`      | `ParserOptions` | Serialization options              |

#### Returns

| Index | Type                          | Description     |
| ----- | ----------------------------- | --------------- |
| `0`   | `T \| undefined`              | Current value   |
| `1`   | `Dispatch<SetStateAction<T>>` | Setter function |
| `2`   | `() => void`                  | Remove function |

***

### <mark style="color:red;">useSessionStorage</mark>

Persists state to sessionStorage. Similar to useLocalStorage but data is cleared when the browser session ends.

#### Usage

```tsx
import { useSessionStorage } from '@akinon/hooks';

const WizardForm = () => {
  const [step, setStep] = useSessionStorage('wizard-step', 1);
  const [formData, setFormData] = useSessionStorage('wizard-data', {});

  // State persists across page reloads within the same session
  return (
    <div>
      <p>Step {step} of 3</p>
      <Button onClick={() => setStep(step + 1)}>Next</Button>
    </div>
  );
};
```

#### Parameters

| Parameter      | Type      | Description                            |
| -------------- | --------- | -------------------------------------- |
| `key`          | `string`  | sessionStorage key                     |
| `initialValue` | `T`       | Initial value if key doesn't exist     |
| `raw`          | `boolean` | Store as raw string (default: `false`) |

#### Returns

| Index | Type                 | Description     |
| ----- | -------------------- | --------------- |
| `0`   | `T`                  | Current value   |
| `1`   | `(value: T) => void` | Setter function |

***

### <mark style="color:red;">useToggle</mark>

Toggles a boolean state. Useful for UI states like open/close, show/hide, enabled/disabled.

#### Usage

```tsx
import { useToggle } from '@akinon/hooks';

const Accordion = () => {
  const [isOpen, toggle] = useToggle(false);

  return (
    <div>
      <Button onClick={toggle}>
        {isOpen ? 'Collapse' : 'Expand'}
      </Button>
      {isOpen && <div>Accordion content</div>}
    </div>
  );
};
```

#### Multiple Toggles

```tsx
const SettingsPanel = () => {
  const [showAdvanced, toggleAdvanced] = useToggle(false);
  const [darkMode, toggleDarkMode] = useToggle(false);
  const [notifications, toggleNotifications] = useToggle(true);

  return (
    <div>
      <Switch checked={darkMode} onChange={toggleDarkMode} />
      <Switch checked={notifications} onChange={toggleNotifications} />
      <Button onClick={toggleAdvanced}>
        {showAdvanced ? 'Hide' : 'Show'} Advanced
      </Button>
    </div>
  );
};
```

#### Parameters

| Parameter      | Type      | Default | Description          |
| -------------- | --------- | ------- | -------------------- |
| `initialValue` | `boolean` | `false` | Initial toggle state |

#### Returns

| Index | Type         | Description     |
| ----- | ------------ | --------------- |
| `0`   | `boolean`    | Current value   |
| `1`   | `() => void` | Toggle function |

***

### <mark style="color:red;">useMount</mark>

Runs a function when the component mounts. A cleaner alternative to `useEffect` with empty dependency array.

#### Usage

```tsx
import { useMount } from '@akinon/hooks';

const Dashboard = () => {
  useMount(() => {
    // Runs once when component mounts
    analytics.trackPageView('dashboard');
    fetchInitialData();
  });

  return <div>Dashboard content</div>;
};
```

#### Parameters

| Parameter | Type         | Description              |
| --------- | ------------ | ------------------------ |
| `fn`      | `() => void` | Function to run on mount |

***

### <mark style="color:red;">usePrevious</mark>

Returns the previous value of a state or prop. Useful for comparing values between renders.

#### Usage

```tsx
import { usePrevious } from '@akinon/hooks';

const Counter = () => {
  const [count, setCount] = useState(0);
  const previousCount = usePrevious(count);

  return (
    <div>
      <p>Current: {count}</p>
      <p>Previous: {previousCount}</p>
      <Button onClick={() => setCount(count + 1)}>Increment</Button>
    </div>
  );
};
```

#### Detecting Changes

```tsx
const ProfilePage = ({ userId }: { userId: string }) => {
  const previousUserId = usePrevious(userId);

  useEffect(() => {
    if (previousUserId !== userId) {
      // User changed, fetch new profile
      fetchUserProfile(userId);
    }
  }, [userId, previousUserId]);

  return <div>Profile for user {userId}</div>;
};
```

#### Parameters

| Parameter | Type | Description    |
| --------- | ---- | -------------- |
| `value`   | `T`  | Value to track |

#### Returns

| Type             | Description                                |
| ---------------- | ------------------------------------------ |
| `T \| undefined` | Previous value (undefined on first render) |

***

### <mark style="color:red;">useWindowSize</mark>

Returns the current window dimensions and updates on resize.

#### Usage

```tsx
import { useWindowSize } from '@akinon/hooks';

const ResponsiveComponent = () => {
  const { width, height } = useWindowSize();

  const isMobile = width < 768;
  const isTablet = width >= 768 && width < 1024;
  const isDesktop = width >= 1024;

  return (
    <div>
      <p>Window: {width}x{height}</p>
      {isMobile && <MobileLayout />}
      {isTablet && <TabletLayout />}
      {isDesktop && <DesktopLayout />}
    </div>
  );
};
```

#### Responsive Grid

```tsx
const ProductGrid = () => {
  const { width } = useWindowSize();
  
  const columns = width < 768 ? 1 : width < 1024 ? 2 : width < 1440 ? 3 : 4;

  return (
    <div style={{ display: 'grid', gridTemplateColumns: `repeat(${columns}, 1fr)` }}>
      {products.map(product => (
        <ProductCard key={product.id} {...product} />
      ))}
    </div>
  );
};
```

#### Returns

| Property | Type     | Description         |
| -------- | -------- | ------------------- |
| `width`  | `number` | Window inner width  |
| `height` | `number` | Window inner height |

***

### <mark style="color:red;">Best Practices</mark>

1. **Use debounce for input** - Debounce search inputs and form fields to reduce API calls
2. **Use throttle for scroll/resize** - Throttle scroll and resize handlers for better performance
3. **Prefer useLocalStorage for persistence** - Use for user preferences that should persist
4. **Use useSessionStorage for temporary data** - Wizard forms, multi-step processes
5. **Use useToggle for boolean states** - Cleaner than managing boolean state manually


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.akinon.com/akinon-ui/ui-kit/hooks.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
