A collection of useful React hooks for building web applications.
Note: This initial release (v0.0.1, v0.0.2, v0.0.3) was created to provide quick support for
@mxweb/viewportpackage, particularly to address the iOS 26 viewport bug issue. TheuseMediaQueryanduseCombineRefshooks are essential utilities for handling viewport-related functionality across different devices and browsers.
npm install @mxweb/react-hooks
# or
yarn add @mxweb/react-hooks
# or
pnpm add @mxweb/react-hooksReturns a responsive value based on the current viewport breakpoint. Perfect for defining different values for different screen sizes.
import { useBreakpointValue } from '@mxweb/react-hooks';
function MyComponent() {
const width = useBreakpointValue({
"100%": "(max-width: 639px)", // Mobile: full width
"500px": "(min-width: 640px)", // Desktop: fixed width
});
return <div style={{ width }}>Responsive content</div>;
}Advanced usage:
function ResponsiveGrid() {
const columns = useBreakpointValue({
"1": "(max-width: 639px)",
"2": "(min-width: 640px) and (max-width: 1023px)",
"4": "(min-width: 1024px)",
});
const gap = useBreakpointValue({
"8px": "(max-width: 639px)",
"16px": "(min-width: 640px)",
});
return <div style={{ display: 'grid', gap }}>Grid content</div>;
}Combines multiple callback functions into a single memoized callback that executes all of them in parallel. Useful for triggering multiple actions from a single event.
import { useCombineCallback } from '@mxweb/react-hooks';
function MyComponent({ onSave, onLog }) {
const handleSave = useCombineCallback(
onSave,
(data) => console.log('Saving:', data),
onLog
);
return <button onClick={() => handleSave({ id: 1 })}>Save</button>;
}A non-hook utility function that combines multiple callbacks into a single callback function.
import { combineCallback } from '@mxweb/react-hooks';
const onClick1 = () => console.log('Click 1');
const onClick2 = () => console.log('Click 2');
const combinedClick = combineCallback(onClick1, onClick2);
<button onClick={combinedClick}>Click me</button>Combines multiple event handler callbacks into a single memoized callback that executes them sequentially. Designed for DOM event handlers with async support and event propagation control.
import { useCombineEvents } from '@mxweb/react-hooks';
function MyComponent({ onClick, onAnalytics }) {
const handleClick = useCombineEvents(
onClick,
async (e) => {
await logEvent('button_clicked');
},
onAnalytics
);
return <button onClick={handleClick}>Click me</button>;
}With event.preventDefault():
function Form() {
const handleSubmit = useCombineEvents(
(e) => {
if (!isValid) {
e.preventDefault(); // Stops subsequent handlers
}
},
async (e) => {
// This won't run if preventDefault was called
await submitForm(e);
}
);
return <form onSubmit={handleSubmit}>...</form>;
}A non-hook utility function that combines multiple event handlers with sequential execution.
import { combineEvents } from '@mxweb/react-hooks';
const handleClick1 = (e) => console.log('Handler 1');
const handleClick2 = async (e) => {
await fetch('/api/log');
console.log('Handler 2');
};
const combinedHandler = combineEvents(handleClick1, handleClick2);
<button onClick={combinedHandler}>Click me</button>Combines multiple React refs into a single memoized callback ref. Useful when you need to use both a forwarded ref and a local ref, or when working with multiple ref-based libraries.
import { useRef, forwardRef } from 'react';
import { useCombineRefs } from '@mxweb/react-hooks';
const MyComponent = forwardRef<HTMLDivElement, Props>((props, forwardedRef) => {
const localRef = useRef<HTMLDivElement>(null);
const combinedRef = useCombineRefs(localRef, forwardedRef);
return <div ref={combinedRef}>Content</div>;
});A non-hook utility function that combines multiple refs into a single callback ref function.
import { useRef } from 'react';
import { combineRefs } from '@mxweb/react-hooks';
function MyComponent() {
const ref1 = useRef<HTMLDivElement>(null);
const ref2 = useRef<HTMLDivElement>(null);
const combinedRef = combineRefs(ref1, ref2);
return <div ref={combinedRef}>Content</div>;
}Manages boolean state with convenient control functions. Perfect for modals, dropdowns, tooltips, or any component that can be opened/closed.
import { useDisclosure } from '@mxweb/react-hooks';
function MyComponent() {
const [isOpen, { open, close, toggle }] = useDisclosure();
return (
<>
<button onClick={open}>Open Modal</button>
<button onClick={toggle}>Toggle Modal</button>
{isOpen && (
<Modal onClose={close}>
<p>Modal content</p>
</Modal>
)}
</>
);
}Tracks whether media query(ies) match the current viewport. Supports both single media queries and multiple named queries.
Single query:
import { useMediaQuery } from '@mxweb/react-hooks';
function MyComponent() {
const isMobile = useMediaQuery('(max-width: 767px)');
return <div>{isMobile ? 'Mobile' : 'Desktop'}</div>;
}Multiple named queries:
import { useMediaQuery } from '@mxweb/react-hooks';
function ResponsiveComponent() {
const { mobile, tablet, desktop } = useMediaQuery({
mobile: '(max-width: 767px)',
tablet: '(min-width: 768px) and (max-width: 1023px)',
desktop: '(min-width: 1024px)',
});
if (mobile) return <MobileView />;
if (tablet) return <TabletView />;
if (desktop) return <DesktopView />;
}This package is written in TypeScript and includes full type definitions. All hooks are fully typed and provide excellent IntelliSense support.
- React >= 16.8.0 (hooks support)
- TypeScript >= 4.0.0 (if using TypeScript)
MIT © MXWeb Team
Contributions are welcome! Please feel free to submit a Pull Request.