New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details
Socket
Book a DemoSign in
Socket

codedsaif-react-hooks

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

codedsaif-react-hooks

To make it easy for you to get started with GitLab, here's a list of recommended next steps.

latest
Source
npmnpm
Version
1.0.6
Version published
Maintainers
1
Created
Source

React Hooks

A collection of useful React custom hooks for common functionalities.

Installation

npm install codedsaif-react-hooks

Available Hooks

useClickOutside

A lightweight React hook to detect clicks outside a referenced component. Perfect for dropdowns, modals, and popovers.

/**
 * Custom hook that triggers a callback when a user clicks outside the referenced element.
 * @param {Function} callback - The function to call when clicking outside the element.
 * @returns {React.RefObject} - A ref that should be attached to the element you want to monitor.
 * @example
 * function Dropdown() {
 *   const [isOpen, setIsOpen] = useState(false);
 *   const dropdownRef = useClickOutside(() => setIsOpen(false));
 *   return (
 *     <div>
 *       <button onClick={() => setIsOpen(!isOpen)}>Toggle Menu</button>
 *       {isOpen && (
 *         <ul ref={dropdownRef}>
 *           <li>Option 1</li>
 *           <li>Option 2</li>
 *           <li>Option 3</li>
 *       </ul>
 *     )}
 *   </div>
 * );
 */

useDebounce

Debounces a value with a specified delay.

/**
 * Custom hook to debounce a value after a specified delay.
 * @param {*} value - The value to debounce.
 * @param {number} [delay=500] - Delay in milliseconds before updating the debounced value.
 * @returns {*} - The debounced value.
 * @example
 * const [searchTerm, setSearchTerm] = useState("");
 * const debouncedSearch = useDebounce(searchTerm, 300);
 * useEffect(() => {
 *   if (debouncedSearch) {
 *     fetch(`https://api.example.com/search?q=${debouncedSearch}`)
 *       .then((res) => res.json())
 *       .then((data) => console.log(data));
 *   }
 * }, [debouncedSearch]);
 * return (
 *   <input
 *     type="text"
 *     placeholder="Search..."
 *     onChange={(e) => setSearchTerm(e.target.value)}
 *   />
 * );
 */

useFetch

Simplifies data fetching with loading and error states.

/**
 * Custom hook to fetch data from an API.
 * @param {string} url - The URL to fetch data from.
 * @param {object} options - Optional fetch options (headers, method, etc.).
 * @returns {{ data: any, loading: boolean, error: string|null }} - The fetched data, loading state, and error message.
 * @example
 * const { data, loading, error } = useFetch("https://api.example.com/users");
 * if (loading) return <p>Loading...</p>;
 * if (error) return <p>Error: {error}</p>;
 * return (
 *   <ul>
 *     {data.map(user => (
 *       <li key={user.id}>{user.name}</li>
 *     ))}
 *   </ul>
 * );
 */

useLocalStorage

Persists state in localStorage with automatic JSON parsing/stringifying.

/**
 * Custom hook to persist state in localStorage.
 * @param {string} key - The localStorage key to store the value under.
 * @param {*} initialValue - The initial value to use if none is found in localStorage.
 * @returns {[any, function]} - Returns the stored value and a setter function.
 * @example
 * function Dropdown() {
 *   const [theme, setTheme] = useLocalStorage("theme", "light");
 *   useEffect(() => {
 *     document.body.className = theme;
 *   }, [theme]);
 *   return (
 *     <button onClick={() => setTheme(theme === "light" ? "dark" : "light")}>
 *       Toggle Theme
 *     </button>
 *   );
 * }
 */

usePrevious

Tracks the previous value of a state or prop.

/**
 * Custom hook to get the previous value of a prop or state.
 * @param {*} value - The current value to track.
 * @returns {*} - The previous value before the current render.
 * @example
 * const [count, setCount] = useState(0);
 * const prevCount = usePrevious(count);
 * return (
 *   <>
 *     <p>Current: {count}, Previous: {prevCount}</p>
 *     <button onClick={() => setCount(count + 1)}>Increase</button>
 *   </>
 * );
 */

useTheme

Manages theme switching with localStorage persistence.

/**
 * Custom hook to manage dark and light theme modes,
 * persisting the theme preference in localStorage.
 * @returns {[string, function]} - Current theme and a toggle function.
 * @example
 * const [theme, toggleTheme] = useDarkMode();
 * return (
 *   <button onClick={toggleTheme}>
 *     Switch to {theme === "light" ? "Dark" : "Light"} Mode
 *   </button>
 * );
 */

useWindowSize

Tracks window dimensions with responsive updates.

