Top 50+ React Coding Interview Questions and Answers
| Summary: React remains widely used for building interactive web applications, making practical React skills valuable for frontend development roles. Strong interview preparation can help you demonstrate your ability to solve coding problems, debug applications, and make sound development decisions. |
React interviews in 2026 often go beyond basic syntax and assess how well candidates apply React concepts to real-world development problems. You may be asked to build components, manage state, handle forms, optimize performance, work with APIs, or troubleshoot rendering issues. For experienced roles, interviewers may also explore hooks, component architecture, state management, and modern React patterns.
This guide covers commonly asked React coding interview questions with practical answers and explanations. It will help you understand the logic behind each solution and prepare confidently for technical discussions.
React Coding Interview Questions and Answers for Freshers
If you are preparing for your first React developer role, practicing React interview coding questions can help you build confidence with real coding tasks. This section covers beginner-friendly questions on components, props, state, hooks, events, and basic problem-solving that are commonly asked in fresher interviews.
| You know? Around 40% of developers worldwide use React, making it one of the most widely adopted web technologies, according to the Stack Overflow Developer Survey. |
Q1. In React, what is the difference between a functional component from a class component?
Sample Answer: In React, the main difference between functional and class components is their syntax, state management, lifecycle handling, and overall approach to component construction. Hooks are used by functional components to control their state and side effects. A class component, on the other hand, makes use of ES6 classes and manages lifecycle methods using specified functions.
In React, the key difference between functional and class components lies in how they manage state and handle lifecycle events.
- Functional components are simpler and use hooks (like useState, useEffect) to manage state and side effects.
- Class components use ES6 class syntax and manage state with this.state, updating it with this.setState(). Lifecycle methods like componentDidMount() are used for side effects.
Functional Component: Here is the code demonstrating this:
function Counter() {
const [count, setCount] = React.useState(0);
return <button onClick={() => setCount(count + 1)}>Count: {count}</button>;
}
Class Component: Here is the code demonstrating this:
class Counter extends React.Component {
state = { count: 0 };
render() {
return (
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Count: {this.state.count}
</button>
);
}
}


