React Interview Questions
1. What are the main features of React?
Answer:
Component-Based Architecture: Breaks UI into reusable, self-contained components.
Virtual DOM: Minimizes DOM manipulation by updating only the changed parts.
Unidirectional Data Flow: Data flows in one direction, simplifying state management.
JSX (JavaScript XML): A syntax extension that allows HTML within JavaScript.
Declarative: Describes what the UI should look like, making it easier to read and manage.
2. What is the difference between State
and Props
?
Answer:
State:
Managed within a component.
Mutable (can change over time).
Controls component behavior and rendering.
Props:
Passed from a parent to a child component.
Immutable (cannot be changed by the receiving component).
Used to pass data and trigger callbacks.
3. What is the Virtual DOM, and how does it improve performance?
Answer:
Virtual DOM is an in-memory representation of the actual DOM. React maintains it as a lightweight copy.
When state or props change, React updates the Virtual DOM first, compares it with the real DOM, and then only applies the differences.
This minimizes costly direct manipulations of the real DOM, improving performance.
4. Explain the React Component Lifecycle?
Answer:
The component lifecycle is divided into three phases:
Mounting:
constructor()
,static getDerivedStateFromProps()
,render()
,componentDidMount()
.Updating:
static getDerivedStateFromProps()
,shouldComponentUpdate()
,render()
,getSnapshotBeforeUpdate()
,componentDidUpdate()
.Unmounting:
componentWillUnmount()
.
Hooks can also be used in functional components to mimic lifecycle methods (e.g.,
useEffect()
forcomponentDidMount
).Summary of Mimicking Lifecycle Phases with Hooks
| Lifecycle Phase | Class Component Method(s) | Functional Component (Hooks) | | --- | --- | --- | | Mounting |
constructor
,componentDidMount
|useEffect(() => {}, [])
| | Updating |shouldComponentUpdate
,componentDidUpdate
,getDerivedStateFromProps
,getSnapshotBeforeUpdate
|useEffect(() => {}, [dependencies])
,React.memo
,useCallback
| | Unmounting |componentWillUnmount
|useEffect(() => { return () => {}; }, [])
|
5. What is the difference between Functional and Class Components?
Answer:
Functional Components: Use functions, introduced with React 16.8 with hooks (
useState
,useEffect
, etc.), making them lightweight and easy to test.Class Components: Use ES6 classes, more complex with lifecycle methods,
this
keyword, andstate
. They are generally less favored for new projects.
6. How does React’s useEffect
hook work?
Answer:
useEffect
allows you to perform side effects (e.g., data fetching, subscriptions) in functional components.Syntax:
useEffect(() => { /* effect */ }, [dependencies]);
Dependencies Array:
Controls when the effect re-runs.
Leaving it empty (
[]
) runs the effect only on mount/unmount.Including variables triggers re-runs when they change.
7. What is Context API, and when should you use it?
Answer:
Context API enables sharing state across components without prop drilling.
Best Use Cases:
- When data needs to be accessible by many nested components (e.g., theme, authentication state).
Usage: Wrap components in a
Context.Provider
, access data usinguseContext
.import React, { createContext, useState } from 'react'; // Create the Context export const ThemeContext = createContext(); // Create a Provider component export const ThemeProvider = ({ children }) => { const [theme, setTheme] = useState("light"); // 'light' or 'dark' // Function to toggle theme const toggleTheme = () => { setTheme((prevTheme) => (prevTheme === "light" ? "dark" : "light")); }; return ( <ThemeContext.Provider value={{ theme, toggleTheme }}> {children} </ThemeContext.Provider> ); };
8. What is Redux, and how does it work with React?
Answer:
Redux is a state management library that manages the application state globally.
Core Concepts:
Store: Holds the entire application state.
Actions: Plain objects that describe the change.
Reducers: Pure functions that return a new state based on actions.
React components access the state via
useSelector
and dispatch actions viauseDispatch
.
import React from 'react'; import ReactDOM from 'react-dom/client'; import { configureStore, createSlice } from '@reduxjs/toolkit'; import { Provider, useDispatch, useSelector } from 'react-redux'; // Step 1: Create a theme slice with initial state, reducers, and actions const themeSlice = createSlice({ name: 'theme', initialState: { mode: 'light' }, // initial theme state is 'light' reducers: { toggleTheme: (state) => { // Toggles theme between 'light' and 'dark' state.mode = state.mode === 'light' ? 'dark' : 'light'; } } }); // Export the action for use in components const { toggleTheme } = themeSlice.actions; // Step 2: Create a Redux store and add themeSlice to it const store = configureStore({ reducer: { theme: themeSlice.reducer } }); // Step 3: Create a component that consumes the theme state and dispatches actions const HomePage = () => { const dispatch = useDispatch(); // Access the dispatch function const theme = useSelector((state) => state.theme.mode); // Access the theme mode from the Redux store return ( <div style={{ background: theme === 'light' ? '#fff' : '#333', color: theme === 'light' ? '#000' : '#fff', padding: '20px', textAlign: 'center' }} > <h1>{theme === 'light' ? 'Light Mode' : 'Dark Mode'}</h1> {/* Dispatch the toggleTheme action on button click */} <button onClick={() => dispatch(toggleTheme())}>Toggle Theme</button> </div> ); }; // Step 4: Wrap the app in the Redux Provider to provide the Redux store to all components const App = () => { return ( <Provider store={store}> <HomePage /> </Provider> ); }; // Render the app const root = ReactDOM.createRoot(document.getElementById('root')); root.render(<App />);
9. What are React Hooks, and why were they introduced?
Answer:
Hooks allow functional components to have state and other features that were previously only available in class components.
Common Hooks:
useState
for state.useEffect
for side effects.useContext
for context.
Benefits: Simplifies code, reduces boilerplate, encourages more functional programming.
10. What is lazy loading, and how do you implement it in React?
Answer:
Lazy Loading is a technique to load components or resources only when they are needed.
In React, use
React.lazy
along withSuspense
to split your code.Example:
const LazyComponent = React.lazy(() => import('./LazyComponent')); // Usage <Suspense fallback={<div>Loading...</div>}> <LazyComponent /> </Suspense>
11. How do you optimize the performance of a React application?
Answer:
Use React.memo and useMemo to avoid unnecessary re-renders.
Implement code-splitting using React.lazy and dynamic imports.
Use shouldComponentUpdate or React.PureComponent for class components.
Avoid anonymous functions in render and pass stable callbacks using
useCallback
.Optimize dependency arrays in
useEffect
and other hooks.
12. What is Prop Drilling, and how do you avoid it?
Answer:
Prop Drilling occurs when props are passed down multiple levels to reach a specific component.
Avoidance Techniques:
Use Context API or Redux for global state management.
Utilize custom hooks to encapsulate logic and share state.
13. What is the purpose of key
in React, and why should they be unique?
Answer:
The
key
prop helps React identify which items have changed, been added, or removed.It should be unique among siblings to optimize re-rendering. Without unique keys, React may render incorrectly.
14. Explain controlled vs. uncontrolled components in React.
Answer:
Controlled Components: Have their state managed by React; updates occur via
onChange
handlers.Uncontrolled Components: Rely on the DOM to handle state; use
ref
to access values.
15. How does error handling work in React?
Answer:
Use Error Boundaries (class components with
componentDidCatch
) to catch errors in child components.In functional components, libraries like
ErrorBoundary
or using customErrorBoundary
components can help handle errors gracefully.
These answers will help you demonstrate not only your React skills but also your problem-solving approach and understanding of best practices during your interview. Let me know if you want more advanced questions or specific scenarios!
Differences between React.memo and useMemo
Feature | React.memo | useMemo |
Type of Optimization | Memoizes the entire component (prevents re-renders) | Memoizes values or the result of a computation |
Use case | Use when you want to prevent unnecessary re-renders of a component | Use when you want to prevent expensive calculations from running on every render |
Works On | Functional components | Values or functions (calculations, objects, etc.) |
How It Works | It compares props to determine if the component needs to re-render | It memoizes the return value of a function based on dependencies |
Shallow Comparison | Yes, compares props shallowly | No, it does not perform any comparison, it only recalculates when dependencies change |
Syntax | React.memo(Component) | useMemo(() => expensiveFunction(), [dependency]) |
16. Define a Callback Function in the Parent Component
1. Define a Callback Function in the Parent Component
- The parent component creates a function that will handle data received from the child component. This function will be passed as a prop to the child.
2. Pass the Callback Function as a Prop to the Child Component
- When you render the child component in the parent, pass the callback function as a prop to the child.
3. Invoke the Callback Function in the Child Component
- Inside the child component, call the function passed via props and pass any data you want to send to the parent as an argument.
Example
Let’s go through an example where a child component sends an input value to its parent:
Parent Component (ParentComponent.js
)
import React, { useState } from 'react';
import ChildComponent from './ChildComponent';
function ParentComponent() {
const [childData, setChildData] = useState("");
// Step 1: Define a callback function in the parent
const handleDataFromChild = (data) => {
setChildData(data); // Update the state with data from the child
};
return (
<div>
<h1>Data from Child: {childData}</h1>
{/* Step 2: Pass the callback function to the child */}
<ChildComponent onData={handleDataFromChild} />
</div>
);
}
export default ParentComponent;
Child Component (ChildComponent.js
)
import React, { useState } from 'react';
function ChildComponent({ onData }) {
const [inputValue, setInputValue] = useState("");
const handleChange = (event) => {
setInputValue(event.target.value);
};
// Step 3: Call the parent’s callback function when needed
const sendDataToParent = () => {
onData(inputValue); // Pass data to parent
};
return (
<div>
<input
type="text"
value={inputValue}
onChange={handleChange}
placeholder="Type something..."
/>
<button onClick={sendDataToParent}>Send to Parent</button>
</div>
);
}
export default ChildComponent;
Explanation
handleDataFromChild
inParentComponent
receives the data fromChildComponent
.onData={handleDataFromChild}
: Passes the function toChildComponent
via theonData
prop.onData(inputValue)
: The child component calls this function when the button is clicked, sendinginputValue
up to the parent.
Result
This method allows the parent component to receive and store data from the child component in its state.