/**
 * Custom hook to get the current window dimensions.
 * @returns {{ width: number, height: number }} - The current width and height of the window.
 * @example
 * function ResponsiveComponent() {
 *   const { width } = useWindowSize();
 *   return (
 *     <div>
 *       {width > 1024 ? (
 *         <h1>Desktop View 🖥️</h1>
 *       ) : width > 768 ? (
 *         <h1>Tablet View 📱</h1>
 *       ) : (
 *         <h1>Mobile View 📲</h1>
 *       )}
 *   </div>
 * );
 */

useInfiniteScroll

Supports both automatic callback fetching and manual slicing with scroll.

/**
 * @param {Function|null} callback - Called when scroll reaches bottom (set null for manual mode)
 * @param {Object} options - Configuration options
 * @param {React.RefObject} [options.containerRef=null] - Scrollable container ref
 * @param {boolean} [options.manual=false] - If true, enables manual mode and returns 'limit'
 * @param {number} [options.start=10] - Initial limit in manual mode
 * @param {number} [options.pace=10] - Increment step for limit
 * @param {number} [options.offset=100] - Distance from bottom to trigger scroll (in px)
 * @param {boolean} [options.hasMore=true] - Set false to stop infinite loading when no more data
 * @param {boolean} [options.debug=false] - Enable funny console logs
 * 
 * @returns {[boolean, Function]|number}
 * - If manual=false: returns [isFetching, setIsFetching]
 * - If manual=true: returns limit (number)
 *
 * Example: Auto-fetch Mode (Default)
 * -------------------------------------
 * const containerRef = useRef(null);
 * const [data, setData] = useState([]);
 * const [page, setPage] = useState(1);
 * const [hasMore, setHasMore] = useState(true);
 * const fetchMore = async () => {
 *   const res = await fetch(`https://medrum.herokuapp.com/feeds/?source=5718e53e7a84fb1901e05971&page=${page}&sort=latest`);
 *   const json = await res.json();
 *   if (json.length === 0) setHasMore(false);
 *   // OR if(json.count === data.length) setHasMore(false);
 *   else {
 *     setData(prev => [...prev, ...json]);
 *     setPage(prev => prev + 1);
 *   }
 * };
 * const [isFetching, setIsFetching] = useInfiniteScroll(fetchMore, { containerRef, hasMore });
 *
 * Example: Manual Slice Mode
 * ------------------------------
 * const containerRef = useRef(null);
 * const [data, setData] = useState([]);
 * const [page, setPage] = useState(1);
 * const [hasMore, setHasMore] = useState(true);
 * const limit = useInfiniteScroll(null, { containerRef, manual: true, start: 10, pace: 10, hasMore });
 * const fetchMore = async () => {
 *   const res = await fetch(`https://medrum.herokuapp.com/feeds/?source=5718e53e7a84fb1901e05971&page=${page}&sort=latest`);
 *   const json = await res.json();
 *   if (json.length === 0) setHasMore(false);
 *   else {
 *     setData(prev => [...prev, ...json]);
 *     setPage(prev => prev + 1);
 *   }
 * };
 * useEffect(() => {
 *   fetchMore();
 * }, [limit]);
 * return (
 *   <ul ref={containerRef} style={{ height: "400px", overflowY: "scroll" }}>
 *     {data.slice(0, limit).map(item => (
 *       <li key={item.id}>{item.title}</li>
 *     ))}
 *   </ul>
 * );
 */

useInterval

Runs a callback at a specified interval with support for pausing, debugging, initial delay, and external control.

