FrontendDeveloper.in

React Interview Questions

  • Question 286

    How does useContext works? Explain with an example

    The useContext hook can be used for authentication state management across multiple components and pages in a React application.

    Let's build a simple authentication flow with:

    • Login and Logout buttons
    • Global AuthContext to share state
    • Components that can access and update auth status

    1. Create the Auth Context:

    You can define AuthProvider which holds and provides user, login(), and logout() via context.

    // AuthContext.js
    import React, { createContext, useContext, useState } from 'react';
    
    const AuthContext = createContext();
    
    export function AuthProvider({ children }) {
    const [user, setUser] = useState(null);
    
    const login = (username) => setUser({ name: username });
    const logout = () => setUser(null);
    
    return (
    <AuthContext.Provider value={{ user, login, logout }}>
    {children}
    </AuthContext.Provider>
    );
    }
    
    // Custom hook for cleaner usage
    export const useAuth = () => useContext(AuthContext);
    

    2. Wrap Your App with the Provider:

    Wrap the above created provider in main App.js file

    // App.js
    import React from 'react';
    import { AuthProvider } from './AuthContext';
    import HomePage from './HomePage';
    import Dashboard from './Dashboard';
    
    function App() {
    return (
    <AuthProvider>
    <HomePage />
    <Dashboard />
    </AuthProvider>
    );
    }
    
    export default App;
    

    3. Home page with login: Read or access user and login details through custom useAuth hook and use it inside home page.

    // HomePage.js
    import React from 'react';
    import { useAuth } from './AuthContext';
    
    function HomePage() {
    const { user, login } = useAuth();
    
    return (
    <h1>Home</h1>
    {user ? (
    ) : (
    <button onClick={() => login('Alice')}>Login</button>
    )}
    );
    }
    
    export default HomePage;
    

    4. Dashboard with logout: Read or access user and logout details from useAuth custom hook and use it inside dashboard page.

    // Dashboard.js
    import React from 'react';
    import { useAuth } from './AuthContext';
    
    function Dashboard() {
    const { user, logout } = useAuth();
    
    if (!user) {
    return <p>Please login to view the dashboard.</p>;
    }
    
    return (
    <h2>Dashboard</h2>
    <button onClick={logout}>Logout</button>
    );
    }
    
    export default Dashboard;
    
  • Question 287

    Can You Use Multiple Contexts in One Component?

    Yes, it is possible. You can use multiple contexts inside the same component by calling useContext multiple times, once for each context.

    It can be achieved with below steps,

    • Create multiple contexts using createContext().
    • Wrap your component tree with multiple <Provider>s.
    • Call useContext() separately for each context in the same component.

    Example: Using ThemeContext and UserContext Together

    import React, { createContext, useContext } from 'react';
    
     // Step 1: Create two contexts
     const ThemeContext = createContext();
     const UserContext = createContext();
    
     function Dashboard() {
    // Step 2: Use both contexts
    const theme = useContext(ThemeContext);
    const user = useContext(UserContext);
    
    return (
    <h1>Welcome, {user.name}</h1>
    );
     }
    
     // Step 3: Provide both contexts
     function App() {
    return (
    <ThemeContext.Provider value="dark">
    <UserContext.Provider value={{ name: 'Sudheer' }}>
    <Dashboard />
    </UserContext.Provider>
    </ThemeContext.Provider>
    );
     }
    
     export default App;
    
  • Question 288

    What's a common pitfall when using useContext with objects?

    A common pitfall when using useContext with objects is triggering unnecessary re-renders across all consuming components — even when only part of the context value changes.

    When you provide an object as the context value, React compares the entire object reference. If the object changes (even slightly), React assumes the whole context has changed, and all components using useContext(MyContext) will re-render, regardless of whether they use the part that changed.

    Example:

    const MyContext = React.createContext();
    
    function MyProvider({ children }) {
    const [user, setUser] = useState(null);
    const [theme, setTheme] = useState('light');
    
    // This causes all consumers to re-render on any state change
    const contextValue = { user, setUser, theme, setTheme };
    
    return (
    <MyContext.Provider value={contextValue}>
    {children}
    </MyContext.Provider>
    );
    }
    

    In this case, a change in theme will also trigger a re-render in components that only care about user.

    This issue can be fixed in two ways,

    1. Split Contexts Create separate contexts for unrelated pieces of state:

    const UserContext = React.createContext();
    const ThemeContext = React.createContext();
    

    2. Memoize Context Value Use useMemo to prevent unnecessary re-renders:

    const contextValue = useMemo(() => ({ user, setUser, theme, setTheme }), [user, theme]);
    

    However, this only helps if the object structure and dependencies are well controlled.

  • Question 289

    What would the context value be for no matching provider?

    When a component calls useContext(SomeContext) but no matching <SomeContext.Provider> is present higher up in the component tree, the default value passed to React.createContext(defaultValue) is returned.

    const ThemeContext = React.createContext('light'); // 'light' is the default value
    
    function ThemedComponent() {
    const theme = useContext(ThemeContext);
    return <div>Current theme: {theme}</div>;
    }
    
    // No ThemeContext.Provider anywhere in the tree
    

    In this case, theme will be 'light'. It's the default value you provided when you created the context.

    Note: If you don’t specify a default value, the context value will be undefined when used without a provider:

    const AuthContext = React.createContext(); // No default
    
    function Profile() {
    const auth = useContext(AuthContext);
    // auth will be undefined if there's no AuthContext.Provider
    }
    
  • Question 290

    How do reactive dependencies in the useEffect dependency array affect its execution behavior?

    The useEffect hook accepts an optional dependencies argument that accepts an array of reactive values. The dependency array determines when the effect runs. i.e, It makes useEffect reactive to changes in specified values.

    How Dependency Array Affects Behavior

    1. Empty Dependency Array: **[]**
    useEffect(() => {
    // runs once after the initial render
    }, []);
    
    • Effect runs only once (like componentDidMount).
    • Ignores all state/prop changes.
    1. With Specific Dependencies: **[count, user]**
    useEffect(() => {
    // runs after initial render
    // AND whenever `count` or `user` changes
    }, [count, user]);
    
    • Effect runs on first render, and
    • Again every time any dependency value changes.
    1. No Dependency Array (Omitted)
    useEffect(() => {
    // runs after **every** render
    });
    
    • Effect runs after every render, regardless of what changed.
    • Can lead to performance issues if not used carefully.

    React uses shallow comparison of the dependencies. If any value has changed (!==), the effect will re-run.

    Note: This hook works well when dependencies are primitives or memoized objects/functions.

  • Question 291

    When and how often does React invoke the setup and cleanup functions inside a useEffect hook?

    1. Setup Function Execution (useEffect)

    The setup function (or the main function) you pass to useEffect runs at specific points:

    1. After the component is mounted (if the dependency array is empty [])

    2. After every render (if no dependency array is provided)

    3. After a dependency value changes (if the dependency array contains variables)

    4. Cleanup Function Execution (Returned function from useEffect)

    The cleanup function is called before the effect is re-executed and when the component unmounts.

  • Question 292

    What happens if you return a Promise from useEffect??

    You should NOT return a Promise from useEffect. React expects the function passed to useEffect to return either nothing (undefined) or a cleanup function (synchronous function). i.e, It does not expect or handle a returned Promise. If you still return a Promise, React will ignore it silently, and it may lead to bugs or warnings in strict mode.

    Incorrect:

    useEffect(async () => {
    await fetchData(); // ❌ useEffect shouldn't be async
    }, []);
    

    Correct:

    useEffect(() => {
    const fetchData = async () => {
    const res = await fetch('/api');
    const data = await res.json();
    setData(data);
    };
    
    fetchData();
    }, []);
    
  • Question 293

    Can you have multiple useEffect hooks in a single component?

    Yes, multiple useEffect hooks are allowed and recommended when you want to separate concerns.

    useEffect(() => {
    // Handles API fetch
    }, []);
    
    useEffect(() => {
    // Handles event listeners
    }, []);
    

    Each effect runs independently and helps make code modular and easier to debug.

  • Question 294

    How to prevent infinite loops with useEffect?

    Infinite loops happen when the effect updates state that’s listed in its own dependency array, which causes the effect to re-run, updating state again and so on.

    Infinite loop scenario:

    useEffect(() => {
    setCount(count + 1);
    }, [count]); // Triggers again every time count updates
    

    You need to ensure that setState calls do not depend on values that cause the effect to rerun, or isolate them with a guard.

    useEffect(() => {
    if (count < 5) {
    setCount(count + 1);
    }
    }, [count]);
    
  • Question 295

    What are the usecases of useLayoutEffect?

    You need to use useLayoutEffect when your effect must run before the browser paints, such as:

    • Reading layout measurements (e.g., element size, scroll position)
    • Synchronously applying DOM styles to prevent visual flicker
    • Animating layout or transitions
    • Integrating with third-party libraries that require DOM manipulation

    If there's no visual or layout dependency, prefer useEffect — it's more performance-friendly.

    useLayoutEffect(() => {
    const width = divRef.current.offsetWidth;
    if (width < 400) {
    divRef.current.style.background = 'blue'; // prevents flicker
    }
    }, []);
    
  • Question 296

    How does useLayoutEffect work during server-side rendering (SSR)?

    The useLayoutEffect hook does not run on the server, because there is no DOM. React issues a warning in server environments like Next.js if useLayoutEffect is used directly.

    This can be mitigated using a conditional polyfill:

    const useIsomorphicLayoutEffect =
    typeof window !== 'undefined' ? useLayoutEffect : useEffect;
    

    i.e, Use useIsomorphicLayoutEffect in components that render both on client and server.

  • Question 297

    What happens if you use useLayoutEffect for non-layout logic?

    Using useLayoutEffect for logic unrelated to layout or visual DOM changes (such as logging, data fetching, or analytics) is not recommended. It can lead to performance issues or even unexpected behavior.

    Example: Anti-pattern

    useLayoutEffect(() => {
    console.log("Tracking analytics");
    fetch('/log-page-view');
    }, []);
    

    The above usage delays the paint of the UI just to send a network request, which could (and should) be done after paint using useEffect.

  • Question 298

    How does useLayoutEffect cause layout thrashing?

    The useLayoutEffect can cause layout thrashing when you repeatedly read and write to the DOM in ways that force the browser to recalculate layout multiple times per frame. This is because useLayoutEffect runs before the browser paints, these reflows happen synchronously, blocking rendering and degrading performance.

    Example:

    function ThrashingComponent() {
    const ref = useRef();
    
    useLayoutEffect(() => {
    const height = ref.current.offsetHeight; //Read
    ref.current.style.height = height + 20 + 'px'; //Write
    const newHeight = ref.current.offsetHeight; //Read again — forces reflow
    }, []);
    
    return <div ref={ref}>Hello</div>;
    }
    

    In the above code, each read/write cycle triggers synchronous reflows, blocking the main thread and delays UI rendering.

    This issue can be avoided by batching your DOM reads and writes and prevent unnecessary reads after writes.

  • Question 299

    How Do You Use useRef to Access a DOM Element in React? Give an example.

    The useRef hook is commonly used in React to directly reference and interact with DOM elements — like focusing an input, scrolling to a section, or controlling media elements.

    When you assign a ref to a DOM element using useRef, React gives you access to the underlying DOM node via the .current property of the ref object.

    Example: Focus an input

    import React, { useRef } from 'react';
    
    function FocusInput() {
    const inputRef = useRef(null); // create the ref
    
    const handleFocus = () => {
    inputRef.current.focus(); // access DOM element and focus it
    };
    
    return (
    <input type="text" ref={inputRef} />
    <button onClick={handleFocus}>Focus the input</button>
    );
    }
    

    Note: The DOM reference is only available after the component has mounted — typically accessed in useEffect or event handlers.

  • Question 300

    Can you use useRef to persist values across renders??

    Yes, you can use useRef to persist values across renders in React. Unlike useState, changing .current does not cause re-renders, but the value is preserved across renders.

    Example:

    function Timer() {
    const renderCount = useRef(0);
    useEffect(() => {
    renderCount.current++;
    console.log("Render count:", renderCount.current);
    });
    
    return <div>Check console for render count.</div>;
    }
    
Get LinkedIn Premium at Rs 399