Get Started
Hooks Pro Guide: 50+ Q&A

50+ React Hooks Interview Questions for Freshers (2026)

The most comprehensive guide to React Hooks for freshers. Over 50 questions covering useState, useEffect, custom hooks, and advanced optimization patterns.

interview-prep

Introduction: The 2026 React Hooks Landscape

Welcome to the future of React development! As we move into 2026, React Hooks have become the universal standard for functional components, with 98% of new React projects adopting hooks-first architectures. For freshers entering the job market, mastering hooks isn't just an advantage—it's an absolute requirement. This comprehensive guide covers 50+ essential hooks interview questions with detailed explanations, practical examples, and 2026-specific insights.


Section 1: Foundational Hooks (useState, useEffect, useContext)

1. What are React Hooks and why were they introduced?

Expected Answer:
"Hooks are functions that let you 'hook into' React state and lifecycle features from function components. They were introduced in React 16.8 to solve several problems:

  1. Reusing stateful logic without complicated patterns like HOCs or render props

  2. Simplifying complex components that became hard to understand with lifecycle methods

  3. Reducing the class-component boilerplate and making React more accessible

  4. Enabling better code organization by separating concerns based on what pieces are related

Hooks represent a fundamental shift from object-oriented to functional programming patterns in React."

2. Explain the useState hook with examples.

Expected Answer:
"The useState hook adds state to functional components. It returns an array with two elements: the current state value and a function to update it."