/**
 * @param {Function} callback - Function to run at each interval tick.
 * @param {number|null} delay - Interval duration in ms. Use `null` to pause.
 * @param {Object} [options={}] - Additional options.
 * @param {boolean} [options.debug=false] - Log lifecycle events to the console.
 * @param {boolean} [options.stop=false] - Stops interval immediately when set to true.
 * @param {boolean} [options.immediate=false] - Fires callback immediately on mount.
 * @param {number} [options.initialDelay] - Wait this long before starting interval loop.
 * @param {number} [options.maxTicks] - Stop after this many ticks.
 *
 * @returns {
 *   count: number,
 *   reset: () => void,
 *   forceTick: () => void,
 *   pause: () => void,
 *   resume: () => void,
 * }
 * 
 * @example
 * // Logs "Tick" every second
 * useInterval(() => console.log('Tick'), 1000);
 *
 * @example
 * const { count, reset } = useInterval(() => {
 *   console.log('Tick!');
 * }, 1000);
 * 
 * @example
 * // With pause/resume capability
 * const [delay, setDelay] = useState(1000);
 * <button onClick={() => setDelay(prev => prev ? null : 1000)}>Toggle</button>
 * useInterval(() => console.log('Toggling...'), delay);
 * 
 * @example
 * function CountDown({ initialCount, downLimit, initialDelay = 1000, bgColor = 'transparent' }) {
 *     const [count, setCount] = useState(initialCount);
 *     const [delay, setDelay] = useState(null);
 *     useInterval(() => {
 *         const newValue = count - 1;
 *         setCount(newValue)
 *         if (newValue <= downLimit) setDelay(null);
 *     }, delay);
 *     return (
 *         <div style={{ display: 'flex', backgroundColor: bgColor }}>{count}
 *             <button onClick={() => setDelay(initialDelay)}>Start</button>
 *             <button onClick={() => setDelay(null)}>Stop</button>
 *         </div>
 *     )
 * }
 * 
 * @example
 * import React, { useState, useCallback } from 'react';
 * import useInterval from './useInterval';
 * const ShoppingList = () => {
 *     // Wait 5 seconds before fetching new data
 *     const POLL_DELAY = 5000;
 *     const [items, setItems] = useState([]);
 *     const fetchItems = useCallback(async () => {
 *         const response = await fetch('/shopping-list/items');
 *         const json = await response.json();
 *         setItems(json);
 *     }, []);
 *     useEffect(() => {
 *         // Fetch items from API on mount
 *         fetchItems();
 *     }, []);
 *     useInterval(() => {
 *         fetchItems();
 *     }, POLL_DELAY);
 *     return (
 *         <ul>
 *             {items.map((item) => <li>{item.title}</li>)}
 *         </ul>
 *     )
 * };
 */

useKeyPress

A powerful custom React hook for handling keyboard interactions.

/**
 * Features:
 * - Detect and respond to individual key presses
 * - Match specific target key (e.g. 'a')
 * - Maintain history of pressed keys
 * - Detect modifier key states: Shift, Alt, Ctrl, Meta
 * - Detect multi-key combos like 'ctrl+s', 'cmd+z'
 * - Pause and resume key tracking
 * - Optionally ignore key presses in input, textarea, or contentEditable fields
 *
 * @param {Object} options - Configuration options
 * @param {Function} [options.onKeyPress] - Function to run when a valid key is pressed
 * @param {string} [options.targetKey] - Key to match for triggering `keyMatched` (case-insensitive)
 * @param {boolean} [options.enableHistory=true] - Whether to track history of pressed keys
 * @param {number} [options.maxHistory=10] - Max number of keys to store in history
 * @param {boolean} [options.ignoreInput=false] - If true, ignores key presses from editable elements (input, textarea, contentEditable)
 * @param {string[]} [options.combos=[]] - List of keyboard combos to detect (e.g. ['ctrl+s', 'cmd+z'])
 *
 * @returns {Object} Hook output
 * @returns {string|null} keyPressed - The current key being pressed (null if none)
 * @returns {boolean} keyMatched - True if the most recent key matched `targetKey`
 * @returns {string[]} keyHistory - Array of previously pressed keys (up to `maxHistory`)
 * @returns {string|null} comboMatched - The matched combo string, if any (e.g. 'ctrl+s')
 * @returns {Object} modifiers - Current modifier key states { shift, alt, ctrl, meta }
 * @returns {Function} reset - Clears the keyMatched, keyHistory, and comboMatched states
 * @returns {Function} setPaused - Function to pause/resume the hook (use `setPaused(true)` to pause)
 *
 * @example
 * // Basic key detection and match tracking
 * const { keyPressed, keyMatched, keyHistory } = useKeyPress({
 *   onKeyPress: (key) => console.log('You pressed:', key),
 *   targetKey: 'a',
 *   enableHistory: true,
 *   maxHistory: 5,
 * });
 *
 * @example
 * // Full usage with modifiers, combo detection, pause and reset
 * const {
 *   keyPressed,
 *   keyMatched,
 *   keyHistory,
 *   comboMatched,
 *   modifiers,
 *   reset,
 *   setPaused,
 * } = useKeyPress({
 *   onKeyPress: (key) => console.log('Key:', key),
 *   targetKey: 's',
 *   combos: ['ctrl+s', 'cmd+z'],
 *   ignoreInput: true,
 * });
 *
 * useEffect(() => {
 *   if (comboMatched === 'ctrl+s') {
 *     console.log('Save triggered!');
 *   }
 * }, [comboMatched]);
 */

License

This package is licensed under the MIT License.

Keywords

codedsaif

FAQs

Package last updated on 10 Jun 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts