# React Simplikit

> Selects and applies react-simplikit hooks, components and utils (useDebounce, useThrottle, useToggle, useBooleanState, useCounter, useList, useMap, useSet, useInterval, useTimeout, usePrevious, usePreservedCallback, useOutsideClickEffect, useIntersectionObserver, useStorageState, useLongPress, SwitchCase, Separated, mergeRefs, buildContext, ...) instead of hand-written equivalents, including the mobile-web keyboard, safe-area, visual viewport and body-scroll-lock hooks. Use when writing React state or effect logic, debouncing or throttling, boolean/counter/list/map/set state, intervals and timeouts, click-outside, long-press or double-click handling, viewport visibility or impression tracking, persisted state in localStorage/sessionStorage, conditional rendering, merging refs, React Context boilerplate, or SSR-safe browser access, and whenever the project depends on react-simplikit.

- Skill: `toss/react-simplikit` (Agent Skill, multi-file: 59 files)
- Install (CLI): `npx skillmds@latest add toss/react-simplikit`
- Raw SKILL.md: https://api.skillmd.com/api/skills/toss/react-simplikit/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- License: MIT
- Author: toss (https://skillmd.com/u/toss)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/toss/react-simplikit

---


<!-- GENERATED by `yarn skill:gen` from the documentation pages in packages/react-simplikit/src — edit .scripts/commands/generateSkill/template.md, not this file. -->

# react-simplikit

Zero-dependency React hooks, components and utils in one package, `react-simplikit`. Alongside state/logic and browser-event hooks it covers the mobile-web problems — on-screen keyboard, safe-area insets, visual viewport, body scroll lock — that usually get hand-written.

## Critical rules

- **Check the catalog before hand-writing debounce, throttle, toggle, counter, list/map/set state, interval, timeout, previous-value, stable-callback, click-outside, long-press, intersection/visibility or storage-persisted-state logic.** If a matching entry exists, use it. Reimplementing these is the most common mistake this skill exists to prevent.
- **Never guess a signature.** Before using an entry, read `references/<name>.md` — it has the parameter table, return shape and a working example.
- **One import path, named imports only**: `import { useDebounce, useKeyboardHeight } from 'react-simplikit'`. There is no subpath and no default export.
- **SSR**: never branch server-rendered markup on a value that comes from a browser API hook. Use `useIsClient` for client-only rendering instead of `typeof window` checks.
- **Do not wrap or re-export these hooks** in the consumer project just to rename them; use them directly so upgrades stay mechanical.

## Common needs → use

Backticks in this table mark catalog entries only.

| Need                                                                | Use                                      |
| ------------------------------------------------------------------- | ---------------------------------------- |
| Debounce a callback (search input, resize)                          | `useDebounce` / `useDebouncedCallback`   |
| Throttle a callback (scroll, pointer move)                          | `useThrottle` / `useThrottledCallback`   |
| Boolean on/off, flip only                                           | `useToggle`                              |
| Boolean on/off with explicit set-true / set-false                   | `useBooleanState`                        |
| Numeric state with bounds/step                                      | `useCounter`                             |
| Array / Map / Set state with immutable helpers                      | `useList` / `useMap` / `useSet`          |
| State persisted in localStorage / sessionStorage                    | `useStorageState`                        |
| Declarative setInterval / setTimeout                                | `useInterval` / `useTimeout`             |
| Stable callback identity without stale closures                     | `usePreservedCallback`                   |
| Skip re-renders when an object is deep-equal                        | `usePreservedReference`                  |
| Run an async function in an effect                                  | `useAsyncEffect`                         |
| Effect that runs only when a condition holds                        | `useConditionalEffect`                   |
| Side effect tied to a DOM ref (attach/detach)                       | `useRefEffect`                           |
| Click / tap outside an element (close menu, modal)                  | `useOutsideClickEffect`                  |
| Long press / double click                                           | `useLongPress` / `useDoubleClick`        |
| Element enters or leaves the viewport                               | `useIntersectionObserver`                |
| How long an element stayed visible (impression tracking)            | `useImpressionRef` / `ImpressionArea`    |
| React to tab / page visibility changes with a callback              | `useVisibilityEvent`                     |
| Read the current tab / page visibility as state                     | `usePageVisibility`                      |
| Device location                                                     | `useGeolocation`                         |
| Combine multiple refs into one                                      | `mergeRefs`                              |
| Controlled-or-uncontrolled component state                          | `useControlledState`                     |
| Input onChange boilerplate                                          | `useInputState`                          |
| Render one of several components by key                             | `SwitchCase`                             |
| Put a separator between children                                    | `Separated`                              |
| Create a Context + Provider + hook without boilerplate              | `buildContext`                           |
| Merge props objects (handlers chained, className joined)            | `mergeProps`                             |
| Client-only rendering guard                                         | `useIsClient`                            |
| Fixed-bottom element must avoid the on-screen keyboard (mobile web) | `useAvoidKeyboard`                       |
| Keyboard height / visibility (mobile web)                           | `useKeyboardHeight`, `isKeyboardVisible` |
| Notch / home-indicator insets (mobile web)                          | `useSafeAreaInset`, `getSafeAreaInset`   |
| Lock body scroll while a sheet/modal is open (mobile web)           | `useBodyScrollLock`                      |

## Workflow

1. Match the need against the table above, then confirm in the full catalog.
2. Read `references/<name>.md` for the signature and example. Do not rely on memory.
3. Import from `react-simplikit`.
4. If nothing matches, write plain React — do not stretch a hook past its documented purpose.

## Catalog

### hooks

| Name | Description |
| --- | --- |
| [`useAsyncEffect`](references/useAsyncEffect.md) | `useAsyncEffect` is a React hook for handling asynchronous side effects in React components. |
| [`useAvoidKeyboard`](references/useAvoidKeyboard.md) | `useAvoidKeyboard` is a React hook that helps fixed-bottom elements avoid the on-screen keyboard. |
| [`useBodyScrollLock`](references/useBodyScrollLock.md) | `useBodyScrollLock` is a React hook that locks body scroll while the component is mounted. |
| [`useBooleanState`](references/useBooleanState.md) | `useBooleanState` is a React hook that simplifies managing a boolean state. |
| [`useCallbackOncePerRender`](references/useCallbackOncePerRender.md) | `useCallbackOncePerRender` is a React hook that ensures a callback function is executed only once, regardless of how many times it's called. |
| [`useConditionalEffect`](references/useConditionalEffect.md) | `useConditionalEffect` is a React hook that conditionally executes effects based on a predicate function. |
| [`useControlledState`](references/useControlledState.md) | `useControlledState` is a React hook that allows you to control both controlled and uncontrolled states. |
| [`useCounter`](references/useCounter.md) | `useCounter` is a React hook that manages a numeric counter state with increment, decrement, and reset capabilities. |
| [`useDebounce`](references/useDebounce.md) | `useDebounce` is a React hook that returns a debounced version of the provided callback function. |
| [`useDebouncedCallback`](references/useDebouncedCallback.md) | `useDebouncedCallback` is a React hook that returns a debounced version of the provided callback function. |
| [`useDebouncedValue`](references/useDebouncedValue.md) | `useDebouncedValue` is a React hook that returns a debounced copy of the given value. |
| [`useDoubleClick`](references/useDoubleClick.md) | `useDoubleClick` is a React hook that differentiates between single and double click events. |
| [`useGeolocation`](references/useGeolocation.md) | `useGeolocation` is a React hook that retrieves and tracks the user's geographical location. |
| [`useImpressionRef`](references/useImpressionRef.md) | `useImpressionRef` is a React hook that measures the time a specific DOM element is visible on the screen and executes callbacks when the element enters or exits the viewport. |
| [`useInputState`](references/useInputState.md) | `useInputState` is a React hook that manages an input state with optional value transformation. |
| [`useIntersectionObserver`](references/useIntersectionObserver.md) | `useIntersectionObserver` is a React hook that detects whether a specific DOM element is visible on the screen. |
| [`useInterval`](references/useInterval.md) | `useInterval` is a React hook that executes a function at a specified interval. |
| [`useIsClient`](references/useIsClient.md) | `useIsClient` is a React hook that returns `true` only in the client-side environment. |
| [`useIsomorphicLayoutEffect`](references/useIsomorphicLayoutEffect.md) | `useIsomorphicLayoutEffect` is a React hook that provides the behavior of `useLayoutEffect` without triggering warnings during server-side rendering. |
| [`useKeyboardHeight`](references/useKeyboardHeight.md) | `useKeyboardHeight` is a React hook that tracks the on-screen keyboard height. |
| [`useList`](references/useList.md) | A React hook that manages an array as state. |
| [`useLoading`](references/useLoading.md) | `useLoading` is a React hook that simplifies managing the loading state of a `Promise`. |
| [`useLongPress`](references/useLongPress.md) | `useLongPress` is a React hook that detects when an element is pressed and held for a specified duration. |
| [`useMap`](references/useMap.md) | A React hook that manages a key-value Map as state. |
| [`useNetworkStatus`](references/useNetworkStatus.md) | `useNetworkStatus` is a React hook that provides access to the Network Information API. |
| [`useOutsideClickEffect`](references/useOutsideClickEffect.md) | `useOutsideClickEffect` is a React hook that triggers a callback when a click event occurs outside the specified container(s). |
| [`usePageVisibility`](references/usePageVisibility.md) | `usePageVisibility` is a React hook that detects page visibility changes. |
| [`usePreservedCallback`](references/usePreservedCallback.md) | `usePreservedCallback` is a React hook that maintains a stable reference to a callback function while ensuring it always has access to the latest state or props. |
| [`usePreservedReference`](references/usePreservedReference.md) | `usePreservedReference` is a React hook that helps maintain the reference of a value when it hasn't changed, while ensuring you can safely use the latest state. |
| [`usePrevious`](references/usePrevious.md) | `usePrevious` is a React hook that returns the previous value of the input state. |
| [`useRefEffect`](references/useRefEffect.md) | `useRefEffect` is a React hook that helps you set a reference to a specific DOM element and execute a callback whenever the element changes. |
| [`useSafeAreaInset`](references/useSafeAreaInset.md) | `useSafeAreaInset` is a React hook that tracks safe area inset changes. |
| [`useScrollDirection`](references/useScrollDirection.md) | `useScrollDirection` is a React hook that detects scroll direction. |
| [`useSet`](references/useSet.md) | A React hook that manages a Set as state. |
| [`useStorageState`](references/useStorageState.md) | `useStorageState` is a React that functions like `useState` but persists the state value in browser storage. |
| [`useThrottle`](references/useThrottle.md) | `useThrottle` is a React hook that creates a throttled version of a callback function. |
| [`useThrottledCallback`](references/useThrottledCallback.md) | `useThrottledCallback` is a React hook that returns a throttled version of the provided callback function. |
| [`useThrottledValue`](references/useThrottledValue.md) | `useThrottledValue` is a React hook that returns a throttled copy of the given value. |
| [`useTimeout`](references/useTimeout.md) | `useTimeout` is a React hook that executes a callback function after a specified delay. |
| [`useToggle`](references/useToggle.md) | `useToggle` is a React hook that simplifies managing a boolean state. |
| [`useVisibilityEvent`](references/useVisibilityEvent.md) | `useVisibilityEvent` is a React hook that listens to changes in the document's visibility state and triggers a callback. |
| [`useVisualViewport`](references/useVisualViewport.md) | `useVisualViewport` is a React hook that tracks Visual Viewport changes. |

### components

| Name | Description |
| --- | --- |
| [`ImpressionArea`](references/ImpressionArea.md) | `ImpressionArea` is a component that measures the time a specific DOM element is visible on the screen and executes callbacks when the element enters or exits the viewport. |
| [`Separated`](references/Separated.md) | `Separated` is a component that inserts a specified component between each child element. |
| [`SwitchCase`](references/SwitchCase.md) | `SwitchCase` is a component that allows you to declaratively render components based on a given value, similar to a `switch-case` statement. |

### utils

| Name | Description |
| --- | --- |
| [`buildContext`](references/buildContext.md) | `buildContext` is a helper function that reduces repetitive code when defining React Context. |
| [`disableBodyScrollLock`](references/disableBodyScrollLock.md) | `disableBodyScrollLock` is a utility function that unlocks the body scroll. |
| [`enableBodyScrollLock`](references/enableBodyScrollLock.md) | `enableBodyScrollLock` is a utility function that locks the body scroll. |
| [`getKeyboardHeight`](references/getKeyboardHeight.md) | `getKeyboardHeight` is a utility function that returns the current on-screen keyboard height in pixels. |
| [`getSafeAreaInset`](references/getSafeAreaInset.md) | `getSafeAreaInset` is a utility function that returns all safe area insets in pixels as an object. |
| [`isAndroid`](references/isAndroid.md) | `isAndroid` is a utility function that detects whether the current device is running Android. |
| [`isIOS`](references/isIOS.md) | `isIOS` is a utility function that detects whether the current device is running iOS or iPadOS. |
| [`isKeyboardVisible`](references/isKeyboardVisible.md) | `isKeyboardVisible` is a utility function that checks whether the on-screen keyboard is currently visible. |
| [`isServer`](references/isServer.md) | `isServer` is a utility function that checks if the code is running on the server. |
| [`mergeProps`](references/mergeProps.md) | `mergeProps` is a utility function that merges multiple props objects into a single object. |
| [`mergeRefs`](references/mergeRefs.md) | This function takes multiple refs (RefObject or RefCallback) and returns a single ref that updates all provided refs. |
| [`subscribeKeyboardHeight`](references/subscribeKeyboardHeight.md) | `subscribeKeyboardHeight` is a utility function that subscribes to changes in the on-screen keyboard height. |

## Learn more

- Docs: https://react-simplikit.slash.page
- Machine-readable index: https://react-simplikit.slash.page/llms.txt (full text: /llms-full.txt; any docs page + `.md` returns raw markdown)
- Source: https://github.com/toss/react-simplikit