javascript
// Basic usage
function Counter() {
  const [count, setCount] = useState(0);
  
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

// Complex state with objects
function UserProfile() {
  const [user, setUser] = useState({
    name: '',
    email: '',
    age: 0
  });
  
  // Update specific property
  const updateName = (name) => {
    setUser(prev => ({ ...prev, name }));
  };
  
  return <div>{user.name}</div>;
}

Key Points for 2026:

  • Lazy initialization: useState(() => expensiveComputation())

  • Functional updates: Always use when new state depends on previous state

  • Batch updates: React batches multiple setState calls in event handlers

3. What is the useEffect hook and how does it work?

Expected Answer:
"useEffect lets you perform side effects in function components. It serves the combined purpose of componentDidMount, componentDidUpdate, and componentWillUnmount."

javascript
// Three variations of useEffect

// 1. Run on every render
useEffect(() => {
  console.log('Runs after every render');
});

// 2. Run only on mount and unmount
useEffect(() => {
  console.log('Runs once on mount');
  
  // Cleanup function (runs on unmount)
  return () => {
    console.log('Cleanup on unmount');
  };
}, []); // Empty dependency array

// 3. Run when dependencies change
useEffect(() => {
  console.log('Runs when userId changes');
  fetchUserData(userId);
}, [userId]); // Dependency array

2026 Advanced Insight:
"With React 19+, the dependency array is more intelligent. The React compiler can sometimes automatically detect dependencies, but it's still best practice to explicitly declare them."

4. Explain the useContext hook with a real example.

Expected Answer:
"useContext lets you subscribe to React context without introducing nesting. It's React's built-in solution for prop drilling."

javascript
// 1. Create Context
const ThemeContext = createContext('light');

// 2. Provide Context
function App() {
  return (
    <ThemeContext.Provider value="dark">
      <Toolbar />
    </ThemeContext.Provider>
  );
}

// 3. Consume Context
function Toolbar() {
  const theme = useContext(ThemeContext);
  return <div>Current theme: {theme}</div>;
}

// Practical example: User Authentication
const AuthContext = createContext(null);

function AuthProvider({ children }) {
  const [user, setUser] = useState(null);
  
  const login = (userData) => setUser(userData);
  const logout = () => setUser(null);
  
  return (
    <AuthContext.Provider value={{ user, login, logout }}>
      {children}
    </AuthContext.Provider>
  );
}

function UserProfile() {
  const { user } = useContext(AuthContext);
  
  if (!user) return <div>Please login</div>;
  
  return <div>Welcome, {user.name}!</div>;
}

Section 2: Performance Hooks (useMemo, useCallback, useRef)

5. What is useMemo and when should you use it?

Expected Answer:
"useMemo memoizes expensive computations so they only recompute when dependencies change."

javascript
function ExpensiveComponent({ items, filter }) {
  // Without useMemo - recalculates on every render
  // const filteredItems = items.filter(item => 
  //   item.name.includes(filter)
  // );
  
  // With useMemo - only recalculates when items or filter changes
  const filteredItems = useMemo(() => {
    console.log('Filtering items...');
    return items.filter(item => item.name.includes(filter));
  }, [items, filter]);
  
  return <div>{filteredItems.length} items found</div>;
}

When to use useMemo in 2026:

  1. Expensive calculations that take noticeable time

  2. Reference equality for objects passed to child components

  3. Preventing re-renders when props haven't meaningfully changed

Important: "Don't overuse useMemo. In 2026, React's compiler handles many optimizations automatically."

6. Explain useCallback with examples.

Expected Answer:
"useCallback returns a memoized callback function that only changes when dependencies change."

javascript
function ParentComponent() {
  const [count, setCount] = useState(0);
  
  // Without useCallback - new function on every render
  // const handleClick = () => {
  //   console.log('Clicked!');
  // };
  
  // With useCallback - same function unless dependencies change
  const handleClick = useCallback(() => {
    console.log(`Clicked ${count} times`);
  }, [count]); // Only changes when count changes
  
  return <ChildComponent onClick={handleClick} />;
}

const ChildComponent = React.memo(({ onClick }) => {
  console.log('Child rendered');
  return <button onClick={onClick}>Click me</button>;
});

Common Mistake Freshers Make:

javascript
// WRONG: Empty dependency array but uses state
const handleClick = useCallback(() => {
  console.log(count); // Will always show initial count
}, []); // ❌

// CORRECT: Include dependencies
const handleClick = useCallback(() => {
  console.log(count);
}, [count]); // ✅

7. What is useRef and how is it different from state?

Expected Answer:
"useRef returns a mutable ref object whose .current property is initialized to the passed argument. The key differences from state:

  1. Mutating .current doesn't cause re-renders

  2. Ref persists across renders (like instance variables in classes)

  3. Ref is mutable, state is immutable through setter functions"

javascript
function RefExample() {
  // 1. Accessing DOM elements
  const inputRef = useRef(null);
  
  const focusInput = () => {
    inputRef.current.focus();
  };
  
  // 2. Storing previous values
  const [count, setCount] = useState(0);
  const prevCountRef = useRef();
  
  useEffect(() => {
    prevCountRef.current = count;
  });
  
  const prevCount = prevCountRef.current;
  
  // 3. Storing mutable values without re-renders
  const intervalRef = useRef();
  
  useEffect(() => {
    intervalRef.current = setInterval(() => {
      console.log('Tick');
    }, 1000);
    
    return () => clearInterval(intervalRef.current);
  }, []);
  
  return (
    <div>
      <input ref={inputRef} type="text" />
      <button onClick={focusInput}>Focus Input</button>
      <p>Current: {count}, Previous: {prevCount}</p>
    </div>
  );
}

Section 3: Advanced Built-in Hooks

8. Explain useReducer with a practical example.

Expected Answer:
"useReducer is an alternative to useState for managing complex state logic. It's inspired by Redux pattern."

javascript
// Reducer function
function todoReducer(state, action) {
  switch (action.type) {
    case 'ADD_TODO':
      return [...state, { 
        id: Date.now(), 
        text: action.payload, 
        completed: false 
      }];
    case 'TOGGLE_TODO':
      return state.map(todo =>
        todo.id === action.payload
          ? { ...todo, completed: !todo.completed }
          : todo
      );
    case 'DELETE_TODO':
      return state.filter(todo => todo.id !== action.payload);
    default:
      return state;
  }
}

function TodoApp() {
  const [todos, dispatch] = useReducer(todoReducer, []);
  const [input, setInput] = useState('');
  
  const addTodo = () => {
    if (input.trim()) {
      dispatch({ type: 'ADD_TODO', payload: input });
      setInput('');
    }
  };
  
  return (
    <div>
      <input 
        value={input}
        onChange={(e) => setInput(e.target.value)}
        placeholder="Add todo"
      />
      <button onClick={addTodo}>Add</button>
      
      <ul>
        {todos.map(todo => (
          <li key={todo.id}>
            <span style={{ 
              textDecoration: todo.completed ? 'line-through' : 'none'
            }}>
              {todo.text}
            </span>
            <button onClick={() => 
              dispatch({ type: 'TOGGLE_TODO', payload: todo.id })
            }>
              Toggle
            </button>
            <button onClick={() => 
              dispatch({ type: 'DELETE_TODO', payload: todo.id })
            }>
              Delete
            </button>
          </li>
        ))}
      </ul>
    </div>
  );
}

9. What is useLayoutEffect and when would you use it?

Expected Answer:
"useLayoutEffect is similar to useEffect, but it fires synchronously after all DOM mutations but before the browser paints. This makes it useful for:

  1. Measuring DOM elements before paint

  2. Animations that need to be synchronized with layout

  3. DOM mutations that should be visible immediately"

javascript
function Tooltip({ text, children }) {
  const ref = useRef(null);
  const [position, setPosition] = useState({ top: 0, left: 0 });
  
  useLayoutEffect(() => {
    // Measure after DOM is updated but before paint
    if (ref.current) {
      const rect = ref.current.getBoundingClientRect();
      setPosition({
        top: rect.top - 30, // Position above element
        left: rect.left
      });
    }
  }, [text]); // Re-measure when text changes
  
  return (
    <>
      <span ref={ref}>{children}</span>
      {text && (
        <div 
          className="tooltip"
          style={{
            position: 'fixed',
            top: `${position.top}px`,
            left: `${position.left}px`
          }}
        >
          {text}
        </div>
      )}
    </>
  );
}

Key Difference:

  • useEffect: Asynchronous, runs after paint

  • useLayoutEffect: Synchronous, runs before paint

10. Explain useImperativeHandle with example.

Expected Answer:
"useImperativeHandle customizes the instance value that's exposed when using ref on a component. It's rarely needed but useful for exposing specific methods to parent components."

javascript
// Child Component
const FancyInput = React.forwardRef((props, ref) => {
  const inputRef = useRef();
  
  // Expose only these methods to parent
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    },
    clear: () => {
      inputRef.current.value = '';
    },
    getValue: () => {
      return inputRef.current.value;
    }
  }));
  
  return <input ref={inputRef} {...props} />;
});

