Toggle State HookProblem StatementWrite a custom hook `useToggle(initialValue)` that returns a boolean state and a function to toggle it.Approach 1. Use `useState`. 2. Define a function that calls `setValue(!value)`. 3. Return the pair as an array. Solution`function useToggle(initialValue = false) { const [value, setValue] = React.useState(initialValue); const toggle = () => setValue(v => !v); return [value, toggle];
Counter HookProblem Statement`Write a custom hook `useCounter(initialValue)` that returns `{count, increment, decrement, resetApproach 1. Use `useState` for the count. 2. Define the three handler functions. 3. Return them together in an object. Solution`function useCounter(initialValue = 0) { const [count, setCount] = React.useState(initialValue); const increment = () => setCount(c => c + 1); const decrement = () => setCount(c => c - 1); const reset = () => setCount(initialValue); return { count, increment, decrement, reset
Update Document TitleProblem Statement`Write a component `TitleUpdater({titleApproach 1. Use `useEffect`. 2. Add `title` to the dependency array. Solution`function TitleUpdater({ title
Get Previous ValueProblem StatementWrite a custom hook `usePrevious(value)` that returns the value from the previous render.Approach 1. Use `useRef` to store the value. 2. Use `useEffect` to update the ref after the render is complete. 3. Return the current ref value (which is still the old value during return). Solution`function usePrevious(value) { const ref = React.useRef(); React.useEffect(() => { ref.current = value;
Is MountedProblem StatementWrite a hook `useIsMounted()` that returns `true` if the component is still mounted.Approach 1. Use `useRef(false)`. 2. Use `useEffect` to set it to true on mount and false in the cleanup function. Solution`function useIsMounted() { const isMounted = React.useRef(false); React.useEffect(() => { isMounted.current = true; return () => { isMounted.current = false;
Window Size HookProblem StatementWrite a hook useWindowSize() that returns an object `{ width, height }` updating on resize.Approach 1. Use `useState` with `window.innerWidth/height`. 2. Use `useEffect` to add a 'resize' listener and remove it on cleanup. Solution`function useWindowSize() { const [size, setSize] = React.useState({ width: window.innerWidth, height: window.innerHeight
Input Binding HookProblem StatementWrite a hook useInput(initialValue) that returns `{ value, onChange }` compatible with input props.Approach 1. Use `useState`. 2. `onChange` should update state with `e.target.value`. Solution`function useInput(initialValue) { const [value, setValue] = React.useState(initialValue); return { value, onChange: (e) => setValue(e.target.value)
Simple Fetch HookProblem StatementWrite a hook useFetch(url) that returns `{ data, loading, error }`.Approach 1. Define states for data, loading, and error. 2. Use `useEffect` to trigger the fetch when the `url` changes. Solution`function useFetch(url) { const [data, setData] = React.useState(null); const [loading, setLoading] = React.useState(true); const [error, setError] = React.useState(null); React.useEffect(() => { setLoading(true); fetch(url) .then(res => res.json()) .then(setData) .catch(setError) .finally(() => setLoading(false));
Click Outside HookProblem StatementWrite a hook `useClickOutside(ref, callback)` that triggers the callback when a click happens outside the ref element.Approach 1. Use `useEffect` to add a 'mousedown' listener to the document. 2. Check if `ref.current` exists and if it DOES NOT contain the event target. Solution`function useClickOutside(ref, callback) { React.useEffect(() => { const listener = (event) => { if (!ref.current || ref.current.contains(event.target)) return; callback(event);
Persistent State HookProblem StatementWrite a hook `useLocalStorage(key, initialValue)` that syncs state with localStorage.Approach 1. Initialize state by checking localStorage first. 2. Use a `useEffect` to update localStorage whenever the state changes. Solution`function useLocalStorage(key, initialValue) { const [value, setValue] = React.useState(() => { const saved = localStorage.getItem(key); return saved !== null ? JSON.parse(saved) : initialValue;
Debounce Value HookProblem StatementWrite a hook `useDebounce(value, delay)` that returns the debounced value.Approach 1. Use `useEffect`. 2. Inside, set a timeout to update the internal state. 3. Return the cleanup function to clear the timeout. Solution`function useDebounce(value, delay) { const [debouncedValue, setDebouncedValue] = React.useState(value); React.useEffect(() => { const handler = setTimeout(() => { setDebouncedValue(value);
Safe Timeout HookProblem StatementWrite a hook `useTimeout(callback, delay)` that automatically clears the timeout on unmount.Approach 1. Use `useRef` to store the latest callback. 2. Use `useEffect` with the delay to trigger the timeout. Solution`function useTimeout(callback, delay) { const savedCallback = React.useRef(callback); React.useEffect(() => { savedCallback.current = callback;
Custom Interval HookProblem StatementWrite a hook `useInterval(callback, delay)` that handles the common "stale closure" problem with setInterval.Approach 1. Store the callback in a `useRef`. 2. Update the ref on every render. 3. In `useEffect`, set up the interval using the ref. Solution`function useInterval(callback, delay) { const savedCallback = React.useRef(callback); React.useEffect(() => { savedCallback.current = callback;
Array Manipulation HookProblem StatementWrite a hook useArray(initialArray) that returns `{ array, push, remove, filter, clear }`.Approach 1. Use `useState` for the array. 2. Define helper functions that call `setArray` with new values. Solution`function useArray(initialValue) { const [array, setArray] = React.useState(initialValue); return { array, push: (item) => setArray(a => [...a, item]), filter: (fn) => setArray(a => a.filter(fn)), remove: (index) => setArray(a => [...a.slice(0, index), ...a.slice(index + 1)]), clear: () => setArray([])
Is Hovering HookProblem StatementWrite a hook `useHover()` that returns a `ref` and a boolean `isHovered`.Approach 1. Create a `ref`. 2. In `useEffect`, add mouseenter/mouseleave listeners to `ref.current`. Solution`function useHover() { const [hovered, setHovered] = React.useState(false); const ref = React.useRef(null); React.useEffect(() => { const node = ref.current; if (node) { node.addEventListener('mouseenter', () => setHovered(true)); node.addEventListener('mouseleave', () => setHovered(false)); return () => { node.removeEventListener('mouseenter', () => setHovered(true)); node.removeEventListener('mouseleave', () => setHovered(false));
Keyboard Event HookProblem StatementWrite a hook `useKeyPress(targetKey)` that returns `true` if the user is pressing that key.Approach 1. Add listeners for 'keydown' and 'keyup' to the window. 2. Update state based on whether the event key matches the target. Solution`function useKeyPress(targetKey) { const [keyPressed, setKeyPressed] = React.useState(false); React.useEffect(() => { const downHandler = ({ key
Force Update HookProblem StatementWrite a hook `useForceUpdate()` that returns a function which forces the component to re-render.Approach 1. Use a state dummy value (like a counter or object) and update it to trigger render. Solution`function useForceUpdate() { const [, setValue] = React.useState(0); return () => setValue(val => val + 1);
Dynamic Script HookProblem StatementWrite a hook `useScript(url)` that dynamically loads a script and returns its loading status.Approach 1. Create a `script` element. 2. Set attributes and listeners for `load` and `error`. 3. Append to body. Solution`function useScript(url) { const [status, setStatus] = React.useState('loading'); React.useEffect(() => { let script = document.querySelector(`script[src="${url
Value TrackerProblem Statement`Write a component `ValueTracker({valueApproach 1. Use `usePrevious` (from before) or a ref to track the last value. 2. Compare current value with prev in an effect. Solution`function ValueTracker({ value
State History HookProblem StatementWrite a hook `useHistory(initialValue)` that returns `[value, setValue, history]` where history is an array of all previous values.Approach 1. Maintain state for the current value and another state for the history array. 2. Wrap `setValue` to push to history whenever it is called. Solution`function useHistory(initialValue) { const [value, setVal] = React.useState(initialValue); const [history, setHistory] = React.useState([initialValue]); const setValue = (newVal) => { setVal(newVal); setHistory(h => [...h, newVal]);