35 React Interview Questions and Answers (2025)



Lupa will help you hire top talent in Latin America.
Book a Free ConsultationLupa helps you build, manage, and pay your remote team. We deliver pre-vetted candidates within a week!
Book a Free ConsultationReact.js powers some of the world's most-used applications—Facebook, Instagram, Netflix, Airbnb. As a React developer, technical interviews are your gateway to real opportunities. This guide covers the essential React interview questions, from fundamentals to advanced concepts that hiring managers actually test for.
Whether you're a beginner preparing for your first front-end role or an experienced developer brushing up on modern patterns, these answers demonstrate the depth interviewers expect when evaluating your React expertise.
React Fundamentals: Basic Interview Questions
1. What is React and what are its key features?
React is a JavaScript library created by Jordan Walke at Facebook for building user interfaces, particularly single-page applications. Its key features include:
Virtual DOM: React maintains a lightweight JavaScript representation of the actual DOM. When state changes, React updates the virtual DOM first, runs its diffing algorithm to compare with the real DOM, and only updates what changed—making updates incredibly efficient.
Component-based architecture: Build reusable components that manage their own state and compose together for complex user interfaces.
Unidirectional data flow: Data flows one direction from parent component to child component via props, making applications predictable and easier to debug.
JSX syntax: Write HTML-like code in JavaScript for intuitive component creation.
2. What is JSX?
JSX (JavaScript XML) is a syntax extension letting you write HTML-like code in JavaScript files. Tools like Babel transform JSX into React.createElement calls:
// JSX
const Welcome = () => <h1 className="greeting">Hello!</h1>;
// Transforms to
const Welcome = () => React.createElement('h1', { className: 'greeting' }, 'Hello!');Use className instead of class (JavaScript reserved keyword) and wrap JavaScript expressions in curly braces. Handle events with onClick, onChange, and other event handlers.
3. What is the difference between Real DOM and Virtual DOM?
The real DOM is the browser's representation of your page. Updates are expensive—requiring CSS recalculation, layout reflow, and repainting.
The virtual DOM is React's lightweight JavaScript representation. When component state changes, React creates a new virtual DOM tree, compares it with the previous one, calculates minimal changes needed, and updates only those specific DOM elements. This reconciliation process dramatically improves performance.
4. What are components in React?
Components are self-contained, reusable pieces returning React elements. They're the building blocks of React applications.
Functional components are JavaScript functions returning JSX:
function UserCard({ name, email }) {
return (
<div className="user-card">
<h2>{name}</h2>
<p>{email}</p>
</div>
);
}
Class components extend React.Component with a render method and access to lifecycle methods and component state through this.state.
5. What is the difference between functional and class components?
Syntax: Functional components are simpler JavaScript functions. Class components require constructor, render method, and explicit this binding.
State management: Before hooks, only class components had state via setState. Now functional components use useState, making them equally capable.
Lifecycle methods: Class components use componentDidMount, componentDidUpdate, componentWillUnmount. Functional components achieve this with useEffect hook, consolidating lifecycle logic elegantly.
Modern React strongly favors functional components with hooks—they're more performant, produce cleaner code, and enable better logic reuse through custom hooks.
6. What are props in React?
Props (properties) pass data from parent component to child component. They're read-only—child components cannot modify received props, maintaining predictable data flow.
// Parent passing props
<UserProfile name="Sarah" role="Engineer" isActive={true} />
// Child receiving props
function UserProfile({ name, role, isActive }) {
return <div>{name} - {role}</div>;
}
7. What is state in React?
State stores dynamic data in components. Unlike props, state is mutable and managed internally. State changes trigger re-renders.
Class components:
this.state = { count: 0 };
this.setState({ count: this.state.count + 1 });Functional components use useState:
const [count, setCount] = useState(0);
setCount(count + 1);Key difference: State is internal to the component. Props come from the parent. React state changes trigger UI updates.
8. What are controlled and uncontrolled components?
Controlled components manage form data through React state—making React the single source of truth:
const [email, setEmail] = useState('');
<input value={email} onChange={(e) => setEmail(e.target.value)} />Uncontrolled components store data in the DOM, accessed via useRef:
const emailRef = useRef();
<input ref={emailRef} />
// Access with emailRef.current.valueUse controlled components for validation, conditional logic, or synchronized inputs. Use uncontrolled components for simple forms needing values only on submit.
9. What is the significance of keys in React lists?
Keys help React identify which items changed, were added, or removed in lists. They're essential for efficient updates when rendering components.
{tasks.map((task) => <li key={task.id}>{task.title}</li>)}Keys should be stable, unique among siblings, and ideally from your data (like database IDs). Don't use array indices as keys—they cause bugs when items reorder.
10. What is conditional rendering in React?
Conditional rendering uses JavaScript operators to decide what elements to render:
// Ternary operator
{isLoggedIn ? <Dashboard /> : <Login />}
// Logical && for conditional display
{count > 0 && <span>{count} notifications</span>}
// if/else before return
if (isLoading) return <Spinner />;
return <Content />;
React Hooks Interview Questions
11. What are React Hooks?
React hooks let you use state and React features in functional components without classes. Introduced in React 16.8, they solve reusing stateful logic, organizing related code, and avoiding class complexity.
Rules of hooks:
- Call only at top level (never in loops, conditions, or nested functions)
- Call only from React functional components or custom hooks
12. Explain useState Hook with examples
useState adds state to functional components, returning current state and update function:
const [count, setCount] = useState(0);
// Update with new value
setCount(count + 1);
// Update with function (prevents stale closures)
setCount(prev => prev + 1);
// Complex state
const [form, setForm] = useState({ name: '', email: '' });
setForm(prev => ({ ...prev, name: 'Sarah' }));13. How does useEffect Hook work?
useEffect handles side effects—data fetching, subscriptions, DOM manipulation:
useEffect(() => {
// Side effect code
fetchData();
return () => {
// Cleanup (optional)
};
}, [dependencies]);No dependencies: Runs after every render
Empty array: Runs once on mount
With dependencies: Runs when dependencies change
useEffect consolidates componentDidMount, componentDidUpdate, and componentWillUnmount into one API.
14. What is the difference between useMemo and useCallback?
Both use memoization for optimization but memoize different things:
useMemo memoizes computed values:
const sortedData = useMemo(() => data.sort(), [data]);useCallback memoizes functions:
const handleClick = useCallback(() => {
console.log('clicked');
}, []);Use useMemo for expensive calculations. Use useCallback when passing callbacks to optimized child components to prevent unnecessary re-renders.
15. Explain useContext Hook and Context API
Context API solves prop drilling by passing data through the component tree without manual prop threading. useContext simplifies consuming context:
const ThemeContext = React.createContext('light');
function App() {
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
function ThemedButton() {
const theme = useContext(ThemeContext);
return <button style={{ background: theme }}>{theme}</button>;
}
Use React context for global data like themes, authentication, or language preferences.
16. What is useReducer and when would you use it over useState?
useReducer manages complex state logic with multiple sub-values or when next state depends on previous:
function reducer(state, action) {
switch (action.type) {
case 'increment': return { count: state.count + 1 };
case 'decrement': return { count: state.count - 1 };
default: return state;
}
}
const [state, dispatch] = useReducer(reducer, { count: 0 });
dispatch({ type: 'increment' });Use useReducer for complex state with multiple related values. Use useState for simple, independent state.
17. How does useRef work?
useRef creates mutable references persisting across renders without triggering re-renders:
Accessing DOM elements:
const inputRef = useRef(null);
inputRef.current.focus();
<input ref={inputRef} />Storing mutable values:
const timerRef = useRef();
timerRef.current = setInterval(() => {}, 1000);Unlike state, changing useRef doesn't cause re-renders.
18. What are custom hooks and how to create them?
Custom hooks extract component logic into reusable functions. They're JavaScript functions using other hooks, starting with "use":
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch(url)
.then(res => res.json())
.then(setData)
.finally(() => setLoading(false));
}, [url]);
return { data, loading };
}
// Usage
const { data, loading } = useFetch('/api/users');Custom hooks reuse stateful logic across components without changing component hierarchy.
Advanced React Concepts
19. What are Higher Order Components (HOCs)?
HOCs are functions taking a component and returning an enhanced component. They're patterns for reusing component logic:
function withAuth(Component) {
return function AuthComponent(props) {
const { isAuthenticated } = useAuth();
if (!isAuthenticated) return <Navigate to="/login" />;
return <Component {...props} />;
};
}
const ProtectedDashboard = withAuth(Dashboard);Modern React favors custom hooks over HOCs for logic reuse—they're more composable and don't create extra components in the tree.
20. What are Error Boundaries in React?
Error boundaries catch JavaScript errors in child component trees, log errors, and display fallback UI instead of crashing:
class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
console.log('Error:', error);
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
Error boundaries don't catch errors in event handlers, async code, or server-side rendering. Essential for preventing full application crashes.
21. Explain React's Reconciliation algorithm
Reconciliation is how React updates the DOM efficiently. When state or props change, React's diffing algorithm determines minimal changes needed.
Process: React compares new virtual DOM with previous version. Elements of different types rebuild entire tree. Same-type elements update only changed attributes. Keys help identify moved, added, or removed list items.
Understanding reconciliation helps write performant code by avoiding unnecessary re-renders and using proper keys.
22. What are React Portals?
Portals render children into DOM nodes outside parent component hierarchy—useful for modals, tooltips, dropdowns:
createPortal(
<div className="modal">{children}</div>,
document.getElementById('modal-root')
);
Events still bubble through React tree (not DOM tree), and context works normally despite different DOM locations.
23. What is React Suspense?
Suspense lets components "wait" for something before rendering, handling async operations like code splitting:
const Heavy = React.lazy(() => import('./Heavy'));
<Suspense fallback={<div>Loading...</div>}>
<Heavy />
</Suspense>
The fallback prop shows while waiting. React 18 expanded Suspense for data fetching, making async programming more declarative.
24. What is code splitting in React and how is it implemented?
Code splitting splits bundles into smaller chunks loaded on demand, improving initial load time:
const Dashboard = React.lazy(() => import('./Dashboard'));
<Suspense fallback={<div>Loading...</div>}>
<Dashboard />
</Suspense>
Implement route-based splitting for different pages or component-based splitting for heavy modules like charts or editors.
React State Management
25. What is prop drilling and how can you avoid it?
Prop drilling passes data through multiple component levels to reach deeply nested children, even when intermediates don't need that data.
Solutions:
- Context API: Share data without threading props
- Component composition: Pass components as children
- State management libraries: Redux, Zustand for global state
Prop drilling isn't always bad—for 2-3 levels, it keeps data flow explicit.
26. Compare Context API with Redux for state management
Context API: Built into React, simple setup, every update re-renders all consumers. Best for infrequent updates like themes or auth.
Redux: External library, more boilerplate but structured, subscriptions minimize re-renders, middleware support, excellent dev tools with time-travel debugging. Best for large apps with complex state.
Many apps use both: Context for global infrequent data, Redux for complex business logic.
27. What are the core principles of Redux?
- Single source of truth: Entire application state in one store
- State is read-only: Change state only by dispatching actions
- Changes via pure functions: Reducers are pure functions taking previous state and action, returning next state
Redux flow:
// Action
{ type: 'INCREMENT' }
// Reducer
function counter(state = 0, action) {
switch (action.type) {
case 'INCREMENT': return state + 1;
default: return state;
}
}
// Dispatch
store.dispatch({ type: 'INCREMENT' });28. What is Redux Toolkit and how does it simplify Redux?
Redux Toolkit reduces boilerplate with utilities for common Redux patterns:
const counterSlice = createSlice({
name: 'counter',
initialState: 0,
reducers: {
increment: state => state + 1
}
});
createAsyncThunk handles async logic elegantly
Includes Immer for "mutable" code that's actually immutable. The recommended way to write Redux.
React Performance Optimization
29. How can you prevent unnecessary re-renders in React?
React.memo: Memoizes functional components, preventing re-renders when props unchanged
useMemo: Memoizes expensive calculations
useCallback: Prevents function recreation to maintain referential equality
PureComponent: For class components, implements shallow comparison
Only optimize when profiling shows actual performance problems. Premature optimization adds complexity without benefit.
30. What is lazy loading in React and how is it implemented?
Lazy loading defers component loading until needed, reducing initial bundle size:
const Chart = React.lazy(() => import('./Chart'));
<Suspense fallback={<div>Loading...</div>}>
<Chart />
</Suspense>
Most effective for large components not immediately visible—modals, tabs, routes, or heavy third-party libraries.
31. What are the best practices for rendering large lists in React?
Virtualization: Render only visible items using react-window:
<FixedSizeList height={600} itemCount={1000} itemSize={50}>
{({ index, style }) => <div style={style}>{items[index]}</div>}
</FixedSizeList>
Pagination: Load items in chunks
Infinite scrolling: Load more as user scrolls
For thousands of items, virtualization is essential—reduces DOM nodes from thousands to dozens.
React Router and Navigation
32. What is React Router and why is it used?
React Router enables client-side routing for single-page applications with multiple views without page reloads:
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/users/:id" element={<UserProfile />} />
</Routes>
</BrowserRouter>
Handles URL synchronization, browser history, nested routing, route parameters, and programmatic navigation.
33. How do you handle route parameters in React Router?
Capture dynamic URL values with useParams:
// Route definition
<Route path="/users/:userId" element={<UserProfile />} />
// Access parameter
function UserProfile() {
const { userId } = useParams();
return <div>User: {userId}</div>;
}
Parameters are always strings—convert when needed: const id = Number(userId);
Testing and Best Practices
34. How do you test React components?
Unit testing with React Testing Library:
import { render, screen } from '@testing-library/react';
test('renders button', () => {
render(<Button>Click me</Button>);
expect(screen.getByText('Click me')).toBeInTheDocument();
});
Test user interactions, not implementation details. Focus on what users see and do.
35. What is server-side rendering and why use it?
Server-side rendering (SSR) renders React applications on the server, sending HTML to the client. Benefits include better SEO, faster initial page load, and improved performance on slow devices.
Frameworks like Next.js handle SSR complexity, providing routing, data fetching, and optimization out of the box.
Ready to Land Your Next React Role?
These React interview questions cover the technical depth hiring managers expect in 2025. But knowing React isn't enough—you need to demonstrate how you think, solve real-world problems, and communicate about code.
At Lupa, we connect React developers with companies building across the US and Latin America. We don't just match JavaScript skills on paper—we find teams where your technical abilities and work style actually fit. Whether you're a front-end developer looking for your next opportunity or a company building a React application, we focus on quality matches, not speed or volume.
Hiring React developers? We specialize in connecting US companies with premium Latin American tech professionals who bring strong technical skills, cultural alignment, and timezone compatibility. No prop drilling through recruiters who don't understand your API requirements—just vetted React developers who can contribute from day one with functional components, hooks, and modern state management patterns.




















