Skip to main content

Hooks Package

The @kousta-ui/hooks package provides a collection of essential, reusable React hooks that solve common UI patterns and state management challenges.


Features

  • TypeScript First: Full TypeScript support with comprehensive type definitions
  • Performance Optimized: Efficient implementations with minimal re-renders
  • Composable: Designed to work together and with other hooks
  • Lightweight: Minimal bundle impact with tree-shaking support
  • Tested: Thoroughly tested for reliability
  • Zero Dependencies: No external dependencies required

Installation

npm install @kousta-ui/hooks
# or
yarn add @kousta-ui/hooks
# or
pnpm add @kousta-ui/hooks

Available Hooks

HookPurposeCommon Use Cases
useDisclosureManage boolean state (open/close)Modals, dropdowns, sidebars
usePaginationHandle pagination logicData tables, lists, galleries
useDebounceCallbackDebounce function callsSearch inputs, API calls
useScrollLockPrevent body scrollingModals, overlays, drawers

Quick Start

import {
useDisclosure,
usePagination,
useDebounceCallback,
useScrollLock
} from "@kousta-ui/hooks";

function App() {
// Modal state management
const { opened, open, close, toggle } = useDisclosure(false);

// Pagination for data
const { page, nextPage, prevPage, setPage } = usePagination({
total: 100,
limit: 10,
});

// Debounced search
const debouncedSearch = useDebounceCallback((query: string) => {
console.log("Searching for:", query);
}, 300);

// Scroll lock for modal
const { lockScroll, unlockScroll } = useScrollLock();

const handleModalOpen = () => {
lockScroll();
open();
};

const handleModalClose = () => {
unlockScroll();
close();
};

return (
<div>
<button onClick={handleModalOpen}>Open Modal</button>

<input
type="text"
placeholder="Search..."
onChange={(e) => debouncedSearch(e.target.value)}
/>

<div>
<button onClick={prevPage} disabled={page === 1}>
Previous
</button>
<span>Page {page}</span>
<button onClick={nextPage}>
Next
</button>
</div>
</div>
);
}

Hook Categories

State Management Hooks

Hooks that help manage component state:

  • useDisclosure - Simplified boolean state management with open/close/toggle actions

Data Handling Hooks

Hooks for managing data operations:

UI/UX Hooks

Hooks that enhance user experience:

  • useScrollLock - Prevent background scrolling when overlays are active

When to Use These Hooks

Use useDisclosure when:

  • Managing modal, dropdown, or sidebar visibility
  • Need simple boolean state with action methods
  • Want consistent open/close/toggle patterns

Use usePagination when:

  • Displaying paginated data (tables, lists, galleries)
  • Need boundary checking and page navigation
  • Want to track current page and total pages

Use useDebounceCallback when:

  • Handling search input with API calls
  • Preventing excessive function execution
  • Need performance optimization for rapid events

Use useScrollLock when:

  • Showing modals or overlays
  • Preventing background scrolling
  • Need scrollbar compensation to prevent layout shift

TypeScript Support

All hooks provide full TypeScript support:

import { useDisclosure, usePagination } from "@kousta-ui/hooks";

// Typed disclosure state
const { opened, open, close } = useDisclosure(false);

// Typed pagination
const { page, setPage } = usePagination({
total: 100,
limit: 10,
page: 1,
});

// Typed debounced callback
const debouncedFn = useDebounceCallback(
(query: string) => searchAPI(query),
300
);

Performance Considerations

  • Optimized Re-renders: Hooks use useCallback and useMemo where appropriate
  • Minimal Dependencies: Zero external dependencies for smaller bundle size
  • Efficient Algorithms: Optimized implementations for common operations
  • Tree Shaking: Unused hooks are eliminated during build

Performance Tip These hooks are designed to be performant out of the box, but always profile your specific use case.


Composition Examples

Search with Pagination

function SearchableList() {
const [query, setQuery] = useState("");
const [results, setResults] = useState([]);
const { page, nextPage, prevPage, setPage } = usePagination({
total: 0, // Will be updated after search
});

const debouncedSearch = useDebounceCallback(async (searchQuery: string) => {
const response = await searchAPI(searchQuery, page);
setResults(response.data);
// Update pagination total
}, 300);

useEffect(() => {
debouncedSearch(query);
}, [query, page, debouncedSearch]);

return (
<div>
<input
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="Search..."
/>

{/* Render results */}
{results.map((item) => (
<div key={item.id}>{item.name}</div>
))}

{/* Pagination controls */}
<div>
<button onClick={prevPage}>Previous</button>
<span>Page {page}</span>
<button onClick={nextPage}>Next</button>
</div>
</div>
);
}
function ModalExample() {
const { opened, open, close } = useDisclosure();
const { lockScroll, unlockScroll } = useScrollLock();

const handleOpen = () => {
lockScroll();
open();
};

const handleClose = () => {
unlockScroll();
close();
};

return (
<div>
<button onClick={handleOpen}>Open Modal</button>

{opened && (
<div className="modal-overlay">
<div className="modal">
<h2>Modal Content</h2>
<p>This modal locks the background scroll.</p>
<button onClick={handleClose}>Close</button>
</div>
</div>
)}
</div>
);
}

Best Practices

Do's

  • ✅ Use hooks for their intended purpose
  • ✅ Combine hooks for complex scenarios
  • ✅ Leverage TypeScript for type safety
  • ✅ Test hook behavior in your components

Don'ts

  • ❌ Don't use hooks outside React components
  • ❌ Don't mutate hook return values
  • ❌ Don't ignore TypeScript warnings
  • ❌ Don't over-engineer simple state management

Next Steps


Contributing

We welcome contributions! Please see our contributing guidelines for details.


License

MIT © Ousta