React interviews questions and answers with code
React Interview Preparation: Best Questions, Best Answers, and Sample Code
1. What are the differences between functional and class components in React?
- Answer: Functional components are simpler and mainly focus on rendering UI, while class components provide more powerful features like state management and lifecycle methods.
- In recent versions of React, hooks (
useState
,useEffect
) enable functional components to use state and lifecycle features without needing to be classes.
2. Explain useEffect and how it differs from lifecycle methods in class components.
- Answer:
useEffect
is a hook that manages side effects in functional components, similar to lifecycle methods (componentDidMount
,componentDidUpdate
,componentWillUnmount
) in class components.useEffect
runs after every render by default, but dependencies can be provided to control when it runs.
Example:
import React, { useState, useEffect } from 'react';
function ExampleComponent() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log(`Count is: ${count}`);
// ComponentDidMount + ComponentDidUpdate equivalent
}, [count]); // Runs only when count changes
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
3. What is the virtual DOM, and how does it improve performance in React?
- Answer: The virtual DOM is an in-memory representation of the real DOM elements generated by React components. When the state of an object changes, the virtual DOM is updated instead of the real DOM. React compares the virtual DOM with a pre-update version using a "diffing" algorithm to determine what has changed, and then only updates the specific elements in the actual DOM, which minimizes re-rendering and improves performance.
4. How does conditional rendering work in React?
- Answer: Conditional rendering in React means rendering components or elements based on certain conditions using JavaScript conditional statements, like
if-else
, ternary operators, or logica l&&
operator.
Example:
function ConditionalComponent({ isLoggedIn }) {
return (
<div>
{isLoggedIn ? (
<h1>Welcome back!</h1>
) : (
<h1>Please log in</h1>
)}
</div>
);
}
5. Explain the concept of "lifting state up" in React.
- Answer: "Lifting state up" is a technique where the shared state is moved to the closest common ancestor component. This allows the parent component to pass the state down as props, ensuring sibling components have a single source of truth.
Example:
function ParentComponent() {
const [sharedValue, setSharedValue] = useState('');
return (
<div>
<InputComponent sharedValue={sharedValue} setSharedValue={setSharedValue} />
<DisplayComponent sharedValue={sharedValue} />
</div>
);
}
function InputComponent({ sharedValue, setSharedValue }) {
return <input value={sharedValue} onChange={(e) => setSharedValue(e.target.value)} />;
}
function DisplayComponent({ sharedValue }) {
return <p>{sharedValue}</p>;
}
6. What is React Context, and when should it be used?
- Answer: React Context provides a way to share values between components without having to pass props manually at every level. It is useful when data needs to be accessed by many components, like theme settings, user authentication, or global state.
Example:
import React, { createContext, useContext } from 'react';
const ThemeContext = createContext('light');
function App() {
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
function Toolbar() {
return <ThemedButton />;
}
function ThemedButton() {
const theme = useContext(ThemeContext);
return <button style={{ backgroundColor: theme === 'dark' ? '#333' : '#FFF' }}>Button</button>;
}
7. What is the difference between useMemo
and useCallback
hooks?
- Answer:
useMemo
is used to memoize expensive computations, whileuseCallback
memoizes functions to prevent them from being recreated on each render.useMemo
returns a computed value, whileuseCallback
returns a memoized function.
Example:
import React, { useState, useMemo, useCallback } from 'react';
function ExampleComponent({ items }) {
const [count, setCount] = useState(0);
const expensiveCalculation = useMemo(() => {
console.log("Calculating...");
return items.reduce((a, b) => a + b, 0);
}, [items]);
const increment = useCallback(() => {
setCount(count + 1);
}, [count]);
return (
<div>
<p>Sum: {expensiveCalculation}</p>
<button onClick={increment}>Increment</button>
</div>
);
}
8. What are Higher-Order Components (HOCs) in React?
- Answer: Higher-Order Components (HOCs) are functions that take a component and return a new component. They allow you to reuse component logic and are often used for cross-cutting concerns like logging, handling authentication, or fetching data.
Example:
function withLoading(Component) {
return function WithLoadingComponent({ isLoading, ...props }) {
if (isLoading) return <p>Loading...</p>;
return <Component {...props} />;
};
}
function MyComponent({ data }) {
return <div>Data: {data}</div>;
}
const MyComponentWithLoading = withLoading(MyComponent);
9. What is the purpose of React's useReducer
hook, and how does it differ from useState
?
- Answer:
useReducer
is an alternative touseState
for managing complex state logic. It allows for more sophisticated state management with a reducer function. It's often used when the state has multiple sub-values or when the next state depends on the previous one.
Example:
import React, { useReducer } from 'react';
const initialState = { count: 0 };
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
<button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>
</div>
);
}
10. Explain React's useRef
hook and give an example of its use.
- Answer:
useRef
creates a mutable object that persists for the lifetime of the component. It can be used to access DOM elements directly or to store any mutable value that doesn’t trigger a re-render when updated.
Example: Accessing a DOM element:
import React, { useRef } from 'react';
function InputFocus() {
const inputRef = useRef(null);
const focusInput = () => {
inputRef.current.focus();
};
return (
<div>
<input ref={inputRef} type="text" />
<button onClick={focusInput}>Focus Input</button>
</div>
);
}
11. What is Prop Drilling, and how can it be avoided?
- Answer: Prop Drilling is when props are passed through multiple levels of components to reach a deeply nested component that needs them. It can be avoided by using React Context or state management libraries like Redux.
Example: with Context:
import React, { createContext, useContext } from 'react';
const UserContext = createContext();
function App() {
return (
<UserContext.Provider value="John Doe">
<MainComponent />
</UserContext.Provider>
);
}
function MainComponent() {
return <NestedComponent />;
}
function NestedComponent() {
const user = useContext(UserContext);
return <p>User: {user}</p>;
}
12. What are React Portals, and when would you use them?
- Answer: React Portals allow rendering components outside of their parent component’s DOM hierarchy. This is useful for components like modals, tooltips, or dropdowns, which need to visually break out of their parent container.
Example:
import React from 'react';
import ReactDOM from 'react-dom';
function Modal({ children }) {
return ReactDOM.createPortal(
<div className="modal">{children}</div>,
document.getElementById('modal-root')
);
}
function App() {
return (
<div>
<h1>App Component</h1>
<Modal>
<h2>Modal Content</h2>
</Modal>
</div>
);
}
13. Explain error boundaries in React. How do they work?
- Answer: Error boundaries are React components that catch JavaScript errors in their child component tree, log the errors, and display a fallback UI. They’re created using the
componentDidCatch
lifecycle method or by wrapping components withReact.ErrorBoundary
.
Example:
import React from 'react';
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, info) {
console.error("Error caught by ErrorBoundary:", error, info);
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
function ProblematicComponent() {
throw new Error("Oops! Something went wrong.");
}
function App() {
return (
<ErrorBoundary>
<ProblematicComponent />
</ErrorBoundary>
);
}
14. What is lazy loading in React, and how does it help with performance?
- Answer: Lazy loading is a technique to defer the loading of resources until they are actually needed. In React, it’s commonly used for code-splitting, allowing components to be loaded only when required. This can reduce the initial load time of the application.
Example:
import React, { Suspense, lazy } from 'react';
const LazyComponent = lazy(() => import('./LazyComponent'));
function App() {
return (
<div>
<h1>My App</h1>
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
</div>
);
}
15. What is Redux, and how does it integrate with React?
- Answer: Redux is a state management library that helps manage the state of an application. It stores the global state in a single store, and components can access the state directly. React can integrate with Redux using the
react-redux
library, which providesProvider
,useSelector
, anduseDispatch
hooks.
Example:
import React from 'react';
import { createStore } from 'redux';
import { Provider, useSelector, useDispatch } from 'react-redux';
const initialState = { count: 0 };
function reducer(state = initialState, action) {
switch (action.type) {
case 'INCREMENT':
return { count: state.count + 1 };
default:
return state;
}
}
const store = createStore(reducer);
function Counter() {
const count = useSelector((state) => state.count);
const dispatch = useDispatch();
return (
<div>
<p>Count: {count}</p>
<button onClick={() => dispatch({ type: 'INCREMENT' })}>Increment</button>
</div>
);
}
function App() {
return (
<Provider store={store}>
<Counter />
</Provider>
);
}
16. How does server-side rendering (SSR) work in React, and what are its benefits?
- Answer: Server-side rendering (SSR) is a technique where HTML is generated on the server and sent to the client instead of rendering the content entirely on the client side. This approach improves SEO and reduces the time it takes for the user to see the initial content because the HTML is already present when the page loads.
Example: using Next.js (a popular SSR framework for React):
// pages/index.js
import React from 'react';
function Home({ data }) {
return (
<div>
<h1>Server-side Rendered Data</h1>
<p>{data}</p>
</div>
);
}
export async function getServerSideProps() {
const res = await fetch('https://api.example.com/data');
const data = await res.json();
return { props: { data } };
}
export default Home;
17. What is code splitting in React, and how does it improve performance?
- Answer: Code splitting is a feature in React, often implemented using dynamic imports or tools like Webpack, that allows you to split the application code into smaller chunks. This reduces the initial load time by only loading the code required for the initial render. Additional code is loaded as needed.
Example:
import React, { Suspense, lazy } from 'react';
const HeavyComponent = lazy(() => import('./HeavyComponent'));
function App() {
return (
<div>
<h1>My App</h1>
<Suspense fallback={<div>Loading...</div>}>
<HeavyComponent />
</Suspense>
</div>
);
}
18. What are controlled and uncontrolled components in React?
- Answer: Controlled components are form elements whose values are controlled by React state, while uncontrolled components manage their own state internally, using
ref
to access their values.
Example: of Controlled Component:
function ControlledInput() {
const [value, setValue] = useState('');
return (
<input type="text" value={value} onChange={(e) => setValue(e.target.value)} />
);
}
19. What are React Hooks, and why were they introduced?
- Answer: React Hooks are functions that let you use React features (like state and lifecycle methods) in functional components. They were introduced to reduce complexity in component structure and to allow more reuse and composition of logic.
Basic Hooks include:
- useState
: Manages state in a functional component.
- useEffect
: Manages side effects (e.g., data fetching, subscriptions).
- useContext
: Accesses context values.
- useRef
: Holds a mutable value that persists across renders.
- useReducer
: Manages complex state logic.
20. Explain how React handles events and how they differ from native HTML events.
- Answer: In React, events are handled using synthetic events, which wrap native events and normalize cross-browser inconsistencies. React event handling follows camelCase naming (e.g.,
onClick
), and handlers are passed as functions.
Example:
function ClickHandler() {
const handleClick = (event) => {
console.log("Button clicked:", event);
};
return <button onClick={handleClick}>Click Me</button>;
}
21. What is React.memo, and how does it optimize performance?
- Answer:
React.memo
is a higher-order component that memoizes the output of a component and only re-renders it if the props have changed. This helps optimize performance by preventing unnecessary renders of components that receive the same props.
Example:
const MemoizedComponent = React.memo(function MyComponent({ value }) {
console.log("Rendering MyComponent");
return <div>{value}</div>;
});
function Parent() {
const [count, setCount] = useState(0);
return (
<div>
<MemoizedComponent value="Hello" />
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
22. What are custom hooks, and how are they created?
- Answer: Custom hooks are reusable functions that allow you to encapsulate logic in a way that uses other hooks. Custom hooks must start with
use
in their name and allow you to share stateful logic across multiple components.
Example:
import { useState, useEffect } from 'react';
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch(url)
.then((response) => response.json())
.then((data) => {
setData(data);
setLoading(false);
});
}, [url]);
return { data, loading };
}
function App() {
const { data, loading } = useFetch('https://api.example.com/data');
return <div>{loading ? 'Loading...' : JSON.stringify(data)}</div>;
}
23. How does React.StrictMode
help with debugging?
- Answer:
React.StrictMode
is a wrapper component that activates additional checks and warnings for its children. It highlights potential problems by identifying unsafe lifecycle methods, deprecated APIs, and unexpected side effects. It doesn’t render any UI but is used solely for development.
Example:
import React from 'react';
import ReactDOM from 'react-dom';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
24. What is the purpose of key
props in lists, and why are they important?
- Answer: Keys help React identify which items have changed, are added, or removed, allowing it to optimize rendering by avoiding unnecessary re-renders. A unique
key
prop should be assigned to each element in a list to ensure consistent identity.
Example:
const items = ['Apple', 'Banana', 'Cherry'];
function ItemList() {
return (
<ul>
{items.map((item) => (
<li key={item}>{item}</li>
))}
</ul>
);
}
25. What are fragments in React, and when should they be used?
- Answer: Fragments let you group a list of children without adding extra nodes to the DOM. They’re useful when you want to return multiple elements from a component without a wrapper div.
Example:
function FragmentExample() {
return (
<>
<h1>Title</h1>
<p>This is a paragraph.</p>
</>
);
}
26. What is the useLayoutEffect
hook, and how does it differ from useEffect
?
- Answer:
useLayoutEffect
is similar touseEffect
but is called synchronously after all DOM mutations, blocking the browser's paint until it completes. It is useful when you need to perform updates before the browser repaints, like measuring layout dimensions.
Example:
import React, { useLayoutEffect, useRef } from 'react';
function LayoutEffectExample() {
const divRef = useRef();
useLayoutEffect(() => {
console.log('Height:', divRef.current.clientHeight);
}, []);
return <div ref={divRef}>Hello World</div>;
}
Frequently Asked Questions (FAQs)
Did you find this article valuable?
Support
by becoming a sponsor.Share
# Tags