// Parent Component
function Parent() {
  const inputRef = useRef();
  
  const handleClick = () => {
    inputRef.current.focus(); // Works
    inputRef.current.clear(); // Works
    // inputRef.current.value = 'test'; // ❌ Not exposed
  };
  
  return (
    <div>
      <FancyInput ref={inputRef} />
      <button onClick={handleClick}>Focus and Clear</button>
    </div>
  );
}

Section 4: Custom Hooks (The Game Changer)

11. What are custom hooks and how do you create one?

Expected Answer:
"Custom hooks are JavaScript functions that use other hooks. They let you extract component logic into reusable functions."

javascript
// Custom hook: useLocalStorage
function useLocalStorage(key, initialValue) {
  // Get from localStorage or use initial value
  const [storedValue, setStoredValue] = useState(() => {
    try {
      const item = window.localStorage.getItem(key);
      return item ? JSON.parse(item) : initialValue;
    } catch (error) {
      console.error(error);
      return initialValue;
    }
  });
  
  // Update localStorage when value changes
  const setValue = useCallback((value) => {
    try {
      const valueToStore = 
        value instanceof Function ? value(storedValue) : value;
      
      setStoredValue(valueToStore);
      window.localStorage.setItem(key, JSON.stringify(valueToStore));
    } catch (error) {
      console.error(error);
    }
  }, [key, storedValue]);
  
  return [storedValue, setValue];
}

// Usage
function UserPreferences() {
  const [theme, setTheme] = useLocalStorage('theme', 'light');
  const [notifications, setNotifications] = useLocalStorage('notifications', true);
  
  return (
    <div>
      <select value={theme} onChange={(e) => setTheme(e.target.value)}>
        <option value="light">Light</option>
        <option value="dark">Dark</option>
      </select>
      <label>
        <input
          type="checkbox"
          checked={notifications}
          onChange={(e) => setNotifications(e.target.checked)}
        />
        Enable Notifications
      </label>
    </div>
  );
}

12. Create a custom hook for fetching data.

Expected Answer:
"Here's a production-ready useFetch hook with error handling, loading states, and abort capability:"

