Files
monitoring-app/.agents/skills/mantine-dev/references/hooks.md
bipproduction 39d659acd0 skills
2026-04-01 10:43:03 +08:00

345 lines
7.5 KiB
Markdown

# Hooks Reference
`@mantine/hooks` provides 75+ React hooks. No styles needed — works independently.
```bash
npm install @mantine/hooks
```
## State Management
### useDisclosure
Boolean state for modals/menus:
```tsx
import { useDisclosure } from '@mantine/hooks';
const [opened, { open, close, toggle }] = useDisclosure(false);
// With callbacks
const [opened, handlers] = useDisclosure(false, {
onOpen: () => console.log('Opened'),
onClose: () => console.log('Closed'),
});
```
### useToggle
Cycle through values:
```tsx
import { useToggle } from '@mantine/hooks';
const [value, toggle] = useToggle(['blue', 'orange', 'cyan']);
// toggle() cycles, toggle('cyan') sets specific
// Boolean
const [active, toggle] = useToggle([false, true]);
```
### useCounter
Numeric counter with min/max:
```tsx
import { useCounter } from '@mantine/hooks';
const [count, { increment, decrement, set, reset }] = useCounter(0, { min: 0, max: 10 });
```
### useListState
Array state management:
```tsx
import { useListState } from '@mantine/hooks';
const [values, handlers] = useListState([1, 2, 3]);
handlers.append(4); // Add to end
handlers.prepend(0); // Add to start
handlers.insert(2, 99); // Insert at index
handlers.remove(1); // Remove at index
handlers.reorder({ from: 0, to: 2 }); // Move item
handlers.filter((item) => item > 2); // Filter
handlers.apply((item) => item * 2); // Transform all
```
### useSetState
Object state with partial updates:
```tsx
import { useSetState } from '@mantine/hooks';
const [state, setState] = useSetState({ name: '', email: '', age: 0 });
setState({ name: 'John' }); // Partial update, others unchanged
```
## Storage
### useLocalStorage / useSessionStorage
```tsx
import { useLocalStorage } from '@mantine/hooks';
const [value, setValue, removeValue] = useLocalStorage({
key: 'my-key',
defaultValue: 'light',
});
// Auto-serializes objects
const [user, setUser] = useLocalStorage({
key: 'user',
defaultValue: { name: '', preferences: {} },
});
```
## Input/Debounce
### useDebouncedValue
```tsx
import { useDebouncedValue } from '@mantine/hooks';
const [value, setValue] = useState('');
const [debounced] = useDebouncedValue(value, 300);
useEffect(() => {
// API call with debounced value
}, [debounced]);
```
### useDebouncedCallback
```tsx
import { useDebouncedCallback } from '@mantine/hooks';
const search = useDebouncedCallback(async (query: string) => {
await searchAPI(query);
}, 300);
<TextInput onChange={(e) => search(e.target.value)} />
```
### useInputState
Simpler input handling:
```tsx
import { useInputState } from '@mantine/hooks';
const [name, setName] = useInputState('');
<TextInput value={name} onChange={setName} />
const [checked, setChecked] = useInputState(false);
<Checkbox checked={checked} onChange={setChecked} />
```
## UI Interactions
### useClickOutside
```tsx
import { useClickOutside } from '@mantine/hooks';
const ref = useClickOutside(() => close());
<Paper ref={ref}>Click outside to close</Paper>
```
### useHover
```tsx
import { useHover } from '@mantine/hooks';
const { hovered, ref } = useHover();
<Box ref={ref} bg={hovered ? 'blue' : 'gray'}>Hover me</Box>
```
### useFocusWithin
```tsx
import { useFocusWithin } from '@mantine/hooks';
const { ref, focused } = useFocusWithin();
<Box ref={ref} style={{ outline: focused ? '2px solid blue' : 'none' }}>
<TextInput /><TextInput />
</Box>
```
### useMediaQuery
```tsx
import { useMediaQuery } from '@mantine/hooks';
const isMobile = useMediaQuery('(max-width: 768px)');
const matches = useMediaQuery('(min-width: 48em)'); // sm breakpoint
return isMobile ? <MobileNav /> : <DesktopNav />;
```
### useViewportSize
```tsx
import { useViewportSize } from '@mantine/hooks';
const { width, height } = useViewportSize();
```
### useElementSize
```tsx
import { useElementSize } from '@mantine/hooks';
const { ref, width, height } = useElementSize();
<Box ref={ref}>Tracks this element's size</Box>
```
### useScrollIntoView
```tsx
import { useScrollIntoView } from '@mantine/hooks';
const { scrollIntoView, targetRef } = useScrollIntoView<HTMLDivElement>({
offset: 60,
duration: 500,
});
<Button onClick={() => scrollIntoView()}>Scroll</Button>
<div ref={targetRef}>Target</div>
```
### useIntersection / useInViewport
```tsx
import { useIntersection, useInViewport } from '@mantine/hooks';
// Detailed intersection info
const { ref, entry } = useIntersection({ threshold: 0.5 });
// Simple visibility check
const { ref, inViewport } = useInViewport();
```
## Utilities
### useClipboard
```tsx
import { useClipboard } from '@mantine/hooks';
const clipboard = useClipboard({ timeout: 500 });
<Button onClick={() => clipboard.copy('Text')} color={clipboard.copied ? 'teal' : 'blue'}>
{clipboard.copied ? 'Copied!' : 'Copy'}
</Button>
```
### useHotkeys
```tsx
import { useHotkeys, getHotkeyHandler } from '@mantine/hooks';
useHotkeys([
['mod+S', () => save()],
['ctrl+K', () => search()],
]);
// On specific input
<input onKeyDown={getHotkeyHandler([
['mod+Enter', submit],
['Escape', cancel],
])} />
```
### useFullscreen
```tsx
import { useFullscreen } from '@mantine/hooks';
const { toggle, fullscreen } = useFullscreen();
<Button onClick={toggle}>{fullscreen ? 'Exit' : 'Enter'} Fullscreen</Button>
```
### useIdle
```tsx
import { useIdle } from '@mantine/hooks';
const idle = useIdle(5000); // 5 seconds
<Text>{idle ? 'User is idle' : 'User is active'}</Text>
```
### useInterval / useTimeout
```tsx
import { useInterval, useTimeout } from '@mantine/hooks';
const interval = useInterval(() => tick(), 1000);
interval.start(); interval.stop(); interval.toggle();
const { start, clear } = useTimeout(() => action(), 3000);
```
### useDocumentTitle
```tsx
import { useDocumentTitle } from '@mantine/hooks';
useDocumentTitle('My Page Title');
```
### useOs
```tsx
import { useOs } from '@mantine/hooks';
const os = useOs(); // 'macos' | 'ios' | 'windows' | 'android' | 'linux'
<Text>Shortcut: {os === 'macos' ? '⌘' : 'Ctrl'}</Text>
```
### useNetwork
```tsx
import { useNetwork } from '@mantine/hooks';
const { online, downlink, effectiveType } = useNetwork();
return online ? <App /> : <OfflineMessage />;
```
### usePrevious
```tsx
import { usePrevious } from '@mantine/hooks';
const [value, setValue] = useState(0);
const previous = usePrevious(value);
```
### useMergedRef
Combine multiple refs:
```tsx
import { useMergedRef } from '@mantine/hooks';
const myRef = useRef<HTMLDivElement>(null);
const { ref: hookRef } = useHover();
const mergedRef = useMergedRef(myRef, hookRef);
<Box ref={mergedRef}>Content</Box>
```
## Complete Hook List
**State:** useDisclosure, useToggle, useCounter, useListState, useSetState, useQueue, usePagination
**Storage:** useLocalStorage, useSessionStorage, readLocalStorageValue
**Input:** useDebouncedValue, useDebouncedState, useDebouncedCallback, useInputState, useValidatedState, useUncontrolled
**UI:** useClickOutside, useHover, useFocusWithin, useFocusReturn, useFocusTrap, useMediaQuery, useViewportSize, useElementSize, useResizeObserver, useScrollIntoView, useIntersection, useInViewport, useWindowScroll, useMouse, useMove
**Utilities:** useClipboard, useHotkeys, useFullscreen, useIdle, useInterval, useTimeout, useDocumentTitle, useDocumentVisibility, useFavicon, useOs, useNetwork, usePrevious, useMergedRef, useId, useForceUpdate, useReducedMotion, useTextSelection, useWindowEvent, useEventListener, useEyeDropper, useHash, useHeadroom, useLogger, useMutationObserver, useOrientation, usePageLeave, usePinchToZoom, useStateHistory