Q2. How do you manage state in a functional component using hooks?
Sample Answer: The ‘useState’ hook allows functional components in React to manage state. This hook allows you to add state variables to your component and update them, triggering re-renders as needed. This removes the need to use class components for state management.
Here is the code demonstrating this:
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<h3>Count: {count}</h3>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
</div>
);
}
export default Counter;
Q3. What is the purpose of the ‘useEffect’ hook, and when does it run?
Sample Answer: The React ‘useEffect’ hook is designed to manage side effects in functional components, such as data fetching, direct DOM manipulation, and subscription setup. It essentially substitutes class components’ lifecycle methods such as ‘componentDidMount’, ‘componentDidUpdate’, and ‘componentWillUnmount’.
Here is the code demonstrating this:
import React, { useState, useEffect } from 'react';
function Timer() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log('Effect ran. Count:', count);
return () => console.log('Cleanup on unmount or before next run.');
}, [count]);
return (
<button onClick={() => setCount(count + 1)}>
Count: {count}
</button>
);
}
export default Timer;
Also Read: React JS Coding Interview Questions
Q4. What are synthetic events in React, and how do they differ from native DOM events?
Sample Answer: Synthetic events are React’s cross-browser wrapper around native DOM events. React normalizes events so they behave consistently across all browsers, and it pools these event objects for performance. You handle them the same way you’d handle native events, but with camelCase naming (like ‘onClick’ instead of ‘onclick’).
Here is the code demonstrating this:
| import React from ‘react’; function ClickTracker() { const handleClick = (e) => { console.log(‘Event type:’, e.type); console.log(‘Is synthetic:’, e.nativeEvent !== e); }; return <button onClick={handleClick}>Click me</button>; } export default ClickTracker; |
Pro Tip: Practicing React JS coding interview questions and answers helps you sound confident in the interview room, but recruiters also want to see proof you can build things. The best way to solidify your knowledge is by building real applications. Check out our guide on React projects for beginners to start building hands-on projects you can add to your resume and discuss in your interviews.
Q5. What are props in React? Can you pass functions as props?
Sample Answer: Props (short for “properties”) in React are a way to transmit data from a parent component to a child component. They are simply arguments supplied to React components in the same way that arguments are passed to functions in JavaScript. Props make components more dynamic and reusable by letting them receive external data and settings.
Here is the code demonstrating this:
import React from 'react';
function Child({ name, greet }) {
return <button onClick={greet}>Hello, {name}!</button>;
}
function App() {
return <Child name="Alice" greet={() => alert('Hi!')} />;
}
export default App;
Q6. How do you render a list of items dynamically from an array in React?
Sample Answer: You can render a list dynamically by using JavaScript’s map() method to create JSX elements from an array. Each item should have a unique and stable key prop, preferably an ID from the data. React uses the key to identify individual items when the list is updated.
Here is an example:
| import React from ‘react’; function FruitList() { const fruits = [ { id: 1, name: ‘Apple’ }, { id: 2, name: ‘Banana’ }, { id: 3, name: ‘Mango’ } ]; return ( <ul> {fruits.map((fruit) => ( <li key={fruit.id}>{fruit.name}</li> ))} </ul> ); } export default FruitList; |
Q7. What is the difference between ‘useState’ and ‘useRef’?
Sample Answer: useState and useRef both allow values to persist between renders, but they serve different purposes. Updating a state value with its setter function causes React to re-render the component, allowing the updated value to appear in the UI. Updating ref.current does not trigger a re-render.
useRef is commonly used to access DOM elements or to store mutable values that persist between renders but do not directly update the UI.
Here is an example:
| import React, { useRef, useState } from ‘react’; function FocusInput() { const [text, setText] = useState(”); const inputRef = useRef(null); const focusInput = () => { inputRef.current?.focus(); }; return ( <div> <input ref={inputRef} value={text} onChange={(e) => setText(e.target.value)} /> <button onClick={focusInput}>Focus Input</button> </div> ); } export default FocusInput; |
Here, useState manages the input value displayed in the UI, while useRef provides access to the input element without causing a re-render when ref.current changes.
Q8. How do you lift state in React? Why is it useful?
Sample Answer: Lifting state is a React strategy for managing shared state across several components by shifting state from a child component to its nearest common ancestor. This is useful for synchronizing data between child components that share the same state.
Here is the code demonstrating this:
import React, { useState } from 'react';
function Parent() {
const [text, setText] = useState('');
return (
<>
<ChildInput onChange={setText} />
<ChildDisplay value={text} />
</>
);
}
function ChildInput({ onChange }) {
return (
<input onChange={(e) => onChange(e.target.value)} />
);
}
function ChildDisplay({ value }) {
return <p>You typed: {value}</p>;
}
export default Parent;
Q9. What happens if you update the state directly without using ‘setState’ or set functions?
Sample Answer: If one updates the state directly without using setState or hook-based set functions, React will not detect the change and will not trigger a re-render. This can lead to inconsistent UI and unexpected behavior in the application.
Here is the code demonstrating this:
import React, { useState } from 'react';
function BadUpdate() {
const [count, setCount] = useState(0);
const wrongUpdate = () => {
let newCount = count + 1; // React doesn't know this happened
console.log('Count incremented to:', newCount);
// Not calling setCount, so no re-render
};
return (
<button onClick={wrongUpdate}>
Count: {count}
</button>
);
}
export default BadUpdate;
Q10. How do you pass data from a child component to a parent component?
Sample Answer: In React, you pass data from a child component to a parent component by using a callback function. The parent defines the function and passes it to the child through props. The child then calls the function with the required data.
Here is the code demonstrating this:
import React, { useState } from 'react';
function Parent() {
const [msg, setMsg] = useState('');
return (
<>
<Child sendData={setMsg} />
<p>Message: {msg}</p>
</>
);
}
function Child({ sendData }) {
return (
<button onClick={() => sendData('Hello from Child')}>
Send Message
</button>
);
}
export default Parent;
Q11. What is conditional rendering in React?
Sample Answer: Conditional rendering in React is the practice of dynamically displaying different UI elements or components in response to specified conditions. This enables the construction of interactive, responsive user interfaces that adapt to changes in application status, user input, or data.
Here is the code demonstrating this:
import React, { useState } from 'react';
function Greeting() {
const [isLoggedIn, setIsLoggedIn] = useState(false);
return (
<div>
{isLoggedIn ? <p>Welcome back!</p> : <p>Please log in.</p>}
<button onClick={() => setIsLoggedIn(!isLoggedIn)}>
Toggle Login
</button>
</div>
);
}
export default Greeting;
Q12. How do you prevent unnecessary re-renders in a React component?
Sample Answer: You can prevent unnecessary re-renders in a React component by using ‘React.memo’ for functional components, ‘useMemo’ to memoize values, and ‘useCallback’ to memoize functions. Ensure you update the state only when necessary and pass stable props.
Here is the code demonstrating this:
import React, { useState, memo } from 'react';
const Child = memo(({ name }) => {
console.log('Child rendered');
return <p>Hello, {name}!</p>;
});
function Parent() {
const [count, setCount] = useState(0);
return (
<>
<Child name="Alice" />
<button onClick={() => setCount(count + 1)}>
Increment
</button>
</>
);
}
export default Parent;
Q13. What are fragments in React, and why are they used?
Sample Answer: Fragments are a React feature that allows a component to return multiple elements without adding a new node to the Document Object Model. They are used to group elements without introducing additional DOM nodes, hence keeping the structure clean and avoiding superfluous wrappers.
Here is the code demonstrating this:
import React from 'react';
function List() {
return (
<>
<li>Item 1</li>
<li>Item 2</li>
</>
);
}
export default List;
Q14. How do you handle form submission in a React component?
Sample Answer: You can handle form submission in a React component by using an ‘onSubmit’ event handler. Form submission in a React component primarily involves controlling the form’s state and preventing the browser’s default behavior.
Here is the code demonstrating this:
import React, { useState } from 'react';
function MyForm() {
const [name, setName] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
alert(`Submitted: ${name}`);
};
return (
<form onSubmit={handleSubmit}>
<input
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Enter name"
/>
<button type="submit">Submit</button>
</form>
);
}
export default MyForm;
React Coding Interview Questions and Answers for Mid-Level Candidates
For mid-level React roles, React interview coding questions often test more than basic syntax. Interviewers may assess your understanding of hooks, state management, component design, API integration, performance, and debugging. This section covers practical coding questions to help you prepare for real-world React development challenges.
Q15. How do you optimize a React component that renders frequently with the same props?
Sample Answer: Memoization is the primary means of optimizing a React component that frequently re-renders with the same props. This solution avoids needless re-renders by caching the component’s output and re-rendering only when its props change.
Here is the code demonstrating this:
import React, { memo } from 'react';
const Greeting = memo(({ name }) => {
console.log('Greeting rendered');
return <p>Hello, {name}!</p>;
});
export default Greeting;
Q16. What is the difference between ‘useEffect’ and ‘useLayoutEffect’?
Sample Answer: The primary distinction between ‘useEffect’ and ‘useLayoutEffect’ in React is when the effects are executed relative to the browser’s rendering process. ‘useEffect’ runs asynchronously after the component has been painted on the screen, whereas ‘useLayoutEffect’ runs synchronously before the browser paints, guaranteeing that the effect is applied before the user sees anything.
Here is the code demonstrating this:
import React, { useEffect, useLayoutEffect } from 'react';
function Demo() {
useLayoutEffect(() => {
console.log('useLayoutEffect runs first');
});
useEffect(() => {
console.log('useEffect runs after paint');
});
return <p>Check the console logs!</p>;
}
export default Demo;
Q17. How do you manage global state in a React app without using external libraries?
Sample Answer: In React, you can manage global state without external libraries by using the Context API. This involves creating a context, wrapping the application with a context provider, and accessing the shared state across components using the ‘useContext’ hook.
Here is the code demonstrating this:
import React, { createContext, useState, useContext } from 'react';
// Create Context
const UserContext = createContext();
function App() {
const [user, setUser] = useState('Alice');
return (
<UserContext.Provider value={user}>
<Child />
</UserContext.Provider>
);
}
function Child() {
const user = useContext(UserContext);
return <p>User: {user}</p>;
}
export default App;
Q18. How do you handle side effects in a React application?
Sample Answer: In React, side effects are typically handled by the ‘useEffect’ hook. After a component has rendered, you may use this hook to interact with the outside world by fetching data, setting up subscriptions, or directly modifying the DOM.
Here is the code demonstrating this:
import React, { useEffect } from 'react';
function FetchData() {
useEffect(() => {
console.log('Side effect: Fetching data...');
// e.g. fetch('api/data') ...
}, []);
return <p>Check the console for side effects!</p>;
}
export default FetchData;
Also Read: TCS React JS Interview Questions
Q19. What causes memory leaks in React, and how do you prevent them in components with side effects?
Sample Answer: Memory leaks in React happen when components or methods keep references to data or resources that are no longer required, preventing them from being garbage collected. This causes a progressive increase in memory use, affecting application performance. You can avoid them by cleaning up any side effects in the ‘useEffect’ return method, such as resetting timers or canceling fetch requests.
Here is the code demonstrating this:
import React, { useEffect } from 'react';
function Timer() {
useEffect(() => {
const id = setInterval(() => {
console.log('Running...');
}, 1000);
return () => clearInterval(id);
}, []);
return <p>Timer running. Check console.</p>;
}
export default Timer;
Q20. How do you implement code splitting in a React project?
Sample Answer: In a React project, code splitting is generally implemented with ‘React.lazy’ and Suspense, which are frequently used in conjunction with dynamic import() declarations. This strategy loads components only when required, reducing the initial bundle size and boosting application speed.
Here is the code demonstrating this:
import React, { Suspense, lazy } from 'react';
const LazyComponent = lazy(() => import('./MyComponent'));
function App() {
return (
<Suspense fallback={<p>Loading...</p>}>
<LazyComponent />
</Suspense>
);
}
export default App;
Q21. What is the difference between ‘useCallback’ and ‘useMemo’? When should you use each?
Sample Answer: The ‘useCallback’ hook memoizes functions, while ‘useMemo’ memoizes computed values. Use ‘useCallback’ when you want to prevent unnecessary re-renders caused by function references. Use ‘useMemo’ to avoid recalculating complex values unless specific
dependencies change.
Here is the code demonstrating ‘useCallback’ in React:
import React, { useState, useCallback } from 'react';
function ButtonComponent({ onClick }) {
console.log('ButtonComponent rendered');
return <button onClick={onClick}>Click me</button>;
}
function App() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
console.log('Button clicked!');
}, []);
return (
<>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
<ButtonComponent onClick={handleClick} />
</>
);
}
export default App;
Here is the code demonstrating ‘useMemo’ in React:
import React, { useState, useMemo } from 'react';
function App() {
const [count, setCount] = useState(0);
const expensiveValue = useMemo(() => {
console.log('Calculating...');
return count * 2;
}, [count]);
return (
<>
<p>Expensive Value: {expensiveValue}</p>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
</>
);
}
export default App;
Q22. How does React reconcile changes in the virtual DOM?
Sample Answer: React employs a reconciliation method to efficiently update the real DOM in response to changes in the virtual DOM. This procedure entails comparing the new virtual DOM to the previous one to determine the smallest number of changes required to update the real DOM, hence minimizing costly DOM manipulations.
Here is the code demonstrating this:
import React, { useState } from 'react';
function ReconcileDemo() {
const [text, setText] = useState('Hello');
return (
<div>
<p>{text}</p>
<button onClick={() => setText('Hello World')}>
Update Text
</button>
</div>
);
}
export default ReconcileDemo;
Q23. How can you create a custom hook?
Sample Answer: To construct a custom hook in React, you must specify a JavaScript function that begins with the prefix ‘use’ and may leverage other built-in or custom hooks to encapsulate reusable logic. The function should return values (such as state or functions) that the component employing the hook can use.
Here is the code demonstrating this:
import React, { useState } from 'react';
// Custom hook
function useCounter(initialValue = 0) {
const [count, setCount] = useState(initialValue);
const increment = () => setCount(count + 1);
return [count, increment];
}
// Using the custom hook
function Counter() {
const [count, increment] = useCounter();
return (
<button onClick={increment}>
Count: {count}
</button>
);
}
export default Counter;
Q24. What is the role of the dependency array in the ‘useEffect hook?
Sample Answer: In React, the dependency array in the ‘useEffect’ hook determines when the effect function is executed. If the array is empty, the effect is applied only after the initial render. If the array contains variables, the effect is triggered whenever any of those variables change. If the dependency array is completely omitted, the effect is applied after each render.
Here is the code demonstrating this:
import React, { useState, useEffect } from 'react';
function Demo() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log('Runs when count changes:', count);
}, [count]);
return <button onClick={() => setCount(count + 1)}>Count: {count}</button>;
}
export default Demo;
Q25. How do you handle API errors and loading states during data fetch in a React component?
Sample Answer: To handle API errors and loading states in a React component, use ‘useState’ to manage ‘loading’, ‘error’, and ‘data’. Update ‘loading’ before and after the fetch, catch errors to set the error state, and display appropriate UI feedback.
Here is the code demonstrating this:
import React, { useState, useEffect } from 'react';
function DataFetcher() {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetch('https://api.example.com/data')
.then((res) => res.json())
.then(setData)
.catch(setError)
.finally(() => setLoading(false));
}, []);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error occurred.</p>;
return <p>Data: {JSON.stringify(data)}</p>;
}
export default DataFetcher;
Q26. How do you debounce user input in a search field using hooks?
Sample Answer: To debounce user input in a search box using hooks, track it using ‘useState’ and postpone execution with ‘useEffect’ and ‘setTimeout’. Clear the timeout in the cleanup
function to avoid multiple triggers and save API calls.
Here is the code demonstrating this:
import React, { useState, useEffect } from 'react';
function SearchBox() {
const [query, setQuery] = useState('');
const [debounced, setDebounced] = useState('');
useEffect(() => {
const id = setTimeout(() => setDebounced(query), 500);
return () => clearTimeout(id);
}, [query]);
return (
<input
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder={`Search: ${debounced}`}
/>
);
}
export default SearchBox;
Q27. How do you share logic between components without repeating code?
Sample Answer:
You can share logic between components without repeating code by creating custom hooks. Custom hooks allow you to extract reusable logic into a separate function that can be imported and used across multiple components, keeping code clean and maintainable.
Here is the code demonstrating this:
import React, { useState } from 'react';
function useToggle() {
const [on, setOn] = useState(false);
return [on, () => setOn(!on)];
}
function Button() {
const [on, toggle] = useToggle();
return <button onClick={toggle}>{on ? 'On' : 'Off'}</button>;
}
export default Button;
Q28. What is the difference between controlled and uncontrolled components, and when should you use each?
Sample Answer: Controlled components in React handle their state, whereas uncontrolled components rely on the DOM. Controlled components are preferable for forms that require input validation, dynamic input enablement/disabling, or complicated interaction implementation. Uncontrolled components are appropriate for simple forms or for integrating with existing non-React code.
Here is the code demonstrating this:
import React, { useState } from 'react';
function ControlledInput() {
const [value, setValue] = useState('');
return (
<input
value={value}
onChange={(e) => setValue(e.target.value)}
placeholder="Controlled"
/>
);
}
export default ControlledInput;
Q29. How do you avoid stale state when updating React state multiple times?
Sample Answer: When the next state depends on the previous state, use the functional form of the state setter. React passes the updater function the pending state from the previous update, making this approach reliable when multiple state updates are queued together.
For example, if you want to increase a counter three times in one event, use a functional updater for each update:
| import React, { useState } from ‘react’; function Counter() { const [count, setCount] = useState(0); const incrementThreeTimes = () => { setCount(prevCount => prevCount + 1); setCount(prevCount => prevCount + 1); setCount(prevCount => prevCount + 1); }; return ( <> <p>Count: {count}</p> <button onClick={incrementThreeTimes}> Add 3 </button> </> ); } export default Counter; |
Here, each updater receives the result of the previous update, so the counter increases from 0 to 3.
Q30. When should you use useReducer instead of useState?
Sample Answer: useState is often a good choice for simple state and straightforward updates. useReducer can be more useful when a component has complex state logic, multiple related values, or several ways to update the state. A reducer keeps state transitions in one place, which can make complex components easier to understand, maintain, and test.
For example:
| import React, { useReducer } from ‘react’; function reducer(state, action) { switch (action.type) { case ‘increment’: return { count: state.count + 1 }; case 'decrement': return { count: state.count - 1 }; default: return state;} } function Counter() { const [state, dispatch] = useReducer(reducer, { count: 0 }); return ( <> Count: {state.count} <button onClick={() => dispatch({ type: 'increment' })}> + </button> <button onClick={() => dispatch({ type: 'decrement' })}> - </button> </>); } export default Counter; |
Here, dispatch sends an action to the reducer, which determines how the state should change.
Q31. How would you create a modal using React portal?
Sample Answer: React Portals allow you to render a component into a different DOM node from its usual parent while keeping it part of the same React tree. They are commonly used for modals, dialogs, tooltips, and overlays because they can help avoid layout and stacking issues caused by parent elements.
For example, if your HTML contains a dedicated element such as <div id=”modal-root”></div>, you can render the modal into it using createPortal:
| import { createPortal } from ‘react-dom’; function Modal({ onClose }) { const modalRoot = document.getElementById(‘modal-root’); if (!modalRoot) { return null; } return createPortal( <div className=”modal” role=”dialog” aria-modal=”true” aria-labelledby=”modal-title” > <h2 id=”modal-title”>Confirm Action</h2> <button onClick={onClose}> Close </button> </div>, modalRoot ); } export default Modal; |
The portal changes where the modal is placed in the DOM. However, it remains part of the React component tree. In a production application, a modal should also consider accessibility requirements such as keyboard handling, focus management, and returning focus to the element that opened the modal.
React Coding Interview Questions and Answers for Experienced Professionals
Once you know the React fundamentals, interviews often focus on how you apply them. You may be asked to choose between hooks, fix unnecessary re-renders, handle stale closures, or improve performance. These questions test your ability to make practical decisions. Here are some React interview questions and answers for experienced candidates:
Q32. How would you prevent race conditions when fetching data in a React component?
Sample Answer:
A race condition can occur when a component starts multiple requests and an older request finishes after a newer one, causing outdated data to overwrite the latest result. One way to prevent this is to use the AbortController tool to cancel the previous request when the component’s dependencies change or when it unmounts.
For example:
| import React, { useEffect, useState } from ‘react’; function UserProfile({ userId }) { const [user, setUser] = useState(null); const [error, setError] = useState(null); useEffect(() => { const controller = new AbortController(); async function fetchUser() { try { setError(null); const response = await fetch( `https://api.example.com/users/${userId}`, { signal: controller.signal } ); if (!response.ok) { throw new Error(‘Failed to fetch user’); } const data = await response.json(); setUser(data); } catch (error) { if (error.name !== ‘AbortError’) { setError(error.message); } } } fetchUser(); return () => { controller.abort(); }; }, [userId]); if (error) { return <p>Error: {error}</p>; } if (!user) { return <p>Loading…</p>; } return <h2>{user.name}</h2>; } export default UserProfile; |
Here, when userId changes, React runs the cleanup function for the previous effect and aborts its request. This prevents an outdated request from continuing unnecessarily and helps ensure that stale results do not replace data for the latest request. In larger applications, data-fetching libraries can also provide request deduplication, caching, and race-condition handling.
Also Read: Infosys React Interview Questions
Q33. How do you preserve component state when rendering dynamic components?
Sample Answer: When rendering components dynamically, React preserves a component’s state as long as it remains at the same position in the component tree and keeps the same identity. If you switch between different component types or change their keys, React may unmount the previous component and reset its state.
For example, if multiple components are selected dynamically, you can give each component a stable identity and render it based on the selected value:
| import React, { useState } from ‘react’; function Profile() { const [name, setName] = useState(”); return ( <div> <h3>Profile</h3> <input value={name} onChange={(e) => setName(e.target.value)} placeholder=”Enter your name” /> </div> ); } function Settings() { const [email, setEmail] = useState(”); return ( <div> <h3>Settings</h3> <input value={email} onChange={(e) => setEmail(e.target.value)} placeholder=”Enter your email” /> </div> ); } function App() { const [activeTab, setActiveTab] = useState(‘profile’); const components = { profile: <Profile />, settings: <Settings /> }; return ( <div> <button onClick={() => setActiveTab(‘profile’)}> Profile </button> <button onClick={() => setActiveTab(‘settings’)}> Settings </button> {components[activeTab]} </div> ); } export default App; |
In this example, switching between the tabs causes the inactive component to be removed from the tree, so its local state will not be preserved when you switch back. If the requirement is to preserve each tab’s state while it is hidden, keep both components mounted and control their visibility instead.
For dynamic lists of components, use stable keys based on item identity, rather than array indexes, to help React preserve the correct component state when items are reordered or changed.
Q34. How would you implement optimistic UI updates in React?
Sample Answer: An optimistic UI update changes the interface immediately, before the server confirms that an operation was successful. This makes the application feel faster and more responsive. If the request fails, you should roll back the UI to its previous state or show an appropriate error.
For example, you can optimistically update a like count while sending the request to the server:
| import React, { useState } from ‘react’; function LikeButton() { const [liked, setLiked] = useState(false); const [count, setCount] = useState(10); const handleLike = async () => { const previousLiked = liked; const previousCount = count; // Update the UI immediately setLiked(true); setCount(prevCount => prevCount + 1); try { const response = await fetch(‘/api/like’, { method: ‘POST’ }); if (!response.ok) { throw new Error(‘Failed to update like’); } } catch (error) { // Roll back if the request fails setLiked(previousLiked); setCount(previousCount); console.error(error); } }; return ( <button onClick={handleLike} disabled={liked}> {liked ? ‘Liked’ : ‘Like’} ({count}) </button> ); } export default LikeButton; |
Here, the UI updates immediately instead of waiting for the server response. If the API request fails, the previous state is restored. In a production application, optimistic updates should also account for duplicate submissions, loading or pending states, and possible server-side validation failures.
Q35. How do you handle performance bottlenecks in large React applications?
Sample Answer: To address performance problems in large React apps, prioritize finding slow components, optimizing rendering, managing state efficiently, and utilizing code splitting and memoization techniques. Profiling the application with tools like React Profiler is crucial for pinpointing bottlenecks.
Here is the code demonstrating this:
import React, { memo } from ‘react’;
const HeavyComponent = memo(({ text }) => {
console.log(‘HeavyComponent rendered’);
return <p>{text}</p>;
});
function App() {
return <HeavyComponent text=”Hello” />;
}
export default App;
Q36. What are React’s concurrent features, and how do they improve rendering?
Sample Answer: React’s concurrent features allow React to interrupt rendering tasks and work on them in smaller chunks. This makes the UI more responsive by prioritizing urgent updates and reducing blocking. Features like ‘startTransition’ and Suspense help manage complex updates smoothly.
Here is the code demonstrating this:
import React, { useState, startTransition } from ‘react’;
function Search() {
const [query, setQuery] = useState(”);
const [results, setResults] = useState(”);
const handleChange = (e) => {
const value = e.target.value;
setQuery(value);
startTransition(() => {
// Simulate expensive filtering
setResults(`Results for “${value}”`);
});
};
return (
<>
<input value={query} onChange={handleChange} />
<p>{results}</p>
</>
);
}
export default Search;
Q37. How do you implement server-side rendering (SSR) in a React app?
Sample Answer: To implement server-side rendering (SSR) in a React app, use frameworks like Next.js. SSR renders React components on the server and sends fully rendered HTML to the client, improving performance and SEO and reducing initial load time.
Here is the code demonstrating this:
// pages/index.js (Next.js)
export default function Home({ name }) {
return <p>Hello, {name}!</p>;
}
export async function getServerSideProps() {
return { props: { name: ‘Alice’ } };
}
Q38. How do you design a scalable folder structure for a complex React project?
Sample Answer: To create a scalable folder structure for a complex React project, group files by feature or module. Create distinct folders for components, pages, hooks, services, and utilities. Maintain consistent nomenclature, separate reusable code, and group related functionality to improve maintainability.
Here is the code demonstrating this:
/src
/components
/Button
Button.jsx
Button.css
/pages
Home.jsx
About.jsx
/hooks
useAuth.js
/services
api.js
/utils
formatDate.js
App.jsx
index.js
Also Read: Infosys React Interview Questions
Q39. How do you manage deeply nested state without affecting performance?
Sample Answer: To manage deeply nested state without affecting performance, use state management patterns like ‘useReducer’ or the Context API with selective updates. Avoid unnecessary re-renders by splitting components and memoizing where needed. Keep state updates localized to specific child components.
Here is the code demonstrating this:
import React, { useReducer } from ‘react’;
const reducer = (state, action) => ({
…state,
user: { …state.user, name: action.payload }
});
function Profile() {
const [state, dispatch] = useReducer(reducer, { user: { name: ‘Alice’ } });
return (
<button onClick={() => dispatch({ payload: ‘Bob’ })}>
{state.user.name}
</button>
);
}
export default Profile;
Q40. How do you handle authentication and route protection in a React single-page application?
Sample Answer: Authentication and route protection in a React Single-Page Application (SPA) entails managing user data and rendering or redirecting users based on their authentication status. To redirect unauthenticated users to the login page, you can use route guards or
conditional rendering.
Here is the code demonstrating this:
import React from ‘react’;
import { BrowserRouter, Routes, Route, Navigate } from ‘react-router-dom’;
const isAuthenticated = false; // Example auth status
function ProtectedRoute({ children }) {
return isAuthenticated ? children : <Navigate to=”/login” />;
}
function App() {
return (
<BrowserRouter>
<Routes>
<Route path=”/login” element={<p>Login Page</p>} />
<Route
path=”/dashboard”
element={
<ProtectedRoute>
<p>Dashboard</p>
</ProtectedRoute>
}
/>
</Routes>
</BrowserRouter>
);
}
export default App;
Q41. What strategies do you use to reduce bundle size in a production build?
Sample Answer: To reduce bundle size in a production build, use code splitting with ‘React.lazy’ and Suspense, remove unused code, and enable tree shaking. Also, you should compress assets, load dependencies only when needed, and use lightweight alternatives for large libraries.
Here is the code demonstrating this:
import React, { lazy, Suspense } from ‘react’;
const LazyComponent = lazy(() => import(‘./BigComponent’));
function App() {
return (
<Suspense fallback={<p>Loading…</p>}>
<LazyComponent />
</Suspense>
);
}
export default App;
Q42. How do you test a component that uses hooks like ‘useEffect’ and ‘useState’?
Sample Answer: To test a component using ‘useEffect’ and ‘useState’, use testing libraries like React Testing Library with Jest. Simulate user actions or data updates, wait for side effects using ‘waitFor’, and assert the expected changes in the component’s output or behavior.
Here is the code demonstrating this:
// MyComponent.jsx
import React, { useState, useEffect } from ‘react’;
export default function MyComponent() {
const [text, setText] = useState(‘Loading…’);
useEffect(() => setTimeout(() => setText(‘Hello!’), 500), []);
return <p>{text}</p>;
}
Q43. What is React Suspense, and how does it work with lazy loading?
Sample Answer: React Suspense is a built-in React component that lets you specify loading states for components that aren’t ready to render. It integrates with React. Use the ‘<Suspense>’ element to enclose the lazy-loaded component. This displays a placeholder (similar to a loader) until the component has finished loading.
Here is the code demonstrating this:
import React, { lazy, Suspense } from ‘react’;
const LazyComponent = lazy(() => import(‘./MyComponent’));
function App() {
return (
<Suspense fallback={<p>Loading…</p>}>
<LazyComponent />
</Suspense>
);
}
export default App;
Q44. How do you integrate TypeScript in a React project and manage prop types?
Sample Answer: To integrate ‘TypeScript’ into a React project, first build the app with TypeScript support using tools like create-react-app and the -template typescript flag. Define prop types using TypeScript interfaces or types to enable compile-time type checking and improve code clarity.
Here is the code demonstrating this:
// MyButton.tsx
import React from ‘react’;
type MyButtonProps = {
label: string;
};
const MyButton: React.FC<MyButtonProps> = ({ label }) => {
return <button>{label}</button>;
};
export default MyButton;
Q45. How do you structure a custom hook that includes data fetching, error handling, and caching?
Sample Answer: A custom React hook for data fetching, error handling, and caching can be built by combining ‘useState’, ‘useEffect’, and possibly ‘useMemo’ or ‘useCallback’ to manage state, side effects, and memoized values. Caching can be done with ‘localStorage’ or a specific caching library such as ‘react-query’ or ‘swr’.
Here is the code demonstrating this:
import { useState, useEffect } from ‘react’;
function useFetch(url) {
const [data, setData] = useState(null);
const [error, setError] = useState(null);
useEffect(() => {
const cached = localStorage.getItem(url);
if (cached) {
setData(JSON.parse(cached));
return;
}
fetch(url)
.then(res => res.json())
.then(json => {
setData(json);
localStorage.setItem(url, JSON.stringify(json));
})
.catch(setError);
}, [url]);
return { data, error };
}
export default useFetch;
Q46. How do you isolate and test reusable UI components in a design system?
Sample Answer: To isolate and test reusable UI components in a design system, use tools like Storybook for isolated development and visual testing, as well as automated testing frameworks for functionality and accessibility. This guarantees that components are reliable, consistent, and usable in a variety of scenarios.
Here is the code demonstrating this:
// Button.jsx
import React from ‘react’;
export default function Button({ label }) {
return <button>{label}</button>;
}
Q47. How would you implement optimistic UI updates in React?
Sample Answer: An optimistic update changes the UI immediately before the server confirms the operation. This makes interactions feel faster, but you should keep the previous state so you can restore it if the request fails. This pattern works well for actions such as liking a post, updating a status, or deleting an item.
import { useState } from ‘react’;
function LikeButton() {
const [liked, setLiked] = useState(false);
const handleLike = async () => {
const previous = liked;
setLiked(true);
try {
const response = await fetch(‘/api/like’, {
method: ‘POST’
});
if (!response.ok) {
throw new Error(‘Request failed’);
}
} catch (error) {
setLiked(previous);
}
};
return (
<button onClick={handleLike}>
{liked ? ‘Liked’ : ‘Like’}
</button>
);
}
export default LikeButton;
React.js Technical Interview Questions with Answers
React.js technical interview questions assess your grasp of core concepts, internal mechanisms, and React’s approach to component structure and behavior. They help interviewers assess your understanding of key principles, component lifecycles, and the overall React architecture. Here are common technical React JS coding interview questions and answers:
Q48. What is the virtual DOM, and how does React use it during rendering?
Sample Answer: The virtual DOM (VDOM) is a lightweight in-memory approximation of React’s true DOM (Document Object Model). It’s an important part of React’s rendering process, considerably improving efficiency by reducing direct manipulation of the real DOM. When the state of a component changes, React first updates its virtual DOM. It then compares the new virtual DOM with the existing one, determining just the necessary modifications.
Q49. How does React differ from traditional JavaScript frameworks?
Sample Answer: React differs from other JavaScript frameworks in that it uses a component-based architecture and a virtual DOM for efficient rendering. It focuses solely on the view layer, encourages the reuse of UI components, and employs unidirectional data flow rather than the two-way bindings used by many previous frameworks.
Q50. What are the differences between state and props?
Sample Answer: In React, props (short for properties) are data sent from a parent component to a child component, whereas state is data kept internally within a component. Props are read-only for the child component, which means the child cannot modify them. State, on the other hand, is handled by the component and can be changed using the ‘setState’ method (in class components) or the ‘useState’ hook (in functional components), forcing the component to re-render.
Q51. When should you use ‘useEffect’, and how does its dependency array work?
Sample Answer: You should use ‘useEffect’ to handle side effects like data fetching, subscriptions, or DOM updates in functional components. The dependency array controls when the effect runs – React re-runs the effect only if the listed dependencies change between renders.
Q52. What is JSX, and how does it get transformed behind the scenes?
Sample Answer: JSX is a syntactic extension for JavaScript that allows developers to include HTML-like code into their JavaScript files. Browsers do not understand it directly; therefore, tools like Babel convert it to standard JavaScript. This transformation allows React to construct and maintain user interface elements more efficiently.
Q53. What are pure components, and how do they affect performance?
Sample Answer: In React, pure components are class components that automatically implement ‘shouldComponentUpdate’ via a shallow comparison of props and state. React uses a shallow comparison of props and state to avoid wasteful re-renders. This improves performance by avoiding the production of the same content multiple times.
Q54. What is the difference between updating, mounting, and unmounting phases in React?
Sample Answer: In React, a component goes through different lifecycle phases. The updating phase is triggered when there’s a change in state or props, leading to a re-render. The mounting phase happens when the component is initially created and added to the DOM. The unmounting phase occurs when the component is removed from the DOM, providing an opportunity to clean up tasks such as side effects, event listeners, and subscriptions.
Q55. What is React’s approach to re-rendering components when there’s a change in props or state?
Sample Answer: When a component’s props or state are updated, React triggers a re-render. It first updates the virtual DOM, then uses a diffing algorithm to compare the new version with the previous one. Only the parts of the real DOM that have changed are updated, ensuring efficient performance and a consistent user interface.
Q56.What is the significance of keys in list rendering?
Sample Answer: Keys in list rendering help React identify which items have changed, been added to, or removed. They provide a stable identity for each element, allowing React to update the list efficiently and avoid re-rendering unchanged items, thereby improving performance and preventing rendering issues.
Q57. What are higher-order components (HOCs), and when would you use one?
Sample Answer: Higher-Order Components (HOCs) are an effective React technique for reusing component logic. They are functions that accept a component as an argument and return a new, improved component. HOCs are excellent for abstracting shared functionality, such as data retrieval, authentication, or styling, into reusable modules that can be applied to several components.
Tips to Prepare for the React Coding Interview Questions
Preparing for React coding interview questions necessitates a thorough understanding of component behavior, hooks, and typical application patterns. Interviewers frequently assess how well you develop clean, reusable, and efficient code. You should know how to debug bugs and effectively manage state during development. Given below are some tips to help you succeed in your preparation:
- Practice Real Coding Scenarios: Build real components instead of just reading about them. Focus on implementing forms, dynamic lists, and conditional rendering—these are frequently asked patterns in React interviews.
- Master React Hooks: Understand how ‘useState’, ‘useEffect,’ ‘useContext,’ and ‘useReducer’ work in various situations. Practice how dependency arrays affect re-renders. Interviewers often test your ability to manage data flow with hooks.
- Debug and Optimize React Code: Learn to identify and fix issues in React components using browser dev tools and React Developer Tools. Interviewers may give you buggy code and ask you to debug or optimize it on the spot.
- Write Clean, Reusable Components: Structure your code to avoid duplication. Use props and custom hooks to separate logic and improve reusability. Clean, modular code shows that you can build scalable applications.
- Review Your Previous Projects: Revisit the React apps you’ve built. Be ready to explain your logic, design choices, and why you used specific hooks or patterns. Interviewers often ask for insights into your decision-making process.


Conclusion
Practicing the React coding interview questions can help you prepare for the practical challenges you may encounter in a technical interview. Focus on understanding how React handles state, hooks, rendering, performance, component design, and application architecture instead of memorizing answers. Write and debug the code yourself, revisit concepts you find difficult, and practice explaining why you chose a particular approach. This will help you solve coding problems more effectively and discuss your solutions with greater clarity and confidence.
If you liked this blog, then check out our guide on Infosys React interview questions tailored to different experience and skill levels and boost your preparation.
FAQs
Answer: React coding interview questions usually cover components, props, state, Hooks, event handling, rendering, forms, performance, API integration, and debugging. For experienced roles, questions may also cover application architecture, testing, state management, and server-side rendering.
Answer: As a fresher, prepare for React coding interviews by learning about components, props, state, and hooks. Build small projects, practice coding patterns, and understand how React handles rendering and data flow.
Answer: Yes, mid-level interviews can include Hooks such as useMemo, useCallback, useRef, useReducer, and custom Hooks. Interviewers may ask you to explain when these Hooks are useful, identify incorrect usage, or apply them to a practical coding problem.
Answer: Architecture can be an important part of experienced-level React interviews, along with performance, testing, data fetching, state management, and scalability. You may be asked to design a component structure, improve an existing implementation, or explain why you would choose one approach over another.
Sources
- https://survey.stackoverflow.co/2023/