javascript
function useFetch(url, options = {}) {
  const [data, setData] = useState(null);
  const [error, setError] = useState(null);
  const [loading, setLoading] = useState(true);
  
  const abortControllerRef = useRef(null);
  
  const fetchData = useCallback(async () => {
    if (abortControllerRef.current) {
      abortControllerRef.current.abort();
    }
    
    abortControllerRef.current = new AbortController();
    
    setLoading(true);
    setError(null);
    
    try {
      const response = await fetch(url, {
        ...options,
        signal: abortControllerRef.current.signal
      });
      
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }
      
      const result = await response.json();
      setData(result);
    } catch (err) {
      if (err.name !== 'AbortError') {
        setError(err.message);
      }
    } finally {
      setLoading(false);
    }
  }, [url, options]);
  
  useEffect(() => {
    fetchData();
    
    return () => {
      if (abortControllerRef.current) {
        abortControllerRef.current.abort();
      }
    };
  }, [fetchData]);
  
  const refetch = useCallback(() => {
    fetchData();
  }, [fetchData]);
  
  return { data, error, loading, refetch };
}

// Usage
function UserProfile({ userId }) {
  const { data: user, loading, error } = useFetch(
    `https://api.example.com/users/${userId}`
  );
  
  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error}</div>;
  
  return (
    <div>
      <h1>{user.name}</h1>
      <p>{user.email}</p>
    </div>
  );
}

13. Create a custom hook for detecting clicks outside an element.

Expected Answer:
"Here's a useClickOutside hook for closing modals, dropdowns, or menus:"

javascript
function useClickOutside(ref, callback) {
  useEffect(() => {
    const handleClickOutside = (event) => {
      if (ref.current && !ref.current.contains(event.target)) {
        callback();
      }
    };
    
    // Use capture phase to catch events before they bubble
    document.addEventListener('mousedown', handleClickOutside, true);
    document.addEventListener('touchstart', handleClickOutside, true);
    
    return () => {
      document.removeEventListener('mousedown', handleClickOutside, true);
      document.removeEventListener('touchstart', handleClickOutside, true);
    };
  }, [ref, callback]);
}

// Usage
function Dropdown() {
  const [isOpen, setIsOpen] = useState(false);
  const dropdownRef = useRef(null);
  
  useClickOutside(dropdownRef, () => {
    if (isOpen) setIsOpen(false);
  });
  
  return (
    <div ref={dropdownRef}>
      <button onClick={() => setIsOpen(!isOpen)}>
        Menu
      </button>
      {isOpen && (
        <div className="dropdown-menu">
          <a href="#">Option 1</a>
          <a href="#">Option 2</a>
          <a href="#">Option 3</a>
        </div>
      )}
    </div>
  );
}

Section 5: Common Hook Patterns & Best Practices

14. What are the Rules of Hooks?

Expected Answer:
"1. Only Call Hooks at the Top Level: Don't call hooks inside loops, conditions, or nested functions
2. Only Call Hooks from React Functions: Call hooks from React function components or custom hooks
3. Hook Names Must Start with 'use': Custom hooks must start with 'use' so React can check rules"

javascript
// ✅ CORRECT
function Component() {
  const [state, setState] = useState(0);
  useEffect(() => { /* ... */ });
  return <div>{state}</div>;
}

// ❌ WRONG - Hook in condition
function Component({ condition }) {
  if (condition) {
    const [state, setState] = useState(0); // ❌
  }
  return <div>Hello</div>;
}

// ❌ WRONG - Hook in loop
function Component() {
  for (let i = 0; i < 10; i++) {
    useEffect(() => { /* ... */ }); // ❌
  }
  return <div>Hello</div>;
}

15. How do you handle async operations in useEffect?

Expected Answer:
"You need to handle cleanup to prevent memory leaks and state updates on unmounted components."

javascript
function UserData({ userId }) {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);
  
  useEffect(() => {
    let isMounted = true;
    
    const fetchUser = async () => {
      try {
        const response = await fetch(`/api/users/${userId}`);
        const data = await response.json();
        
        if (isMounted) {
          setUser(data);
          setLoading(false);
        }
      } catch (error) {
        if (isMounted) {
          console.error('Failed to fetch user:', error);
          setLoading(false);
        }
      }
    };
    
    fetchUser();
    
    return () => {
      isMounted = false;
    };
  }, [userId]);
  
  if (loading) return <div>Loading...</div>;
  return <div>{user?.name}</div>;
}

16. How to optimize performance with hooks?

Expected Answer:
"1. Memoize expensive calculations with useMemo
2. Memoize callbacks with useCallback when passing to optimized children
3. Use React.memo for component memoization
4. Lazy load components with React.lazy and Suspense
5. Split effects for independent logic
6. Batch state updates when possible"

javascript
function OptimizedComponent({ items, filter, onSelect }) {
  // 1. Memoize filtered items
  const filteredItems = useMemo(() => {
    return items.filter(item => item.includes(filter));
  }, [items, filter]);
  
  // 2. Memoize callback
  const handleSelect = useCallback((item) => {
    onSelect(item);
  }, [onSelect]);
  
  // 3. Split effects for independent concerns
  useEffect(() => {
    // Analytics effect
    trackAnalytics(filter);
  }, [filter]);
  
  useEffect(() => {
    // Data fetching effect
    fetchRelatedData(filter);
  }, [filter]);
  
  return (
    <MemoizedChild 
      items={filteredItems}
      onSelect={handleSelect}
    />
  );
}

const MemoizedChild = React.memo(function Child({ items, onSelect }) {
  return (
    <ul>
      {items.map(item => (
        <li key={item} onClick={() => onSelect(item)}>
          {item}
        </li>
      ))}
    </ul>
  );
});

Section 6: Advanced Hook Concepts

17. What is the difference between useMemo and useCallback?

Expected Answer:
"useMemo memoizes a value, while useCallback memoizes a function.

javascript
// useMemo - returns a memoized VALUE
const expensiveValue = useMemo(() => {
  return computeExpensiveValue(a, b);
}, [a, b]);

// useCallback - returns a memoized FUNCTION
const memoizedCallback = useCallback(() => {
  doSomething(a, b);
}, [a, b]);

// Under the hood, useCallback is essentially:
const useCallback = (fn, deps) => {
  return useMemo(() => fn, deps);
};

When to use each:

  • useMemo: When you have an expensive calculation

  • useCallback: When you need to maintain referential equality of functions

18. How to handle forms with hooks?

Expected Answer:
"Here's a complete form handling solution with validation:"

javascript
function useForm(initialValues, validate) {
  const [values, setValues] = useState(initialValues);
  const [errors, setErrors] = useState({});
  const [touched, setTouched] = useState({});
  
  const handleChange = useCallback((e) => {
    const { name, value, type, checked } = e.target;
    setValues(prev => ({
      ...prev,
      [name]: type === 'checkbox' ? checked : value
    }));
  }, []);
  
  const handleBlur = useCallback((e) => {
    const { name } = e.target;
    setTouched(prev => ({ ...prev, [name]: true }));
    
    // Validate on blur
    if (validate) {
      const validationErrors = validate(values);
      setErrors(validationErrors);
    }
  }, [values, validate]);
  
  const handleSubmit = useCallback((onSubmit) => (e) => {
    e.preventDefault();
    
    // Mark all fields as touched
    const allTouched = Object.keys(values).reduce((acc, key) => {
      acc[key] = true;
      return acc;
    }, {});
    setTouched(allTouched);
    
    // Validate
    if (validate) {
      const validationErrors = validate(values);
      setErrors(validationErrors);
      
      if (Object.keys(validationErrors).length === 0) {
        onSubmit(values);
      }
    } else {
      onSubmit(values);
    }
  }, [values, validate]);
  
  const resetForm = useCallback(() => {
    setValues(initialValues);
    setErrors({});
    setTouched({});
  }, [initialValues]);
  
  return {
    values,
    errors,
    touched,
    handleChange,
    handleBlur,
    handleSubmit,
    resetForm,
    setValues
  };
}

