React Js Interview Questions
On this page24
- 1What is React.js and what are its key features?
- 2Explain the difference between functional and class components.
- 3What are React Hooks? Name the most commonly used ones.
- 4Explain the Virtual DOM and how it works in React.
- 5What is JSX and why is it used in React?
- 6Explain the concept of state in React.
- 7What are props in React and how do they differ from state?
- 8What is the significance of keys in React lists?
- 910. What is the Context API in React?
- 10What is Redux and when would you use it?
- 11Explain the concept of code splitting in React.
- 12What are React fragments and why are they useful?
- 13How do you handle forms in React?
- 14What is prop drilling and how can you avoid it?
- 15Ways to avoid prop drilling:
- 16Explain the useEffect Hook and its common use cases.
- 17Common use cases:
- 18What is React Router and how is it used?
- 1918. What are React portals and when would you use them?
- 20How do you optimize performance in React applications?
- 21What are React Hooks rules and why are they important?
- 2221. Explain the concept of Higher-Order Components (HOCs) in React.
- 23What is the difference between Shadow DOM and Virtual DOM?
- 24Answer:
1. What is React.js and what are its key features?
Answer: React.js is an open-source JavaScript library developed by Facebook for building user interfaces, particularly single-page applications. Its key features include:
- Virtual DOM for optimized rendering
- Component-based architecture for reusable UI elements
- Declarative approach to describe UI state
- Unidirectional data flow (one-way binding)
- JSX syntax that combines HTML and JavaScript
- React Native for mobile application development
- Rich ecosystem and community support
2. Explain the difference between functional and class components.
Answer:
Functional Components: JavaScript functions that accept props and return React elements. They're simpler, more concise, and with the introduction of Hooks, can now manage state and side effects.
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
Class Components: ES6 classes that extend React.Component and have additional features like local state, lifecycle methods, and the ability to use refs.
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
Since React 16.8, functional components with Hooks are generally preferred for their simplicity and performance benefits.
3. What are React Hooks? Name the most commonly used ones.
Answer: React Hooks are functions that let you "hook into" React state and lifecycle features from functional components. The most commonly used Hooks are:
- useState: Manages local state in functional components
- useEffect: Handles side effects (similar to componentDidMount, componentDidUpdate, componentWillUnmount)
- useContext: Subscribes to React context without nesting
- useReducer: Manages complex state logic
- useRef: Creates a mutable reference that persists across renders
- useMemo: Memoizes expensive calculations to optimize performance
- useCallback: Returns a memoized callback to prevent unnecessary renders
4. Explain the Virtual DOM and how it works in React.
Answer: The Virtual DOM is a lightweight JavaScript representation of the actual DOM. When state changes in a React component:
- React creates a new Virtual DOM tree
- It compares this new tree with the previous Virtual DOM tree (diffing)
- It calculates the minimal number of operations needed to update the real DOM (reconciliation)
- It updates only the changed parts of the actual DOM
This process is more efficient than directly manipulating the DOM for every state change, as DOM operations are expensive. The Virtual DOM allows React to batch updates and minimize browser reflows and repaints.
5. What is JSX and why is it used in React?
Answer: JSX (JavaScript XML) is a syntax extension for JavaScript that looks similar to HTML. It allows us to write HTML-like code in JavaScript files. For example:
const element = <h1>Hello, world!</h1>;
JSX is used in React because:
- It makes the code more readable and intuitive
- It allows for the full power of JavaScript within HTML structures
- It helps prevent injection attacks by escaping embedded values
- It's compiled to regular JavaScript objects, making it efficient
Under the hood, JSX is transformed into React.createElement() calls by tools like Babel.
6. Explain the concept of state in React.
Answer: State is a JavaScript object that represents the parts of a component that can change over time. It's managed internally by the component and determines how a component renders and behaves.
Key characteristics of state:
- It's private and fully controlled by the component
- Changes to state trigger re-renders of the component and its children
- State should be considered immutable (never modified directly)
- State updates may be asynchronous
- State can be passed down to child components as props
In class components, state is accessed via this.state and updated with this.setState(). In functional components, state is managed with the useState Hook.
7. What are props in React and how do they differ from state?
Answer: Props (short for properties) are inputs to React components that allow passing data from parent to child components.
Differences between props and state:
- Props are passed from parent components; state is managed within the component
- Props are read-only; state can be changed using setState or useState
- Props can be used in both functional and class components; state traditionally required class components (before Hooks)
- Changes in props come from parent component re-renders; changes in state are triggered within the component
- Props can be used to configure a component when it renders; state represents values that change over time
// Parent component passing props
<ChildComponent name="John" age={25} />
// Child component receiving props
function ChildComponent(props) {
return <p>Name: {props.name}, Age: {props.age}</p>;
}
8. What is the significance of keys in React lists?
Answer: Keys are special attributes that help React identify which items in a list have changed, been added, or removed. They help React optimize rendering by reusing existing DOM elements when possible.
Keys should be:
- Unique among siblings
- Stable (not generated on-the-fly during rendering)
- Typically derived from your data (like IDs)
const todoItems = todos.map((todo) =>
<li key={todo.id}>
{todo.text}
</li>
);
Without keys, React would have to re-render the entire list when items change, rather than just updating the changed items. Using array indices as keys is not recommended if the order of items may change, as it can lead to performance issues and bugs.
9. Explain the React component lifecycle methods.
Answer: React component lifecycle methods allow you to run code at specific times during a component's existence. In class components, the main lifecycle phases are:
Mounting:
constructor(): Initialize state and bind methodsstatic getDerivedStateFromProps(): Update state based on propsrender(): Required method to return JSXcomponentDidMount(): Run after component is mounted to DOM
Updating:
static getDerivedStateFromProps()shouldComponentUpdate(): Control if component should re-renderrender()getSnapshotBeforeUpdate(): Capture information before DOM updatescomponentDidUpdate(): Run after component updates
Unmounting:
componentWillUnmount(): Clean up before component is removed
In functional components, the
useEffectHook replaces most lifecycle methods:
// Similar to componentDidMount and componentDidUpdate
useEffect(() => {
// Effect code
return () => {
// Cleanup (similar to componentWillUnmount)
};
}, [dependencies]); // Dependencies array controls when effect runs
10. What is the Context API in React?
Answer: The Context API provides a way to share values like themes, user data, or language preferences between components without explicitly passing props through every level of the component tree (prop drilling).
It consists of three main parts:
React.createContext: Creates a Context objectContext.Provider: Wraps components and provides the valueContext.ConsumeroruseContextHook: Consumes the context value
// Create context
const ThemeContext =React.createContext('light');
// Provider
function App() {
return (
<ThemeContext.Provider value="dark">
<ThemedButton/>
</ThemeContext.Provider>
);
}
// Consumer (using useContext Hook)
function ThemedButton() {
const theme = useContext(ThemeContext);
return <button className={theme}>Themed Button</button>;
}
Context is ideal for global data but shouldn't replace props for most component communication as it can make component reuse more difficult.
11. What is Redux and when would you use it?
Answer: Redux is a predictable state container for JavaScript applications, commonly used with React. It maintains the application state in a single store and uses a strict unidirectional data flow.
Key concepts in Redux:
- Store: Holds the application state
- Actions: Plain objects describing what happened
- Reducers: Pure functions that specify how state changes in response to actions
- Dispatch: Method to send actions to the store
You would use Redux when:
- Your application has complex state that's shared across many components
- The state is updated frequently
- The logic to update state is complex
- The application has a medium to large codebase with many developers
- You need to track state changes over time for debugging
For smaller applications, React's built-in state management with Context API might be sufficient.
12. Explain the concept of code splitting in React.
Answer: Code splitting is a technique that allows you to split your JavaScript bundle into smaller chunks that can be loaded on demand, improving initial load time and performance.
In React, code splitting can be implemented using:
- Dynamic imports with
import()syntax:
import('./math').then(math=> {
console.log(math.add(16, 26));
});
- React.lazyfor component-based code splitting:
const OtherComponent = React.lazy(() =>import('./OtherComponent'));
function MyComponent() {
return (
<React.Suspense fallback={<div>Loading...</div>}>
<OtherComponent/>
</React.Suspense>
);
}
- Route-based code splitting using React Router with lazy loading:
const Home = React.lazy(() => import('./routes/Home'));
const About = React.lazy(() => import('./routes/About'));
<React.Suspense fallback={<div>Loading...</div>}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</React.Suspense>
Code splitting is particularly useful for large applications where users don't need all the code at once.
13. What are React fragments and why are they useful?
Answer: React fragments let you group multiple elements without adding an extra node to the DOM. They're useful when you need to return multiple elements from a component but don't want to add unnecessary divs or spans to the DOM structure.
// Using the explicit Fragment syntax
return (
<React.Fragment>
<ChildA />
<ChildB />
<ChildC />
</React.Fragment>
);
// Using the shorthand syntax
return (
<>
<ChildA />
<ChildB />
<ChildC />
</>
);
Fragments are beneficial because they:
- Keep the DOM cleaner and less nested
- Avoid breaking CSS layouts that depend on direct parent-child relationships
- Improve performance slightly by creating fewer DOM nodes
- Work well with flexbox and grid layouts where wrapper divs might interfere
14. How do you handle forms in React?
Answer: There are two main approaches to handling forms in React:
Controlled Components: Form elements maintain their own state in React state, and updates are handled through onChange events.
function Form() {
const [value, setValue] = useState('');
const handleChange = (event) => {
setValue(event.target.value);
};
const handleSubmit = (event) => {
event.preventDefault();
console.log('Submitted value:', value);
};
return (
<form onSubmit={handleSubmit}>
<input type="text" value={value} onChange={handleChange} />
<button type="submit">Submit</button>
</form>
);
}
Uncontrolled Components: Form data is handled by the DOM itself, and values are accessed using refs
function Form() {
const inputRef = useRef(null);
const handleSubmit = (event) => {
event.preventDefault();
console.log('Submitted value:',
inputRef.current.value);
};
return (
<form onSubmit={handleSubmit}>
<input type="text" ref={inputRef} defaultValue="default value" />
<button type="submit">Submit</button>
</form>
);
}
Controlled components are generally preferred as they:
- Keep form state in sync with the UI
- Allow for immediate validation and feedback
- Enable conditional rendering based on form state
- Make it easier to submit form values
For complex forms, libraries like Formik or React Hook Form can simplify form management.
15. What is prop drilling and how can you avoid it?
Answer: Prop drilling (also called "threading") occurs when props need to be passed through multiple levels of nested components, even when some intermediate components don't need those props.
// Prop drilling example
function App() {
const [user, setUser] = useState({name:'John'});
return <TopLevel user={user} />;
}
function TopLevel({user}) {
// This component doesn't use user but passes it down
return <MiddleComponent user={user} />;
}
function MiddleComponent({user}) {
// This component also doesn't use user
return <BottomComponent user={user} />;
}
function BottomComponent({user}) {
// Finally uses the user prop
return <div>Hello, {user.name}</div>;
}
Ways to avoid prop drilling:
- Context API: Use React Context to provide values to deeply nested components without passing props.
const UserContext = React.createContext();
function App() {
const [user, setUser] = useState({name:'John'});
return (
<UserContext.Provider value={user}>
<TopLevel/>
</UserContext.Provider>
);
}
function BottomComponent() {
const user= useContext(UserContext);
return <div>Hello, {user.name}</div>;
}
State Management Libraries: Use Redux, MobX, or Recoil for more complex state management.
Component Composition: Restructure components to avoid deep nesting.
Custom Hooks: Create hooks that encapsulate and share stateful logic.
16. Explain the useEffect Hook and its common use cases.
Answer: The useEffect Hook lets you perform side effects in functional components. It runs after every render by default, but can be configured to run only when certain values change.
Syntax:
useEffect(() => {
// Side effect code
return () => {
// Optional cleanup function
};
}, [dependencies]); // Optional dependency array
Common use cases:
Data fetching:
useEffect(() => {const fetchData =async () => {const response =await fetch('https://api.example.com/data');const data = await response.json();setData(data);};fetchData();}, []); // Empty array means run once on mount
Subscriptions or event listeners:
useEffect(() => {
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize); };
}, []); // Cleanup function removes the listener
DOM manipulations:
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]); // Only re-run when count changes
Timers:
useEffect(() => {
const timer = setTimeout(() => {
console.log('This runs after 1 second'); }, 1000);
return () => clearTimeout(timer);
}, []);
Synchronizing with external systems
The dependency array is crucial for controlling when effects run and preventing infinite loops.
17. What is React Router and how is it used?
Answer: React Router is a standard library for routing in React applications. It enables navigation between different components, changing the browser URL, and keeping the UI in sync with the URL.
Basic usage with React Router v6:
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
<Link to="/users/123">User Profile</Link>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/users/:userId" element={<UserProfile />} />
<Route path="*" element={<NotFound />} />
</Routes>
</BrowserRouter>
);
}
Key features:
- Route parameters (like
:userId) for dynamic routing - Nested routes for complex layouts
- useParams Hook to access URL parameters
- useNavigate Hook for programmatic navigation
- useLocation Hook to access the current URL
- Outlet component for nested UI
- Route protection for authentication
React Router helps create single-page applications where page transitions are smooth and don't require full page reloads.
18. What are React portals and when would you use them?
Answer: React portals provide a way to render children into a DOM node that exists outside the DOM hierarchy of the parent component.
import ReactDOM from 'react-dom';
function Modal({ children }) {
return ReactDOM.createPortal(
children,
document.getElementById('modal-root')
);
}
function App() {
return (
<div>
<h1>App Content</h1>
<Modal>
<h2>This renders in the modal container</h2>
</Modal>
</div>
);
}
You would use portals for:
Modals, dialogs, and tooltips: Render these UI elements outside the main application hierarchy to avoid CSS issues with
z-index,overflow, orposition.Floating elements: For components that need to "break out" of their containers, like popovers or dropdown menus.
Widgets embedded in other applications: When your React app needs to render content into a specific DOM node controlled by another application.
Accessibility concerns: When you need to ensure screen readers interpret your UI correctly.
Portals only affect the DOM structure, not the React component hierarchy. Events still bubble up through the React tree regardless of the DOM placement.
19. How do you optimize performance in React applications?
Answer: There are several strategies to optimize React application performance:
1. Use React.memo for component memoization:
const MyComponent = React.memo(function MyComponent(props) {
/* render using props */
});
2. Implement shouldComponentUpdate or React.PureComponent:
class MyComponent extends React.PureComponent {
// PureComponent implements shouldComponentUpdate with shallow comparison
}
3. Use useMemo for expensive calculations:
const memoizedValue = useMemo(() =>computeExpensiveValue(a, b), [a, b]);
4. Use useCallback to prevent unnecessary renders of child components:
const memoizedCallback = useCallback(() => {
doSomething(a, b);
}, [a, b]);
5. Code splitting and lazy loading:
const LazyComponent = React.lazy(() => import('./LazyComponent'));
6. Virtualization for long lists:
import { FixedSizeList } from 'react-window';
function MyList({ items }) {
return (
<FixedSizeList
height={500}
width={500}
itemSize={35}
itemCount={items.length}
itemData={items}
>
{Row}
</FixedSizeList>
);
}
7. Avoid inline function definitions in render:
// Instead of
<button onClick={() =>handleClick(id)}>Click</button>
// Better approach
const handleItemClick = useCallback((id) => {
handleClick(id);
}, [handleClick]);
<button onClick={() =>handleItemClick(id)}>Click</button>
8. Use production builds with minification and tree shaking
9. Implement proper keys for lists
10. Avoid unnecessary re-renders by keeping component state local when possible
11. Use web workers for CPU-intensive tasks
12. Implement proper bundling and caching strategies
20. What are React Hooks rules and why are they important?
Answer: React Hooks have two essential rules:
- Only call Hooks at the top level:
- Don't call Hooks inside loops, conditions, or nested functions
- Always use Hooks at the top level of your React function
- Only call Hooks from React functions:
- Call Hooks from React functional components
- Call Hooks from custom Hooks
- Don't call Hooks from regular JavaScript functions
These rules are important because:
- React relies on the order of Hook calls to maintain state between re-renders
- Conditional Hook calls can lead to bugs and inconsistent state
- The dependency system of Hooks requires consistent execution
- React's internal mechanisms for tracking Hook state depend on these rules
Example of incorrect usage:
function Counter(props) {
// 🔴 Wrong: Conditional Hook call
if (props.isVisible) {
const [count, setCount] = useState(0);
}
// 🔴 Wrong: Hook inside a loop
for (let i = 0; i < props.items.length; i++) {
useEffect(() => {
console.log(i);
});
}
}
Correct usage:
function Counter(props) {
// ✅ Correct: Hooks at the top level
const [count, setCount] = useState(0);
// Conditional rendering is fine
if (!props.isVisible) {
return null;
}
// ✅ Correct: Effect with dependencies
useEffect(() => {
document.title = `Count: ${count}`;
}, [count]);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
21. Explain the concept of Higher-Order Components (HOCs) in React.
Answer: A Higher-Order Component (HOC) is an advanced pattern in React where a function takes a component and returns a new enhanced component. HOCs allow you to reuse component logic, add additional props, or modify the rendering behavior.
// HOC definition
function withLogger(WrappedComponent){
return function WithLogger(props){
useEffect(()=>{
console.log(`Component ${WrappedComponent.name}rendered with props:`,props);
},[props]);
return<WrappedComponent {...props}/>;
};
}
// Usage
function SimpleButton(props){
return<button {...props}>{props.children}</button>;
}
const ButtonWithLogging=withLogger(SimpleButton);
// In another component
<ButtonWithLogging onClick={()=>alert('Clicked')}>Click Me</ButtonWithLogging>
Common use cases for HOCs:
- Code reuse and logic abstraction
- State abstraction and manipulation
- Props manipulation (adding, modifying)
- Rendering hijacking
- Conditionally rendering components (like authentication checks)
Example of a more practical HOC:
function withAuth(Component) {
return function WithAuth(props) {
const { isAuthenticated, user } = useAuth();
if (!isAuthenticated) {
return <Navigate to="/login" />;
}
return <Component {...props} user={user} />;
};
}
const ProtectedDashboard = withAuth(Dashboard);
With the introduction of Hooks, many use cases for HOCs can now be handled with custom Hooks, but HOCs remain useful for certain scenarios, especially when working with class components.
22. What is the difference between Shadow DOM and Virtual DOM?
Answer:
Virtual DOM:
- A concept used by React to optimize rendering
- A lightweight JavaScript representation of the actual DOM
- Used for diffing and reconciliation to minimize DOM updates
- A programming concept, not a web standard
- Exists entirely in memory and is synchronized with the "real" DOM
Shadow DOM:
- A browser technology for encapsulating DOM and CSS
- Allows for the creation of scoped subtrees in web components
- Provides true CSS encapsulation and DOM isolation
- A web standard implemented by browsers
- Actually rendered in the browser alongside the main DOM
Key differences:
- Virtual DOM is a React-specific optimization technique; Shadow DOM is a web standard
- Virtual DOM addresses performance; Shadow DOM addresses encapsulation
- Virtual DOM works with the entire application; Shadow DOM works at the component level
- Virtual DOM is not directly accessible in the browser; Shadow DOM can be inspected
React doesn't use Shadow DOM by default, but you can use libraries like styled-components or emotion to achieve similar CSS encapsulation. Web Components, on the other hand, typically use Shadow DOM for encapsulation.