// Usage
function LoginForm() {
  const validate = (values) => {
    const errors = {};
    if (!values.email) errors.email = 'Email is required';
    if (!values.password) errors.password = 'Password is required';
    return errors;
  };
  
  const { values, errors, touched, handleChange, handleBlur, handleSubmit } = 
    useForm({ email: '', password: '' }, validate);
  
  const onSubmit = (data) => {
    console.log('Form submitted:', data);
  };
  
  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <div>
        <input
          type="email"
          name="email"
          value={values.email}
          onChange={handleChange}
          onBlur={handleBlur}
          placeholder="Email"
        />
        {touched.email && errors.email && (
          <span style={{ color: 'red' }}>{errors.email}</span>
        )}
      </div>
      <div>
        <input
          type="password"
          name="password"
          value={values.password}
          onChange={handleChange}
          onBlur={handleBlur}
          placeholder="Password"
        />
        {touched.password && errors.password && (
          <span style={{ color: 'red' }}>{errors.password}</span>
        )}
      </div>
      <button type="submit">Login</button>
    </form>
  );
}

19. How to create a custom hook for dark/light theme?

Expected Answer:
"Here's a complete theme hook with system preference detection:"

javascript
function useTheme() {
  const [theme, setTheme] = useState(() => {
    // Check localStorage first
    const savedTheme = localStorage.getItem('theme');
    if (savedTheme) return savedTheme;
    
    // Then check system preference
    if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
      return 'dark';
    }
    
    return 'light';
  });
  
  const toggleTheme = useCallback(() => {
    setTheme(prev => prev === 'light' ? 'dark' : 'light');
  }, []);
  
  // Apply theme to document
  useEffect(() => {
    const root = document.documentElement;
    root.setAttribute('data-theme', theme);
    localStorage.setItem('theme', theme);
  }, [theme]);
  
  // Listen for system theme changes
  useEffect(() => {
    const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
    
    const handleChange = (e) => {
      // Only change if user hasn't set a preference
      if (!localStorage.getItem('theme')) {
        setTheme(e.matches ? 'dark' : 'light');
      }
    };
    
    mediaQuery.addEventListener('change', handleChange);
    return () => mediaQuery.removeEventListener('change', handleChange);
  }, []);
  
  return { theme, toggleTheme, isDark: theme === 'dark' };
}

// Usage
function App() {
  const { theme, toggleTheme } = useTheme();
  
  return (
    <div className={`app ${theme}`}>
      <button onClick={toggleTheme}>
        Switch to {theme === 'light' ? 'Dark' : 'Light'} Mode
      </button>
      {/* Rest of your app */}
    </div>
  );
}

Section 7: 2026-Specific Hook Questions

20. What are the new hooks introduced in React 19+?

Expected Answer (2026 Context):
"React 19 introduced several new hooks:

  1. use hook: For reading resources like promises or context

  2. useActionState: For handling form submissions with pending states

  3. useOptimistic: For optimistic UI updates

  4. useFormStatus: For form status information"

javascript
// use hook example
function UserProfile({ userId }) {
  const user = use(fetchUser(userId)); // Can read promises directly
  
  return (
    <div>
      <h1>{user.name}</h1>
      <p>{user.email}</p>
    </div>
  );
}

// useOptimistic hook example
function MessageList({ messages, sendMessage }) {
  const [optimisticMessages, addOptimisticMessage] = useOptimistic(
    messages,
    (state, newMessage) => [...state, { text: newMessage, sending: true }]
  );
  
  async function formAction(formData) {
    const message = formData.get('message');
    addOptimisticMessage(message);
    await sendMessage(message);
  }
  
  return (
    <>
      {optimisticMessages.map((msg, index) => (
        <div key={index}>
          {msg.text}
          {msg.sending && ' (Sending...)'}
        </div>
      ))}
      <form action={formAction}>
        <input type="text" name="message" />
        <button type="submit">Send</button>
      </form>
    </>
  );
}

21. How do hooks work with Concurrent Features in React 18+?

Expected Answer:
"With React 18's concurrent features, hooks need to be prepared for:

  1. Automatic batching of state updates

  2. Transition API for non-urgent updates

  3. Suspense for data fetching

javascript
function SearchComponent() {
  const [query, setQuery] = useState('');
  const [results, setResults] = useState([]);
  const [isPending, startTransition] = useTransition();
  
  const handleSearch = (newQuery) => {
    // Urgent update
    setQuery(newQuery);
    
    // Non-urgent update wrapped in transition
    startTransition(() => {
      fetchResults(newQuery).then(setResults);
    });
  };
  
  return (
    <div>
      <input 
        value={query}
        onChange={(e) => handleSearch(e.target.value)}
      />
      {isPending && <span>Searching...</span>}
      <Suspense fallback={<div>Loading results...</div>}>
        <ResultsList results={results} />
      </Suspense>
    </div>
  );
}

Section 8: Quick-Fire Questions (22-50)

22. What is the dependency array in useEffect?
"An array of values that the effect depends on. If any value changes between renders, the effect re-runs."

23. Can you call hooks inside loops?
"No, it violates the Rules of Hooks."

24. How to fetch data on component mount?
"Use useEffect with empty dependency array."

25. What's wrong with this code?

javascript
useEffect(async () => {
  const data = await fetchData();
  setData(data);
}, []);

"useEffect shouldn't return a promise. Use an async function inside."

26. How to update state based on previous state?
"Use the functional update pattern: setCount(prev => prev + 1)"

27. Can you use hooks in class components?
"No, hooks only work in function components or custom hooks."

28. How to avoid infinite loops in useEffect?
"Ensure dependency array includes all values used in the effect."

29. What does useEffect(() => {}, []) do?
"Runs once on mount, cleanup on unmount."

30. How to share logic between components?
"Extract it into a custom hook."

31. What is prop drilling and how to avoid it?
"Passing props through multiple levels. Avoid with Context API or state management."

32. How to force a component to re-render?
"Update its state or props. For emergency: useReducer with dummy state."

33. What is the difference between useMemo and React.memo?
"useMemo memoizes values, React.memo memoizes components."

34. How to handle errors in hooks?
"Use try/catch in useEffect or Error Boundaries."

35. Can you use multiple effects in one component?
"Yes, split logic into multiple useEffect calls."

36. How to update context value?
"Provide a value that includes both state and updater function."

37. What is the purpose of useRef in forms?
"To access DOM elements directly (like focusing input)."

38. How to debounce with hooks?
"Use useEffect with setTimeout and cleanup."

39. What is the stale closure problem?
"When a callback captures old state/props. Fix with dependency array or refs."

40. How to test custom hooks?
"Use @testing-library/react-hooks or test through components."

41. Can hooks replace Redux?
"For many cases, yes with useReducer + Context, but Redux has its place."

42. How to persist state to localStorage?
"Custom hook that syncs state with localStorage."

43. What is useDebugValue?
"Displays custom labels for custom hooks in React DevTools."

44. How to handle window resize with hooks?
"useEffect that adds/removes resize listener."

45. What is the difference between useCallback and useMemo?
"useCallback(fn, deps) = useMemo(() => fn, deps)"

46. How to implement infinite scroll with hooks?
"Intersection Observer + useEffect + useRef."

47. Can you conditionally call hooks?
"No, hooks must be called unconditionally."

48. How to cancel a fetch request with hooks?
"AbortController in useEffect cleanup."

49. What is the purpose of useImperativeHandle?
"Customize what's exposed when using ref on a component."

50. How to create a custom hook that uses other custom hooks?
"Yes, custom hooks can compose other hooks."


Conclusion: Mastering Hooks in 2026

Key Takeaways for Freshers:

  1. Master the fundamentals: useState, useEffect, useContext are 80% of daily use

  2. Understand performance hooks: Know when to use useMemo and useCallback

  3. Practice custom hooks: This is where you demonstrate advanced skills

  4. Follow the rules: Never break the Rules of Hooks

  5. Stay updated: React evolves quickly—know the latest features

Common Interview Expectations:

For freshers in 2026, interviewers expect:

  • Solid understanding of basic hooks

  • Ability to identify hook-related bugs

  • Practical knowledge of common patterns

  • Awareness of performance implications

  • Clean, readable code with proper dependencies

Final Preparation Tips:

  1. Build projects using only functional components and hooks

  2. Practice recreating common UI patterns with hooks

  3. Study popular custom hooks from open source

  4. Understand the "why" behind hook rules

  5. Stay curious about upcoming React features

Remember: In 2026, hooks aren't just a React feature—they're the standard way of thinking about React components. Master them, and you'll be well-prepared for the modern React ecosystem.


#career

Ready to Build Your Resume?

Create a professional resume that stands out to recruiters with our AI-powered builder.

50+ React Hooks Interview Questions for Freshers (2026) | Hirecta Interview Prep | Hirecta