React Interview Questions and Answers
Components, hooks, rendering behaviour, state management, concurrent features and modern React ecosystem.
Whether you are preparing for entry-level React interview questions for freshers or senior software engineer interview questions addressing concurrency, scalability, and system architecture, this track provides peer-reviewed model answers with syntax walkthroughs, edge cases, and practical interview tips.
1 What are Pure Components? Medium
Pure components are the components which render the same output for the same state and props. In function components, you can achieve these pure components through memoized React.memo() API wrapping around the component. This API prevents unnecessary re-renders by comparing the previous props and new props using shallow comparison. So it will be helpful for performance optimizations.
But at the same time, it won't compare the previous state with the current state because function component itself prevents the unnecessary rendering by default when you set the same state again.
The syntactic representation of memoized components looks like below,
const MemoizedComponent = memo(SomeComponent, arePropsEqual?);
Below is the example of how child component(i.e., EmployeeProfile) prevents re-renders for the same props passed by parent component(i.e.,EmployeeRegForm).
import { memo, useState } from "react";
const EmployeeProfile = memo(function EmployeeProfile({ name, email }) {
return (
<>
<p>Name:{name}</p>
<p>Email: {email}</p>
</>
);
});
export default function EmployeeRegForm() {
const [name, setName] = useState("");
const [email, setEmail] = useState("");
return (
<>
<label>
Name:{" "}
<input value={name} onChange={(e) => setName(e.target.value)} />
</label>
<label>
Email:{" "}
<input value={email} onChange={(e) => setEmail(e.target.value)} />
</label>
<hr />
<EmployeeProfile name={name} />
</>
);
}
In the above code, the email prop has not been passed to child component. So there won't be any re-renders for email prop change.
In class components, the components extending _React.PureComponent_ instead of _React.Component_ become the pure components. When props or state changes, _PureComponent_ will do a shallow comparison on both props and state by invoking shouldComponentUpdate() lifecycle method.
Note: React.memo() is a higher-order component.
2 What are controlled components? Medium
A controlled component is a React component that fully manages the form element's state(e.g, elements like <input>, <textarea>, or <select>)) using React's internal state mechanism. i.e, The component does not manage its own internal state — instead, React acts as the single source of truth for form data.
The controlled components will be implemented using the below steps,
- Initialize the state using
useStatehooks in function components or inside constructor for class components. - Set the value of the form element to the respective state variable.
- Create an event handler(
onChange) to handle the user input changes throughuseState's updater function orsetStatefrom class component. - Attach the above event handler to form element's change or click events
Note: React re-renders the component every time the input value changes.
For example, the name input field updates the username using handleChange event handler as below,
import React, { useState } from "react";
function UserProfile() {
const [username, setUsername] = useState("");
const handleChange = (e) => {
setUsername(e.target.value);
};
return (
<form>
<label>
Name:
<input type="text" value={username} onChange={handleChange} />
</label>
</form>
);
}
In these components, DOM does not hold the actual data instead React does.
Benefits:
- Easy to implement validation, conditional formatting, or live feedback.
- Full control over form data.
- Easier to test and debug because the data is centralized in the component’s state.
3 What are uncontrolled components? Medium
The Uncontrolled components are form elements (like <input>, <textarea>, or <select>) that manage their own state internally via the DOM, rather than through React state.
You can query the DOM using a ref to find its current value when you need it. This is a bit more like traditional HTML.
The uncontrolled components will be implemented using the below steps,
- Create a ref using
useRefreact hook in function component orReact.createRef()in class based component. - Attach this
refto the form element. - The form element value can be accessed directly through
refin event handlers orcomponentDidMountfor class components
In the below UserProfile component, the username input is accessed using ref.
```jsx harmony
import React, { useRef } from "react";
function UserProfile() {
const usernameRef = useRef(null);
const handleSubmit = (event) => {
event.preventDefault();
console.log("The submitted username is: " + usernameRef.current.value);
};
return (
<form onSubmit={handleSubmit}>
<label>
Username:
<input type="text" ref={usernameRef} />
</label>
<button type="submit">Submit</button>
</form>
);
}
**Note:** Here, DOM is in charge of the value. React only accesses the value when needed (via `ref`).
**Benefits:**
* **Less boilerplate** — no need for `useState` and `onChange`.
* Useful for **quick form setups** or when integrating with **non-React code**.
* Slightly better **performance** in very large forms (fewer re-renders).
In most cases, it's recommend to use controlled components to implement forms. In a controlled component, form data is handled by a React component. The alternative is uncontrolled components, where form data is handled by the DOM itself.
<details><summary><b>See Class</b></summary>
<p>
jsx harmonyclass UserProfile extends React.Component {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
this.input = React.createRef();
}
handleSubmit(event) {
alert("A name was submitted: " + this.input.current.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
{"Name:"}
<input type="text" ref={this.input} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
```
</p>
</details>
4 Does the lazy function support named exports? Medium
No, currently React.lazy function supports default exports only. If you would like to import modules which are named exports, you can create an intermediate module that reexports it as the default. It also ensures that tree shaking keeps working and don’t pull unused components.
Let's take a component file which exports multiple named components,
// MoreComponents.js
export const SomeComponent = /* ... */;
export const UnusedComponent = /* ... */;
and reexport MoreComponents.js components in an intermediate file IntermediateComponent.js
// IntermediateComponent.js
export { SomeComponent as default } from "./MoreComponents.js";
Now you can import the module using lazy function as below,
import React, { lazy } from "react";
const SomeComponent = lazy(() => import("./IntermediateComponent.js"));
5 What are portals in React? Medium
A Portal is a React feature that enables rendering children into a DOM node that exists outside the parent component's DOM hierarchy, while still preserving the React component hierarchy. Portals help avoid CSS stacking issues—for example, elements with position: fixed may not behave as expected inside a parent with transform. Portals solve this by rendering content (like modals or tooltips) outside such constrained DOM contexts.
ReactDOM.createPortal(child, container);
child: Any valid React node (e.g., JSX, string, fragment).container: A real DOM node (e.g.,document.getElementById('modal-root')).
Even though the content renders elsewhere in the DOM, it still behaves like a normal child in React. It has access to context, state, and event handling.
Example:- Modal:
function Modal({ children }) {
return ReactDOM.createPortal(
<div className="modal">{children}</div>,
document.body)
);
}
The above code will render the modal content into the body element in the HTML, not inside the component's usual location.
6 Do Hooks replace render props and higher order components? Medium
Both render props and higher-order components render only a single child but in most of the cases Hooks are a simpler way to serve this by reducing nesting in your tree.
7 What is the difference between React context and React Redux? Medium
You can use Context in your application directly and is going to be great for passing down data to deeply nested components which what it was designed for.
Whereas Redux is much more powerful and provides a large number of features that the Context API doesn't provide. Also, React Redux uses context internally but it doesn't expose this fact in the public API.
| Aspect | Context API | Redux |
| --- | --- | --- |
| Purpose | Dependency injection — passes data through the tree without prop drilling | Full state-management library with a predictable, centralized store |
| State updates | Plain useState/useReducer next to the provider; no built-in middleware | Actions + reducers, with middleware support (redux-thunk, redux-saga, etc.) |
| Performance | Every consumer re-renders on any value change unless you split contexts/memoize | Uses selectors (useSelector/connect) so components only re-render when the selected slice changes |
| DevTools | None built-in | Time-travel debugging, action logs via Redux DevTools |
| Async logic | You wire it yourself (custom hooks, effects) | Standardized patterns via middleware |
| Boilerplate | Minimal — just createContext/useContext | More setup, though Redux Toolkit reduces this significantly |
#### Does Context replace Redux?
Not entirely — they solve overlapping but different problems, so the right choice depends on the app's needs:
- Context is a good fit for low-frequency, mostly-static data that many components need (theme, locale, authenticated user, feature flags). Combined with
useReducer, it can even model simple local/global state without pulling in Redux (see [Can you combine useReducer with useContext?](#can-you-combine-usereducer-with-usecontext)). - Redux is still preferable for large apps with complex, frequently-updating state, cross-cutting concerns like caching/undo/logging, a need for middleware (async flows, side effects), or debugging tools like time-travel and action replay.
- Performance matters: Context has no built-in mechanism to prevent unnecessary re-renders of all consumers when the provided value changes, whereas Redux's
useSelectorre-renders only the components that depend on the changed slice of state.
In short, Context is a simpler tool for prop-drilling/dependency-injection use cases, while Redux remains a more robust, scalable option for complex application-wide state management. Many apps use both together — Context for simple, rarely-changing values and Redux (or another store) for the rest.
8 What is React lazy function? Medium
The React.lazy function lets you render a dynamic import as a regular component. It will automatically load the bundle containing the OtherComponent when the component gets rendered. This must return a Promise which resolves to a module with a default export containing a React component.
const OtherComponent = React.lazy(() => import("./OtherComponent"));
function MyComponent() {
return (
<div>
<OtherComponent />
</div>
);
}
Note:React.lazy and Suspense is not yet available for server-side rendering. If you want to do code-splitting in a server rendered app, we still recommend React Loadable.
9 What are hooks? Medium
Hooks is a special JavaScript function that allows you use state and other React features without writing a class. This pattern has been introduced as a new feature in React 16.8 and helped to isolate the stateful logic from the components.
Let's see an example of useState hook:
import { useState } from "react";
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
return (
<>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</>
);
}
Note: Hooks can be used inside an existing function component without rewriting the component.
10 What rules need to be followed for hooks? Medium
You need to follow two rules in order to use hooks,
- Call Hooks only at the top level of your react functions: You should always use hooks at the top level of react function before any early returns. i.e, You shouldn’t call Hooks inside loops, conditions, or nested functions. This will ensure that Hooks are called in the same order each time a component renders and it preserves the state of Hooks between multiple re-renders due to
useStateanduseEffectcalls.
Let's see the difference using an example,
Correct usage::
function UserProfile() {
// Correct: Hooks called at the top level
const [name, setName] = useState('John');
const [country, setCountry] = useState('US');
return (
<div>
<h1>Name: {name}</h1>
<p>Country: {country}</p>
</div>
);
}
Incorrect usage::
function UserProfile() {
const [name, setName] = useState('John');
if (name === 'John') {
// Incorrect: useState is called inside a conditional
const [country, setCountry] = useState('US');
}
return (
<div>
<h1>Name: {name}</h1>
<p>Country: {country}</p> {/* This will throw an error if the name condition isn't met */}
</div>
);
}
The useState hook for the country field is being called conditionally within an if block. This can lead to inconsistent state behavior and may cause hooks to be called in a different order on each re-render.
- Call Hooks from React Functions only: You shouldn’t call Hooks from regular JavaScript functions or class components. Instead, you should call them from either function components or custom hooks.
Let's find the difference of correct and incorrect usage with below examples,
Correct usage::
//Example1:
function Counter() {
// Correct: useState is used inside a functional component
const [count, setCount] = useState(0);
return <div>Counter: {count}</div>;
}
//Example2:
function useFetchData(url) {
const [data, setData] = useState(null);
useEffect(() => {
fetch(url)
.then((response) => response.json())
.then((data) => setData(data));
}, [url]);
return data;
}
function UserProfile() {
// Correct: Using a custom hook here
const user = useFetchData('https://some-api.com/user');
return (
<div>
<h1>{user ? user.name : 'Loading profile...'}</h1>
</div>
);
}
Incorrect usage::
//Example1
function normalFunction() {
// Incorrect: Can't call hooks in normal functions
const [count, setCount] = useState(0);
}
//Example2
function fetchData(url) {
// Incorrect: Hooks can't be used in non-React functions
const [data, setData] = useState(null);
useEffect(() => {
fetch(url)
.then((response) => response.json())
.then((data) => setData(data));
}, [url]);
return data;
}
In the above incorrect usage example, both useState and useEffect are used in non-React functions(normalFunction and fetchData), which is not allowed.
11 How to ensure hooks followed the rules in your project? Medium
React team released an ESLint plugin called eslint-plugin-react-hooks that enforces Hook's two rules. It is part of Hooks API. You can add this plugin to your project using the below command,
npm install eslint-plugin-react-hooks --save-dev
And apply the below config in your ESLint config file,
// Your ESLint configuration
{
"plugins": [
// ...
"react-hooks"
],
"rules": {
// ...
"react-hooks/rules-of-hooks": "error"
}
}
This plugin also provide another important rule through react-hooks/exhaustive-deps. It ensures that the dependencies of useEffect, useCallback, and useMemo hooks are correctly listed to avoid potential bugs.
useEffect(() => {
// Forgetting `message` will result in incorrect behavior
console.log(message);
}, []); // Here `message` should be a dependency
The recommended eslint-config-react-app preset already includes the hooks rules of this plugin.
For example, the linter enforce proper naming convention for hooks. If you rename your custom hooks which as prefix "use" to something else then linter won't allow you to call built-in hooks such as useState, useEffect etc inside of your custom hook anymore.
Note: This plugin is intended to use in Create React App by default.
12 Can you describe about componentDidCatch lifecycle method signature? Medium
The componentDidCatch lifecycle method is invoked after an error has been thrown by a descendant component. The method receives two parameters,
- error: - The error object which was thrown
- info: - An object with a componentStack key contains the information about which component threw the error.
The method structure would be as follows
componentDidCatch(error, info);
13 What is the benefit of component stack trace from error boundary? Medium
Apart from error messages and javascript stack, React16 will display the component stack trace with file names and line numbers using error boundary concept.
For example, BuggyCounter component displays the component stack trace as below,

14 What is the purpose of default value in context? Medium
The defaultValue argument is only used when a component does not have a matching Provider above it in the tree. This can be helpful for testing components in isolation without wrapping them.
Below code snippet provides default theme value as Luna.
const MyContext = React.createContext(defaultValue);
15 What are the problems of using render props with pure components? Medium
If you create a function inside a render method, it negates the purpose of pure component. Because the shallow prop comparison will always return false for new props, and each render in this case will generate a new value for the render prop. You can solve this issue by defining the render function as instance method.
class Mouse extends React.PureComponent {
render() {
// BAD: a new arrow function reference is created on every render,
// so PureComponent's shallow comparison always sees "new" props
return <MouseTracker render={(mouse) => <Cat mouse={mouse} />} />;
}
}
class MouseWithCat extends React.PureComponent {
// GOOD: defined once as an instance method/class property, so the
// reference stays stable across renders
renderTheCat = (mouse) => <Cat mouse={mouse} />;
render() {
return <MouseTracker render={this.renderTheCat} />;
}
}
16 What is the typical use case of portals? Medium
React Portals are primarily used to render UI components such as modals, tooltips, dropdowns, hovercards, and notifications outside of their parent component's DOM tree. This helps avoid common CSS issues caused by parent elements, such as:
overflow: hiddenon parent elements clipping or hiding child elements like modals or tooltips,- stacking context and
z-indexconflicts created by parent containers that prevent child elements from appearing above other content.
That means, you need to visually “break out” of its container. By rendering these UI elements into a separate DOM node (often directly under <body>), portals ensure they appear above all other content and are not restricted by the parent’s CSS or layout constraints, resulting in correct positioning and visibility regardless of the parent’s styling.
17 How do you set default value for uncontrolled component? Medium
In React, the value attribute on form elements will override the value in the DOM. With an uncontrolled component, you might want React to specify the initial value, but leave subsequent updates uncontrolled. To handle this case, you can specify a defaultValue attribute instead of value.
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
User Name:
<input
defaultValue="John"
type="text"
ref={this.input} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
The same applies for select and textArea inputs. But you need to use defaultChecked for checkbox and radio inputs.
18 Do I need to rewrite all my class components with hooks? Medium
No. But you can try Hooks in a few components(or new components) without rewriting any existing code. Because there are no plans to remove classes in ReactJS.
19 What is useEffect hook? How to fetch data with React Hooks? Medium
The useEffect hook is a React Hook that lets you perform side effects in function components. Side effects are operations that interact with the outside world or system and aren't directly related to rendering UI — such as fetching data, setting up subscriptions, timers, manually manipulating the DOM, etc.
In function components, useEffect replaces the class component lifecycle methods(componentDidMount, componentDidUpdate and componentWillUnmount) with a single, unified API.
Syntax
useEffect(() => {
// Side effect logic here
return () => {
// Cleanup logic (optional)
};
}, [dependencies]);
This effect hook can be used to fetch data from an API and to set the data in the local state of the component with the useState hook’s update function.
Here is an example of fetching a list of ReactJS articles from an API using fetch.
import React from "react";
function App() {
const [data, setData] = React.useState({ hits: [] });
React.useEffect(() => {
fetch("http://hn.algolia.com/api/v1/search?query=react")
.then((response) => response.json())
.then((data) => setData(data));
}, []);
return (
<ul>
{data.hits.map((item) => (
<li key={item.objectID}>
<a href={item.url}>{item.title}</a>
</li>
))}
</ul>
);
}
export default App;
A popular way to simplify this is by using the library axios.
We provided an empty array as second argument to the useEffect hook to avoid activating it on component updates. This way, it only fetches on component mount.
20 Is Hooks cover all use cases for classes? Medium
Hooks doesn't cover all use cases of classes but there is a plan to add them soon. Currently there are no Hook equivalents to the uncommon getSnapshotBeforeUpdate and componentDidCatch lifecycles yet.
21 What is the stable release for hooks support? Medium
React includes a stable implementation of React Hooks in 16.8 release for below packages
- React DOM
- React DOM Server
- React Test Renderer
- React Shallow Renderer
22 What are the sources used for introducing hooks? Medium
Hooks got the ideas from several different sources. Below are some of them,
- Previous experiments with functional APIs in the react-future repository
- Community experiments with render prop APIs such as Reactions Component
- State variables and state cells in DisplayScript.
- Subscriptions in Rx.
- Reducer components in ReasonReact.
23 What is the purpose of eslint plugin for hooks? Medium
The ESLint plugin enforces rules of Hooks to avoid bugs. It assumes that any function starting with ”use” and a capital letter right after it is a Hook. In particular, the rule enforces that,
- Calls to Hooks are either inside a PascalCase function (assumed to be a component) or another useSomething function (assumed to be a custom Hook).
- Hooks are called in the same order on every render.
24 How do you make sure that user remains authenticated on page refresh while using Context API State Management? Medium
When a user logs in and reload, to persist the state generally we add the load user action in the useEffect hooks in the main App.js. While using Redux, loadUser action can be easily accessed.
App.js
import { loadUser } from "../actions/auth";
store.dispatch(loadUser());
- But while using Context API, to access context in App.js, wrap the AuthState in index.js so that App.js can access the auth context. Now whenever the page reloads, no matter what route you are on, the user will be authenticated as loadUser action will be triggered on each re-render.
index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import AuthState from "./context/auth/AuthState";
ReactDOM.render(
<React.StrictMode>
<AuthState>
<App />
</AuthState>
</React.StrictMode>,
document.getElementById("root")
);
App.js
const authContext = useContext(AuthContext);
const { loadUser } = authContext;
useEffect(() => {
loadUser();
}, []);
loadUser
const loadUser = async () => {
const token = sessionStorage.getItem("token");
if (!token) {
dispatch({
type: ERROR,
});
}
setAuthToken(token);
try {
const res = await axios("/api/auth");
dispatch({
type: USER_LOADED,
payload: res.data.data,
});
} catch (err) {
console.error(err);
}
};
> Modern React Note (React 18/19): ReactDOM.render was deprecated in React 18 and removed in React 19. In modern applications, always use createRoot from react-dom/client:
>
> import { createRoot } from 'react-dom/client';
> const root = createRoot(document.getElementById('root'));
> root.render(<App />);
>
25 What is the difference between useState and useRef hook? Medium
- useState causes components to re-render after state updates whereas useRef doesn’t cause a component to re-render when the value or state changes.
Essentially, useRef is like a “box” that can hold a mutable value in its (.current) property.
- useState allows us to update the state inside components. While useRef allows referencing DOM elements and tracking values.
26 What are the differences between useEffect and useLayoutEffect hooks? Medium
useEffect and useLayoutEffect are both React hooks that can be used to synchronize a component with an external system, such as a browser API or a third-party library. However, there are some key differences between the two:
- Timing: useEffect runs after the browser has finished painting, while useLayoutEffect runs synchronously before the browser paints. This means that useLayoutEffect can be used to measure and update layout in a way that feels more synchronous to the user.
- Browser Paint: useEffect allows browser to paint the changes before running the effect, hence it may cause some visual flicker. useLayoutEffect synchronously runs the effect before browser paints and hence it will avoid visual flicker.
- Execution Order: The order in which multiple useEffect hooks are executed is determined by React and may not be predictable. However, the order in which multiple useLayoutEffect hooks are executed is determined by the order in which they were called.
- Error handling: useEffect has a built-in mechanism for handling errors that occur during the execution of the effect, so that it does not crash the entire application. useLayoutEffect does not have this mechanism, and errors that occur during the execution of the effect will crash the entire application.
In general, it's recommended to use useEffect as much as possible, because it is more performant and less prone to errors. useLayoutEffect should only be used when you need to measure or update layout, and you can't achieve the same result using useEffect.
27 What is useContext? What are the steps to follow for useContext? Medium
The useContext hook is a built-in React Hook that lets you access the value of a context inside a functional component without needing to wrap it in a <Context.Consumer> component.
It helps you avoid prop drilling (passing props through multiple levels) by allowing components to access shared data like themes, authentication status, or user preferences.
The usage of useContext involves three main steps:
#### Step 1 : Create the Context
Use React.createContext() to create a context object.
import React, { createContext } from 'react';
const ThemeContext = createContext(); // default value optional
You typically export this so other components can import it.
#### Step 2: Provide the Context Value
Wrap your component tree (or a part of it) with the Context.Provider and pass a value prop.
function App() {
return (
<ThemeContext.Provider value="dark">
<MyComponent />
</ThemeContext.Provider>
);
}
Now any component inside <ThemeContext.Provider> can access the context value.
#### Step 3: Consume the Context with useContext
In any functional component inside the Provider, use the useContext hook:
import { useContext } from 'react';
function MyComponent() {
const theme = useContext(ThemeContext); // theme = "dark"
return <p>Current Theme: {theme}</p>;
}
28 What are the use cases of useContext hook? Medium
The useContext hook in React is used to share data across components without having to pass props manually through each level. Here are some common and effective use cases:
- Theme Customization
useContext can be used to manage application-wide themes, such as light and dark modes, ensuring consistent styling and enabling user-driven customization.
- Localization and Internationalization
It supports localization by providing translated strings or locale-specific content to components, adapting the application for users in different regions.
- User Authentication and Session Management
useContext allows global access to authentication status and user data. This enables conditional rendering of components and helps manage protected routes or user-specific UI elements.
- Shared Modal or Sidebar Visibility
It's ideal for managing the visibility of shared UI components like modals, drawers, or sidebars, especially when their state needs to be controlled from various parts of the app.
- Combining with
useReducerfor Global State Management
When combined with useReducer, useContext becomes a powerful tool for managing more complex global state logic. This pattern helps maintain cleaner, scalable state logic without introducing external libraries like Redux.
Some of the common use cases of useContext are listed below,
29 Can you describe the useMemo() Hook? Medium
The useMemo() Hook in React is used to optimize performance by memoizing the result of expensive calculations. It ensures that a function is only re-executed when its dependencies change, preventing unnecessary computations on every re-render.
#### Syntax
const memoizedValue = useMemo(() => computeExpensiveValue(arg), [dependencies]);
computeExpensiveValue:
A function that returns the computed result.
dependencies:
An array of values that, when changed, will cause the memoized function to re-run.
If the dependencies haven’t changed since the last render, React returns the cached result instead of re-running the function.
Let's exaplain the usage of useMemo hook with an example of user search and its respective filtered users list.
#### Example: Memoizing a Filtered List
import React, { useState, useMemo } from 'react';
const users = [
{ id: 1, name: 'Sudheer' },
{ id: 2, name: 'Brendon' },
{ id: 3, name: 'Charlie' },
{ id: 4, name: 'Dary' },
{ id: 5, name: 'Eden' }
];
export default function UserSearch({ users }) {
const [searchTerm, setSearchTerm] = useState('');
const [counter, setCounter] = useState(0);
// Memoize the filtered user list based on the search term
const filteredUsers = useMemo(() => {
console.log("Filtering users...");
return users.filter(user =>
user.name.toLowerCase().includes(searchTerm.toLowerCase())
);
}, [searchTerm]);
return (
<div>
<h2>Counter: {counter}</h2>
<button onClick={() => setCounter(prev => prev + 1)}>Increment Counter</button>
<h2>Search Users</h2>
<input
type="text"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
placeholder="Enter name"
/>
<ul>
{filteredUsers.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
}
In the above example:
- The filteredUsers list is only recomputed when searchTerm changes.
- Pressing the "Increment Counter" button does not trigger the filtering logic again, as it's not a dependency.
- The console will only log "Filtering users..." when the search term updates.
30 Can Hooks be used in class components? Medium
No, Hooks cannot be used inside class components. They are specially designed for function components. This is because hooks depend on the sequence in which they are called during a component’s render, something that's only guaranteed in functional components. However, both class and function components can coexist in the same application.
31 Can you combine **useReducer** with **useContext**? Medium
Yes, it's common to combine useReducer with useContext to build a lightweight state management system similar to Redux:
const AppContext = React.createContext();
function AppProvider({ children }) {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<AppContext.Provider value={{ state, dispatch }}>
{children}
</AppContext.Provider>
);
}
32 How does useContext works? Explain with an example Medium
The useContext hook can be used for authentication state management across multiple components and pages in a React application.
Let's build a simple authentication flow with:
- Login and Logout buttons
- Global
AuthContextto share state - Components that can access and update auth status
1. Create the Auth Context:
You can define AuthProvider which holds and provides user, login(), and logout() via context.
// AuthContext.js
import React, { createContext, useContext, useState } from 'react';
const AuthContext = createContext();
export function AuthProvider({ children }) {
const [user, setUser] = useState(null);
const login = (username) => setUser({ name: username });
const logout = () => setUser(null);
return (
<AuthContext.Provider value={{ user, login, logout }}>
{children}
</AuthContext.Provider>
);
}
// Custom hook for cleaner usage
export const useAuth = () => useContext(AuthContext);
2. Wrap Your App with the Provider:
Wrap the above created provider in main App.js file
// App.js
import React from 'react';
import { AuthProvider } from './AuthContext';
import HomePage from './HomePage';
import Dashboard from './Dashboard';
function App() {
return (
<AuthProvider>
<HomePage />
<Dashboard />
</AuthProvider>
);
}
export default App;
3. Home page with login:
Read or access user and login details through custom useAuth hook and use it inside home page.
// HomePage.js
import React from 'react';
import { useAuth } from './AuthContext';
function HomePage() {
const { user, login } = useAuth();
return (
<div>
<h1>Home</h1>
{user ? (
<p>Welcome back, {user.name}!</p>
) : (
<button onClick={() => login('Alice')}>Login</button>
)}
</div>
);
}
export default HomePage;
4. Dashboard with logout:
Read or access user and logout details from useAuth custom hook and use it inside dashboard page.
// Dashboard.js
import React from 'react';
import { useAuth } from './AuthContext';
function Dashboard() {
const { user, logout } = useAuth();
if (!user) {
return <p>Please login to view the dashboard.</p>;
}
return (
<div>
<h2>Dashboard</h2>
<p>Logged in as: {user.name}</p>
<button onClick={logout}>Logout</button>
</div>
);
}
export default Dashboard;
33 Can You Use Multiple Contexts in One Component? Medium
Yes, it is possible. You can use multiple contexts inside the same component by calling useContext multiple times, once for each context.
It can be achieved with below steps,
- Create multiple contexts using
createContext(). - Wrap your component tree with multiple
<Provider>s. - Call
useContext()separately for each context in the same component.
Example: Using ThemeContext and UserContext Together
import React, { createContext, useContext } from 'react';
// Step 1: Create two contexts
const ThemeContext = createContext();
const UserContext = createContext();
function Dashboard() {
// Step 2: Use both contexts
const theme = useContext(ThemeContext);
const user = useContext(UserContext);
return (
<div style={{ background: theme === 'dark' ? '#333' : '#fff' }}>
<h1>Welcome, {user.name}</h1>
<p>Current theme: {theme}</p>
</div>
);
}
// Step 3: Provide both contexts
function App() {
return (
<ThemeContext.Provider value="dark">
<UserContext.Provider value={{ name: 'Sudheer' }}>
<Dashboard />
</UserContext.Provider>
</ThemeContext.Provider>
);
}
export default App;
34 What's a common pitfall when using useContext with objects? Medium
A common pitfall when using useContext with objects is triggering unnecessary re-renders across all consuming components — even when only part of the context value changes.
When you provide an object as the context value, React compares the entire object reference. If the object changes (even slightly), React assumes the whole context has changed, and all components using useContext(MyContext) will re-render, regardless of whether they use the part that changed.
Example:
const MyContext = React.createContext();
function MyProvider({ children }) {
const [user, setUser] = useState(null);
const [theme, setTheme] = useState('light');
// This causes all consumers to re-render on any state change
const contextValue = { user, setUser, theme, setTheme };
return (
<MyContext.Provider value={contextValue}>
{children}
</MyContext.Provider>
);
}
In this case, a change in theme will also trigger a re-render in components that only care about user.
This issue can be fixed in two ways,
1. Split Contexts
Create separate contexts for unrelated pieces of state:
const UserContext = React.createContext();
const ThemeContext = React.createContext();
2. Memoize Context Value
Use useMemo to prevent unnecessary re-renders:
const contextValue = useMemo(() => ({ user, setUser, theme, setTheme }), [user, theme]);
However, this only helps if the object structure and dependencies are well controlled.
35 What would the context value be for no matching provider? Medium
When a component calls useContext(SomeContext) but no matching <SomeContext.Provider> is present higher up in the component tree, the default value passed to React.createContext(defaultValue) is returned.
const ThemeContext = React.createContext('light'); // 'light' is the default value
function ThemedComponent() {
const theme = useContext(ThemeContext);
return <div>Current theme: {theme}</div>;
}
// No ThemeContext.Provider anywhere in the tree
In this case, theme will be 'light'. It's the default value you provided when you created the context.
Note: If you don’t specify a default value, the context value will be undefined when used without a provider:
const AuthContext = React.createContext(); // No default
function Profile() {
const auth = useContext(AuthContext);
// auth will be undefined if there's no AuthContext.Provider
}
36 How do reactive dependencies in the useEffect dependency array affect its execution behavior? Medium
The useEffect hook accepts an optional dependencies argument that accepts an array of reactive values. The dependency array determines when the effect runs. i.e, It makes useEffect _reactive_ to changes in specified values.
#### How Dependency Array Affects Behavior
- Empty Dependency Array:
[]
useEffect(() => {
// runs once after the initial render
}, []);
- Effect runs only once (like
componentDidMount). - Ignores all state/prop changes.
- With Specific Dependencies:
[count, user]
useEffect(() => {
// runs after initial render
// AND whenever `count` or `user` changes
}, [count, user]);
- Effect runs on first render, and
- Again every time any dependency value changes.
- No Dependency Array (Omitted)
useEffect(() => {
// runs after **every** render
});
- Effect runs after every render, regardless of what changed.
- Can lead to performance issues if not used carefully.
React uses shallow comparison of the dependencies. If any value has changed (!==), the effect will re-run.
Note: This hook works well when dependencies are primitives or memoized objects/functions.
37 When and how often does React invoke the setup and cleanup functions inside a useEffect hook? Medium
- Setup Function Execution (
useEffect)
The setup function (or the main function) you pass to useEffect runs at specific points:
- After the component is mounted (if the dependency array is empty
[]) - After every render (if no dependency array is provided)
- After a dependency value changes (if the dependency array contains variables)
- Cleanup Function Execution (Returned function from
useEffect)
The cleanup function is called before the effect is re-executed and when the component unmounts.
38 What happens if you return a Promise from useEffect?? Medium
You should NOT return a Promise from useEffect. React expects the function passed to useEffect to return either nothing (undefined) or a cleanup function (synchronous function). i.e, It does not expect or handle a returned Promise. If you still return a Promise, React will ignore it silently, and it may lead to bugs or warnings in strict mode.
Incorrect:
useEffect(async () => {
await fetchData(); // ❌ useEffect shouldn't be async
}, []);
Correct:
useEffect(() => {
const fetchData = async () => {
const res = await fetch('/api');
const data = await res.json();
setData(data);
};
fetchData();
}, []);
39 Can you have multiple useEffect hooks in a single component? Medium
Yes, multiple useEffect hooks are allowed and recommended when you want to separate concerns.
useEffect(() => {
// Handles API fetch
}, []);
useEffect(() => {
// Handles event listeners
}, []);
Each effect runs independently and helps make code modular and easier to debug.
40 How to prevent infinite loops with useEffect? Medium
Infinite loops happen when the effect updates state that’s listed in its own dependency array, which causes the effect to re-run, updating state again and so on.
Infinite loop scenario:
useEffect(() => {
setCount(count + 1);
}, [count]); // Triggers again every time count updates
You need to ensure that setState calls do not depend on values that cause the effect to rerun, or isolate them with a guard.
useEffect(() => {
if (count < 5) {
setCount(count + 1);
}
}, [count]);
41 What are the common usecases of useRef hook? Medium
Some of the common cases are:
- Automatically focus an input when a component mounts.
- Scroll to a specific element.
- Measure element dimensions (
offsetWidth,clientHeight). - Control video/audio playback.
- Integrate with non-React libraries (like D3 or jQuery).
42 What is useImperativeHandle Hook? Give an example. Medium
useImperativeHandle is a React Hook that allows a child component to expose custom functions or properties to its parent component, when using ref.
It is typically used with forwardRef and is very useful in cases like modals, dialogs, custom inputs, etc., where the parent needs to control behavior imperatively (e.g., open, close, reset).
Example: Dialog component
import React, {
useRef,
useState,
useImperativeHandle,
forwardRef,
} from 'react';
import './Dialog.css';
const Dialog = forwardRef((props, ref) => {
const [isOpen, setIsOpen] = useState(false);
const [formData, setFormData] = useState('');
useImperativeHandle(ref, () => ({
open: () => setIsOpen(true),
close: () => setIsOpen(false),
reset: () => setFormData(''),
}));
if (!isOpen) return null;
return (
<div className="dialog">
<h2>Dialog</h2>
<input
type="text"
value={formData}
placeholder="Type something..."
onChange={(e) => setFormData(e.target.value)}
/>
<br />
<button onClick={() => setIsOpen(false)}>Close</button>
</div>
);
});
function Parent() {
const dialogRef = useRef();
return (
<div>
<h1>useImperativeHandle Dialog Example</h1>
<button onClick={() => dialogRef.current.open()}>Open Dialog</button>
<button onClick={() => dialogRef.current.reset()}>Reset Dialog</button>
<button onClick={() => dialogRef.current.close()}>Close Dialog</button>
<Dialog ref={dialogRef} />
</div>
);
}
export default Parent;
43 Is that possible to use useImperativeHandle without forwardRef? Medium
No. useImperativeHandle only works when the component is wrapped in forwardRef. It's the combination that allows parent components to use a ref on a function component.
44 How is useMemo different from useCallback? Medium
The following table compares both useMemo and useCallback:
| Feature | useMemo | useCallback |
| --- | --- | --- |
| Purpose | Memoizes the result of a computation | Memoizes a function reference |
| Returns | A value (e.g., result of a function) | A function |
| Usage | useMemo(() => computeValue(), [deps]) | useCallback(() => doSomething(), [deps]) |
| Primary Use Case | Avoid expensive recalculations | Prevent unnecessary re-creations of functions |
| Common Scenario | Filtering, sorting, calculating derived data | Passing callbacks to child components |
| When It's Useful | When the value is expensive to compute | When referential equality matters (e.g., props) |
| Recomputed When | Dependencies change | Dependencies change |
| Returned Value Type | Any (number, object, array, etc.) | Always a function |
| Overhead | Slight (evaluates a function and caches result) | Slight (caches a function reference) |
45 Does useMemo prevent re-rendering of child components? Medium
The useMemo hook does not directly prevent re-rendering of child components. Its main purpose is to memoize the result of an expensive computation so that it doesn’t get recalculated unless its dependencies change. While this can improve performance, it doesn’t inherently control whether a child component re-renders.
However, useMemo can help prevent re-renders when the memoized value is passed as a prop to a child component that is wrapped in React.memo. In that case, if the memoized value doesn’t change between renders (i.e., it has the same reference), React.memo can skip re-rendering the child. So, while useMemo doesn’t stop renders on its own, it works in combination with tools like React.memo to optimize rendering behavior.
46 What is `useCallback` and why is it used? Medium
The useCallback is a React Hook used to memoize function definitions between renders. It returns the same function reference unless its dependencies change. This is especially useful when passing callbacks to optimized child components (e.g. those wrapped in React.memo) to prevent unnecessary re-renders.
Example:
const handleClick = useCallback(() => {
console.log('Button clicked');
}, []);
Without useCallback, a new function is created on every render, potentially causing child components to re-render unnecessarily.
47 What are Custom React Hooks, and How Can You Develop One? Medium
Custom Hooks in React are JavaScript functions that allow you to extract and reuse component logic using React’s built-in Hooks like useState, useEffect, etc.
They start with the word "use" and let you encapsulate logic that multiple components might share—such as fetching data, handling forms, or managing timers—without repeating code.
Let's explain the custom hook usage with useFetchData example. The useFetchData custom Hook is a reusable function in React that simplifies the process of fetching data from an API. It encapsulates common logic such as initiating the fetch request, managing loading and error states, and storing the fetched data. By using built-in Hooks like useState and useEffect, useFetchData provides a clean interface that returns the data, loading, and error values, which can be directly used in components.
import { useState, useEffect } from 'react';
function useFetchData(url) {
const [data, setData] = useState(null); // Holds the response
const [loading, setLoading] = useState(true); // Loading state
const [error, setError] = useState(null); // Error state
useEffect(() => {
let isMounted = true; // Prevent setting state on unmounted component
setLoading(true);
fetch(url)
.then((response) => {
if (!response.ok) throw new Error('Network response was not ok');
return response.json();
})
.then((json) => {
if (isMounted) {
setData(json);
setLoading(false);
}
})
.catch((err) => {
if (isMounted) {
setError(err.message);
setLoading(false);
}
});
return () => {
isMounted = false; // Clean-up function to avoid memory leaks
};
}, [url]);
return { data, loading, error };
}
The above custom hook can be used to retrieve users data for AuthorList, ReviewerList components.
Example: AuthorList component
function AuthorList() {
const { data, loading, error } = useFetchData('https://api.example.com/authors');
if (loading) return <p>Loading authors...</p>;
if (error) return <p>Error: {error}</p>;
return (
<ul>
{data.map((author) => (
<li key={author.id}>{author.name}</li>
))}
</ul>
);
}
Some of the benefits of custom hooks are:
- Promotes code reuse
- Keeps components clean and focused
- Makes complex logic easier to test and maintain
48 What is the useId hook and when should you use it? Medium
The useId hook is a React hook introduced in React 18 that generates unique IDs that are stable across server and client renders. It's primarily used for accessibility attributes like linking form labels to inputs.
#### Syntax
const id = useId();
#### Example: Accessible Form Input
import { useId } from 'react';
function EmailField() {
const id = useId();
return (
<div>
<label htmlFor={id}>Email:</label>
<input id={id} type="email" />
</div>
);
}
#### When to Use
- Generating unique IDs for form elements (
htmlFor,aria-describedby,aria-labelledby) - Creating stable IDs in server-side rendering (SSR) applications
- Avoiding ID collisions when the same component is rendered multiple times
#### When NOT to Use
- As keys in a list (use data-based keys instead)
- As CSS selectors or query selectors
- For any purpose that requires the ID to be predictable
Note: The IDs generated by useId contain colons (:) which may not work in CSS selectors. For multiple related IDs, you can use the same id as a prefix: ${id}-firstName, ${id}-lastName.
49 What is the useDeferredValue hook? Medium
The useDeferredValue hook is used to defer updating a part of the UI to keep other parts responsive. It accepts a value and returns a "deferred" version of that value that may lag behind. This is useful for optimizing performance when rendering expensive components.
#### Syntax
const deferredValue = useDeferredValue(value);
#### Example: Search with Deferred Results
import { useState, useDeferredValue, useMemo } from 'react';
function SearchResults({ query }) {
// Expensive computation or large list filtering
const results = useMemo(() => {
return largeDataSet.filter(item =>
item.name.toLowerCase().includes(query.toLowerCase())
);
}, [query]);
return (
<ul>
{results.map(item => <li key={item.id}>{item.name}</li>)}
</ul>
);
}
function SearchPage() {
const [query, setQuery] = useState('');
const deferredQuery = useDeferredValue(query);
const isStale = query !== deferredQuery;
return (
<div>
<input
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="Search..."
/>
<div style={{ opacity: isStale ? 0.5 : 1 }}>
<SearchResults query={deferredQuery} />
</div>
</div>
);
}
The input stays responsive while the expensive SearchResults component re-renders with a slight delay using the deferred value.
50 What is the useTransition hook and how does it differ from useDeferredValue? Medium
The useTransition hook allows you to mark certain state updates as non-urgent transitions, keeping the UI responsive during expensive re-renders. It returns a isPending flag and a startTransition function.
#### Syntax
const [isPending, startTransition] = useTransition();
#### Example: Tab Switching
import { useState, useTransition } from 'react';
function TabContainer() {
const [isPending, startTransition] = useTransition();
const [tab, setTab] = useState('home');
function selectTab(nextTab) {
startTransition(() => {
setTab(nextTab);
});
}
return (
<div>
<button onClick={() => selectTab('home')}>Home</button>
<button onClick={() => selectTab('posts')}>Posts (slow)</button>
<button onClick={() => selectTab('contact')}>Contact</button>
{isPending && <Spinner />}
{tab === 'home' && <HomeTab />}
{tab === 'posts' && <PostsTab />} {/* Expensive component */}
{tab === 'contact' && <ContactTab />}
</div>
);
}
#### Differences from useDeferredValue
| Feature | useTransition | useDeferredValue |
|---------|--------------|------------------|
| Controls | State updates (wraps setState) | Values (wraps a value) |
| Use case | When you control the state update | When you receive a value from props or other hooks |
| Returns | [isPending, startTransition] | Deferred value |
| Pending state | Built-in isPending flag | Manual comparison needed |
51 What is the useSyncExternalStore hook? Medium
The useSyncExternalStore hook is designed to subscribe to external stores (non-React state sources) in a way that's compatible with concurrent rendering. It's primarily used by library authors for state management libraries.
#### Syntax
const state = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot?);
- subscribe: Function to subscribe to the store, returns an unsubscribe function
- getSnapshot: Function that returns the current store value
- getServerSnapshot: Optional function for SSR that returns the initial server snapshot
#### Example: Browser Online Status
import { useSyncExternalStore } from 'react';
function getSnapshot() {
return navigator.onLine;
}
function subscribe(callback) {
window.addEventListener('online', callback);
window.addEventListener('offline', callback);
return () => {
window.removeEventListener('online', callback);
window.removeEventListener('offline', callback);
};
}
function useOnlineStatus() {
return useSyncExternalStore(subscribe, getSnapshot, () => true);
}
function StatusBar() {
const isOnline = useOnlineStatus();
return <h1>{isOnline ? '✅ Online' : '❌ Disconnected'}</h1>;
}
This hook ensures that when the external store changes, React re-renders consistently without tearing (showing inconsistent data).
52 What is the useInsertionEffect hook? Medium
The useInsertionEffect hook is designed for CSS-in-JS library authors to inject styles into the DOM before any layout effects run. It fires synchronously before DOM mutations.
#### Syntax
useInsertionEffect(() => {
// Insert styles here
return () => {
// Cleanup
};
}, [dependencies]);
#### Execution Order
1. useInsertionEffect → Inject styles
2. DOM mutations → React updates DOM
3. useLayoutEffect → Read layout, synchronously re-render if needed
4. Browser paint → User sees the result
5. useEffect → Side effects run
#### Example: Dynamic Style Injection
import { useInsertionEffect } from 'react';
let isInserted = new Set();
function useCSS(rule) {
useInsertionEffect(() => {
if (!isInserted.has(rule)) {
isInserted.add(rule);
const style = document.createElement('style');
style.textContent = rule;
document.head.appendChild(style);
}
}, [rule]);
}
function Button() {
useCSS('.dynamic-btn { background: blue; color: white; }');
return <button className="dynamic-btn">Click me</button>;
}
Note: This hook is not intended for application code. It's specifically for CSS-in-JS libraries like styled-components or Emotion to prevent style flickering.
53 How do you share state logic between components using custom hooks? Medium
Custom hooks allow you to extract and share stateful logic between components without changing their hierarchy. The state itself is not shared—each component using the hook gets its own isolated state.
#### Example: useLocalStorage Hook
import { useState, useEffect } from 'react';
function useLocalStorage(key, initialValue) {
// Get stored value or use initial value
const [storedValue, setStoredValue] = useState(() => {
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch (error) {
console.error(error);
return initialValue;
}
});
// Update localStorage when state changes
useEffect(() => {
try {
window.localStorage.setItem(key, JSON.stringify(storedValue));
} catch (error) {
console.error(error);
}
}, [key, storedValue]);
return [storedValue, setStoredValue];
}
// Usage in multiple components
function ThemeToggle() {
const [theme, setTheme] = useLocalStorage('theme', 'light');
return (
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
Current: {theme}
</button>
);
}
function FontSizeSelector() {
const [fontSize, setFontSize] = useLocalStorage('fontSize', 16);
return (
<input
type="range"
value={fontSize}
onChange={(e) => setFontSize(Number(e.target.value))}
/>
);
}
Both components use useLocalStorage, but each has its own independent state that persists to localStorage.
54 What is the useDebugValue hook? Medium
The useDebugValue hook is used to display a label for custom hooks in React DevTools. It helps developers debug custom hooks by showing meaningful information.
#### Syntax
useDebugValue(value);
useDebugValue(value, formatFn); // With optional formatter
#### Example: Custom Hook with Debug Value
import { useState, useEffect, useDebugValue } from 'react';
function useOnlineStatus() {
const [isOnline, setIsOnline] = useState(true);
useEffect(() => {
const handleOnline = () => setIsOnline(true);
const handleOffline = () => setIsOnline(false);
window.addEventListener('online', handleOnline);
window.addEventListener('offline', handleOffline);
return () => {
window.removeEventListener('online', handleOnline);
window.removeEventListener('offline', handleOffline);
};
}, []);
// Shows "OnlineStatus: Online" or "OnlineStatus: Offline" in DevTools
useDebugValue(isOnline ? 'Online' : 'Offline');
return isOnline;
}
#### With Formatting Function (for expensive computations)
function useUser(userId) {
const [user, setUser] = useState(null);
// The format function only runs when DevTools is open
useDebugValue(user, (user) => user ? `User: ${user.name}` : 'Loading...');
return user;
}
Note: Only use useDebugValue in custom hooks that are part of shared libraries. It's not necessary for every custom hook in application code.
55 How do you handle cleanup in useEffect? Medium
The cleanup function in useEffect is used to clean up side effects before the component unmounts or before the effect runs again. This prevents memory leaks, stale data, and unexpected behavior.
#### Syntax
useEffect(() => {
// Setup code
return () => {
// Cleanup code
};
}, [dependencies]);
#### Common Cleanup Scenarios
1. Event Listeners
useEffect(() => {
const handleResize = () => setWidth(window.innerWidth);
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
2. Timers and Intervals
useEffect(() => {
const intervalId = setInterval(() => {
setCount(c => c + 1);
}, 1000);
return () => clearInterval(intervalId);
}, []);
3. Subscriptions
useEffect(() => {
const subscription = dataSource.subscribe(handleChange);
return () => subscription.unsubscribe();
}, [dataSource]);
4. Abort Fetch Requests
useEffect(() => {
const controller = new AbortController();
fetch(url, { signal: controller.signal })
.then(response => response.json())
.then(data => setData(data))
.catch(err => {
if (err.name !== 'AbortError') {
setError(err);
}
});
return () => controller.abort();
}, [url]);
When Cleanup Runs:
- Before the component unmounts
- Before re-running the effect when dependencies change
56 What are the differences between useEffect and useEvent (experimental)? Medium
useEvent is an experimental hook (not yet stable in React) designed to solve the problem of creating stable event handlers that always access the latest props and state without causing re-renders or needing to be in dependency arrays.
#### The Problem useEvent Solves
// Problem: onTick changes on every render, causing interval to reset
function Timer({ onTick }) {
useEffect(() => {
const id = setInterval(() => {
onTick(); // Uses stale closure if onTick is not in deps
}, 1000);
return () => clearInterval(id);
}, [onTick]); // Adding onTick causes interval to reset frequently
}
#### Solution with useEvent (Experimental)
import { useEvent } from 'react'; // Experimental
function Timer({ onTick }) {
const stableOnTick = useEvent(onTick);
useEffect(() => {
const id = setInterval(() => {
stableOnTick(); // Always calls latest onTick
}, 1000);
return () => clearInterval(id);
}, []); // No dependency needed!
}
#### Key Differences
| Feature | useEffect | useEvent (experimental) |
|---------|-----------|------------------------|
| Purpose | Run side effects | Create stable callbacks |
| Runs | After render | During render (creates function) |
| Returns | Cleanup function | Stable event handler |
| Closure | Captures values at render time | Always accesses latest values |
| Dependencies | Must list all used values | Not needed in other hooks' deps |
Note: Until useEvent is stable, you can use useCallback with useRef as a workaround for stable callbacks.
57 What are the best practices for using React Hooks? Medium
Following best practices ensures your hooks are predictable, maintainable, and bug-free.
#### 1. Follow the Rules of Hooks
- Only call hooks at the top level (not inside loops, conditions, or nested functions)
- Only call hooks from React functions (components or custom hooks)
#### 2. Use the ESLint Plugin
npm install eslint-plugin-react-hooks --save-dev
{
"plugins": ["react-hooks"],
"rules": {
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn"
}
}
#### 3. Keep Hooks Focused and Simple
// ❌ Bad: One hook doing too much
function useEverything() {
const [user, setUser] = useState(null);
const [posts, setPosts] = useState([]);
const [theme, setTheme] = useState('light');
// ... lots of unrelated logic
}
// ✅ Good: Separate concerns
function useUser() { /* user logic */ }
function usePosts() { /* posts logic */ }
function useTheme() { /* theme logic */ }
#### 4. Use Descriptive Names for Custom Hooks
// ❌ Bad
function useData() { }
// ✅ Good
function useUserAuthentication() { }
function useFetchProducts() { }
function useFormValidation() { }
#### 5. Properly Manage Dependencies
// ❌ Bad: Missing dependency
useEffect(() => {
fetchUser(userId);
}, []); // userId is missing
// ✅ Good: All dependencies listed
useEffect(() => {
fetchUser(userId);
}, [userId]);
#### 6. Avoid Inline Object/Function Dependencies
// ❌ Bad: New object on every render
useEffect(() => {
doSomething(options);
}, [{ page: 1, limit: 10 }]); // Always different reference
// ✅ Good: Memoize or extract
const options = useMemo(() => ({ page: 1, limit: 10 }), []);
useEffect(() => {
doSomething(options);
}, [options]);
#### 7. Clean Up Side Effects
Always return a cleanup function when subscribing to events, timers, or external data sources.
## Modern React Features (React 18/19)
58 What is the use() hook in React 19? Medium
The use() hook allows you to read the value of a resource (Promise or Context) during render, with Suspense integration.
#### Reading Promises
import { use, Suspense } from 'react';
function UserProfile({ userPromise }) {
const user = use(userPromise); // Suspends until resolved
return (
<div>
<h1>{user.name}</h1>
<p>{user.email}</p>
</div>
);
}
function App() {
const userPromise = fetchUser(123);
return (
<Suspense fallback={<div>Loading...</div>}>
<UserProfile userPromise={userPromise} />
</Suspense>
);
}
#### Reading Context
import { use } from 'react';
import { ThemeContext } from './context';
function Button() {
const theme = use(ThemeContext);
return <button className={theme}>Click me</button>;
}
#### Key Differences from Other Hooks
| Feature | use() | useContext() | useState() |
|---------|-------|--------------|------------|
| Can be called conditionally | ✅ Yes | ❌ No | ❌ No |
| Can be called in loops | ✅ Yes | ❌ No | ❌ No |
| Suspends for Promises | ✅ Yes | ❌ N/A | ❌ N/A |
| Reads Context | ✅ Yes | ✅ Yes | ❌ N/A |
#### Conditional Usage (Unique!)
function Component({ showUser, userPromise }) {
// ✅ This is allowed with use()!
const user = showUser ? use(userPromise) : null;
return user ? <div>{user.name}</div> : <div>No user</div>;
}
59 What are useFormState and useFormStatus hooks? Medium
These hooks simplify form handling with Server Actions in React 19.
#### useFormState
Manages form state and handles server responses:
'use client'
import { useFormState } from 'react-dom';
import { loginAction } from './actions';
export default function LoginForm() {
const [state, formAction] = useFormState(loginAction, {
errors: {},
message: ''
});
return (
<form action={formAction}>
<input name="email" type="email" />
{state.errors.email && <p>{state.errors.email}</p>}
<input name="password" type="password" />
{state.errors.password && <p>{state.errors.password}</p>}
<button type="submit">Login</button>
{state.message && <p>{state.message}</p>}
</form>
);
}
#### useFormStatus
Get the pending state of parent form:
'use client'
import { useFormStatus } from 'react-dom';
function SubmitButton() {
const { pending, data, method, action } = useFormStatus();
return (
<button type="submit" disabled={pending}>
{pending ? 'Submitting...' : 'Submit'}
</button>
);
}
// Must be used in a child component of <form>
export default function MyForm() {
return (
<form action={serverAction}>
<input name="email" />
<SubmitButton />
</form>
);
}
#### Combining Both
'use client'
import { useFormState, useFormStatus } from 'react-dom';
function SubmitButton() {
const { pending } = useFormStatus();
return (
<button disabled={pending}>
{pending ? '⏳ Saving...' : '💾 Save'}
</button>
);
}
export default function EditProfile() {
const [state, formAction] = useFormState(updateProfile, null);
return (
<form action={formAction}>
<input name="name" defaultValue={user.name} />
<input name="bio" defaultValue={user.bio} />
<SubmitButton />
{state?.success && <p>✅ Profile updated!</p>}
{state?.error && <p>❌ {state.error}</p>}
</form>
);
}
#### Key Points
useFormState: For managing server responses and errorsuseFormStatus: For UI feedback during submissionuseFormStatusmust be used in a child component of the form- Works seamlessly with Server Actions
60 What is the useOptimistic hook? Medium
useOptimistic enables optimistic UI updates - showing changes immediately before server confirmation.
#### Basic Usage
import { useOptimistic } from 'react';
function TodoList({ todos, addTodo }) {
const [optimisticTodos, addOptimisticTodo] = useOptimistic(
todos,
(currentTodos, newTodo) => [...currentTodos, { ...newTodo, pending: true }]
);
async function handleSubmit(formData) {
const title = formData.get('title');
// Immediately show optimistic update
addOptimisticTodo({ id: Date.now(), title });
// Send to server
await addTodo(title);
// Component re-renders with real data when complete
}
return (
<>
<form action={handleSubmit}>
<input name="title" />
<button>Add</button>
</form>
<ul>
{optimisticTodos.map(todo => (
<li key={todo.id} style={{ opacity: todo.pending ? 0.5 : 1 }}>
{todo.title}
{todo.pending && ' ⏳'}
</li>
))}
</ul>
</>
);
}
#### With Server Actions
'use client'
import { useOptimistic } from 'react';
import { likePost } from './actions';
export default function Post({ post, likes }) {
const [optimisticLikes, addOptimisticLike] = useOptimistic(
likes,
(currentLikes, amount) => currentLikes + amount
);
async function handleLike() {
addOptimisticLike(1); // Immediate UI update
await likePost(post.id); // Server update
}
return (
<div>
<h2>{post.title}</h2>
<button onClick={handleLike}>
❤️ {optimisticLikes} Likes
</button>
</div>
);
}
#### Complex Example with Error Handling
function ShoppingCart({ items, removeItem }) {
const [optimisticItems, removeOptimistic] = useOptimistic(
items,
(current, removedId) => current.filter(item => item.id !== removedId)
);
async function handleRemove(itemId) {
removeOptimistic(itemId); // Immediate removal from UI
try {
await removeItem(itemId);
} catch (error) {
// Automatic rollback on error!
toast.error('Failed to remove item');
}
}
return (
<ul>
{optimisticItems.map(item => (
<li key={item.id}>
{item.name}
<button onClick={() => handleRemove(item.id)}>Remove</button>
</li>
))}
</ul>
);
}
#### When to Use
- ✅ Toggling likes/favorites
- ✅ Adding/removing items from lists
- ✅ Sending messages in chat
- ✅ Any action where immediate feedback improves UX
- ❌ Financial transactions (wait for confirmation)
- ❌ Critical operations requiring server validation
61 What is the difference between HOCs and Hooks? Medium
Both Higher-Order Components (HOCs) and Hooks let you reuse logic across components, but they solve that problem in very different ways.
| Aspect | Higher-Order Components (HOCs) | Hooks |
| --- | --- | --- |
| Pattern | A function that takes a component and returns a new, enhanced component | A function called directly inside a function component |
| Component tree | Adds an extra wrapper component, which can lead to "wrapper hell" with multiple HOCs | Adds no extra components to the tree |
| Sharing logic | Injects props/behavior into the wrapped component | Shares stateful logic directly via custom hooks (useX) |
| Prop handling | Can cause prop name collisions when composing multiple HOCs | No prop collisions since state lives inside the component itself |
| Debugging | Harder to trace which HOC injected which prop (often needs displayName) | Easier to trace; shows up as plain hook calls in React DevTools |
| Usage | Works with both class and function components | Can only be used in function components (or other hooks) |
#### Example: sharing "toggle" logic
Using a HOC:
function withToggle(WrappedComponent) {
return function Enhanced(props) {
const [on, setOn] = useState(false);
const toggle = () => setOn((prev) => !prev);
return <WrappedComponent {...props} on={on} toggle={toggle} />;
};
}
const Modal = withToggle(BaseModal);
Using a custom Hook:
function useToggle(initial = false) {
const [on, setOn] = useState(initial);
const toggle = () => setOn((prev) => !prev);
return [on, toggle];
}
function Modal() {
const [on, toggle] = useToggle();
// ...
}
In short, Hooks were introduced to solve the same logic-reuse problem as HOCs (and render props), but without adding extra components to the render tree—avoiding wrapper hell and making the code easier to read, type, and debug. See also [Do Hooks replace render props and higher-order components?](#do-hooks-replace-render-props-and-higher-order-components).
62 Does `React.memo` prevent Context consumers from re-rendering? Medium
No. React.memo only performs a shallow comparison of a component's props — it has no visibility into context. If a component reads a value via useContext/Context.Consumer, that component re-renders whenever the context value changes, regardless of whether it's wrapped in React.memo and regardless of whether its own props changed.
const CountContext = React.createContext();
// Wrapping with React.memo does NOT help here
const Display = React.memo(function Display() {
const count = useContext(CountContext);
return <div>{count}</div>;
});
function App() {
const [count, setCount] = useState(0);
return (
<CountContext.Provider value={count}>
<button onClick={() => setCount((c) => c + 1)}>Increment</button>
<Display />
</CountContext.Provider>
);
}
Every time count changes, Display re-renders even though it takes no props and is memoized — React.memo bails out based on prop equality, but context consumption bypasses that check entirely.
#### How to actually reduce these re-renders
- Split contexts by concern so a component only subscribes to the slice of state it actually needs (see [What's a common pitfall when using useContext with objects?](#whats-a-common-pitfall-when-using-usecontext-with-objects)).
- Memoize the provider's value with
useMemoso the reference only changes when the underlying data changes — this reduces churn but doesn't stop consumers from re-rendering when the value itself legitimately changes. - Push
useContextdown into a small wrapper component and pass the extracted value as a prop to a memoized child. The child (wrapped inReact.memo) will now correctly skip re-rendering when that specific prop hasn't changed, since the memoization check happens one level below the context read. - Use a state management library or selector-based API (Redux's
useSelector, Zustand, Jotai) when you need fine-grained, per-field subscriptions instead of one large context object.
63 How would you create a reusable Context? Medium
A reusable Context bundles the createContext call, its Provider (with local state/logic), and a custom hook to consume it into a single module. This hides the raw Context object from consumers, provides a clear API, and lets you validate that the hook is used within its provider.
// ThemeContext.js
import { createContext, useContext, useMemo, useState } from "react";
const ThemeContext = createContext(undefined);
export function ThemeProvider({ children }) {
const [theme, setTheme] = useState("light");
const toggleTheme = () =>
setTheme((prev) => (prev === "light" ? "dark" : "light"));
// Memoize so the value reference is stable across renders
const value = useMemo(() => ({ theme, toggleTheme }), [theme]);
return (
<ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>
);
}
// Custom hook consumers use instead of importing ThemeContext directly
export function useTheme() {
const context = useContext(ThemeContext);
if (context === undefined) {
throw new Error("useTheme must be used within a ThemeProvider");
}
return context;
}
// App.js
function App() {
return (
<ThemeProvider>
<Toolbar />
</ThemeProvider>
);
}
function Toolbar() {
const { theme, toggleTheme } = useTheme();
return <button onClick={toggleTheme}>Current theme: {theme}</button>;
}
#### Why wrap Context like this?
- Encapsulation: Consumers never import or touch the raw
Contextobject, so its internal shape can change without breaking callers. - Guardrails: The custom hook throws a clear error if used outside its provider, instead of silently returning
undefined. - Colocation: State, updater functions, and derived values live next to the provider, making the context self-contained and easy to test in isolation.
- Composability: Multiple reusable contexts (theme, auth, locale, etc.) can be combined by nesting providers, or composed with a helper that merges them.
- Performance-friendly: Memoizing the provider's value (with
useMemo) avoids creating a new object on every render, reducing unnecessary consumer re-renders (see [DoesReact.memoprevent Context consumers from re-rendering?](#does-reactmemo-prevent-context-consumers-from-re-rendering)).
64 What are the different phases of component lifecycle? Medium
The component lifecycle has three distinct lifecycle phases:
- Mounting: The component is ready to mount in the browser DOM. This phase covers initialization from
constructor(),getDerivedStateFromProps(),render(), andcomponentDidMount()lifecycle methods.
- Updating: In this phase, the component gets updated in two ways, sending the new props and updating the state either from
setState()orforceUpdate(). This phase coversgetDerivedStateFromProps(),shouldComponentUpdate(),render(),getSnapshotBeforeUpdate()andcomponentDidUpdate()lifecycle methods.
- Unmounting: In this last phase, the component is not needed and gets unmounted from the browser DOM. This phase includes
componentWillUnmount()lifecycle method.
It's worth mentioning that React internally has a concept of phases when applying changes to the DOM. They are separated as follows
- Render The component will render without any side effects. This applies to Pure components and in this phase, React can pause, abort, or restart the render.
- Pre-commit Before the component actually applies the changes to the DOM, there is a moment that allows React to read from the DOM through the
getSnapshotBeforeUpdate().
- Commit React works with the DOM and executes the final lifecycles respectively
componentDidMount()for mounting,componentDidUpdate()for updating, andcomponentWillUnmount()for unmounting.
React 16.3+ Phases (or an interactive version)

Before React 16.3

65 What are the lifecycle methods of React? Medium
Before React 16.3
- componentWillMount: Executed before rendering and is used for App level configuration in your root component.
- componentDidMount: Executed after first rendering and here all AJAX requests, DOM or state updates, and set up event listeners should occur.
- componentWillReceiveProps: Executed when particular prop updates to trigger state transitions.
- shouldComponentUpdate: Determines if the component will be updated or not. By default it returns
true. If you are sure that the component doesn't need to render after state or props are updated, you can return false value. It is a great place to improve performance as it allows you to prevent a re-render if component receives new prop. - componentWillUpdate: Executed before re-rendering the component when there are props & state changes confirmed by
shouldComponentUpdate()which returns true. - componentDidUpdate: Mostly it is used to update the DOM in response to prop or state changes.
- componentWillUnmount: It will be used to cancel any outgoing network requests, or remove all event listeners associated with the component.
React 16.3+
- getDerivedStateFromProps: Invoked right before calling
render()and is invoked on _every_ render. This exists for rare use cases where you need a derived state. Worth reading if you need derived state. - componentDidMount: Executed after first rendering and where all AJAX requests, DOM or state updates, and set up event listeners should occur.
- shouldComponentUpdate: Determines if the component will be updated or not. By default, it returns
true. If you are sure that the component doesn't need to render after the state or props are updated, you can return a false value. It is a great place to improve performance as it allows you to prevent a re-render if component receives a new prop. - getSnapshotBeforeUpdate: Executed right before rendered output is committed to the DOM. Any value returned by this will be passed into
componentDidUpdate(). This is useful to capture information from the DOM i.e. scroll position. - componentDidUpdate: Mostly it is used to update the DOM in response to prop or state changes. This will not fire if
shouldComponentUpdate()returnsfalse. - componentWillUnmount It will be used to cancel any outgoing network requests, or remove all event listeners associated with the component.
> Modern React Note: componentWillMount, componentWillReceiveProps, and componentWillUpdate are legacy lifecycles deprecated since React 16.3 and removed in modern React. In modern functional React, use the useEffect Hook or derive state values directly during render.
66 What is context? Medium
_Context_ provides a way to pass data through the component tree without having to pass props down manually at every level.
For example, authenticated users, locale preferences, UI themes need to be accessed in the application by many components.
const { Provider, Consumer } = React.createContext(defaultValue);
67 What is the lifecycle methods order in mounting? Medium
The lifecycle methods are called in the following order when an instance of a component is being created and inserted into the DOM.
constructor()static getDerivedStateFromProps()render()componentDidMount()
68 What are the lifecycle methods going to be deprecated in React v16? Medium
⚠️ FULLY DEPRECATED: These lifecycle methods have been deprecated and removed from React 17+.
The following lifecycle methods were deprecated due to unsafe coding practices and problems with async rendering:
componentWillMount()- REMOVED in React 17componentWillReceiveProps()- REMOVED in React 17componentWillUpdate()- REMOVED in React 17
Timeline:
- React 16.3: Methods aliased with
UNSAFE_prefix - React 17+: Unprefixed versions completely removed
- Current (React 18/19): Only
UNSAFE_versions exist (not recommended)
Modern Alternatives:
| Deprecated Method | Modern Replacement |
|---|---|
| componentWillMount() | constructor() or componentDidMount() |
| componentWillReceiveProps() | static getDerivedStateFromProps() or componentDidUpdate() |
| componentWillUpdate() | getSnapshotBeforeUpdate() + componentDidUpdate() |
Best Practice: Use functional components with hooks instead:
useEffect()for side effectsuseState()for state managementuseMemo()/useCallback()for optimization
69 What is the purpose of `getDerivedStateFromProps()` lifecycle method? Medium
The new static getDerivedStateFromProps() lifecycle method is invoked after a component is instantiated as well as before it is re-rendered. It can return an object to update state, or null to indicate that the new props do not require any state updates.
class MyComponent extends React.Component {
static getDerivedStateFromProps(props, state) {
// ...
}
}
This lifecycle method along with componentDidUpdate() covers all the use cases of componentWillReceiveProps().
> Modern React Note: componentWillMount, componentWillReceiveProps, and componentWillUpdate are legacy lifecycles deprecated since React 16.3 and removed in modern React. In modern functional React, use the useEffect Hook or derive state values directly during render.
70 What is the purpose of `getSnapshotBeforeUpdate()` lifecycle method? Medium
The new getSnapshotBeforeUpdate() lifecycle method is called right before DOM updates. The return value from this method will be passed as the third parameter to componentDidUpdate().
class MyComponent extends React.Component {
getSnapshotBeforeUpdate(prevProps, prevState) {
// ...
}
}
This lifecycle method along with componentDidUpdate() covers all the use cases of componentWillUpdate().
> Modern React Note: componentWillMount, componentWillReceiveProps, and componentWillUpdate are legacy lifecycles deprecated since React 16.3 and removed in modern React. In modern functional React, use the useEffect Hook or derive state values directly during render.
71 How to make AJAX call and in which component lifecycle methods should I make an AJAX call? Medium
You can use AJAX libraries such as Axios, jQuery AJAX, and the browser built-in fetch. You should fetch data in the componentDidMount() lifecycle method. This is so you can use setState() to update your component when the data is retrieved.
For example, the employees list fetched from API and set local state:
```jsx harmony
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
employees: [],
error: null,
};
}
componentDidMount() {
fetch("https://api.example.com/items")
.then((res) => res.json())
.then(
(result) => {
this.setState({
employees: result.employees,
});
},
(error) => {
this.setState({ error });
}
);
}
render() {
const { error, employees } = this.state;
if (error) {
return <div>Error: {error.message}</div>;
} else {
return (
<ul>
{employees.map((employee) => (
<li key={employee.name}>
{employee.name}-{employee.experience}
</li>
))}
</ul>
);
}
}
}
```
72 How to debug forwardRefs in DevTools? Medium
React.forwardRef accepts a render function as parameter and DevTools uses this function to determine what to display for the ref forwarding component.
For example, If you don't name the render function or not using displayName property then it will appear as ”ForwardRef” in the DevTools,
const WrappedComponent = React.forwardRef((props, ref) => {
return <LogProps {...props} forwardedRef={ref} />;
});
But If you name the render function then it will appear as ”ForwardRef(myFunction)”
const WrappedComponent = React.forwardRef(function myFunction(props, ref) {
return <LogProps {...props} forwardedRef={ref} />;
});
As an alternative, You can also set displayName property for forwardRef function,
function logProps(Component) {
class LogProps extends React.Component {
// ...
}
function forwardRef(props, ref) {
return <LogProps {...props} forwardedRef={ref} />;
}
// Give this component a more helpful display name in DevTools.
// e.g. "ForwardRef(logProps(MyComponent))"
const name = Component.displayName || Component.name;
forwardRef.displayName = `logProps(${name})`;
return React.forwardRef(forwardRef);
}
73 Give an example on How to use context? Medium
Context is designed to share data that can be considered global for a tree of React components.
For example, in the code below lets manually thread through a “theme” prop in order to style the Button component.
//Lets create a context with a default theme value "luna"
const ThemeContext = React.createContext("luna");
// Create App component where it uses provider to pass theme value in the tree
class App extends React.Component {
render() {
return (
<ThemeContext.Provider value="nova">
<Toolbar />
</ThemeContext.Provider>
);
}
}
// A middle component where you don't need to pass theme prop anymore
function Toolbar(props) {
return (
<div>
<ThemedButton />
</div>
);
}
// Lets read theme value in the button component to use
class ThemedButton extends React.Component {
static contextType = ThemeContext;
render() {
return <Button theme={this.context} />;
}
}
74 How do you use contextType? Medium
ContextType is used to consume the context object. The contextType property can be used in two ways,
- contextType as property of class:
The contextType property on a class can be assigned a Context object created by React.createContext(). After that, you can consume the nearest current value of that Context type using this.context in any of the lifecycle methods and render function.
Lets assign contextType property on MyClass as below,
class MyClass extends React.Component {
componentDidMount() {
let value = this.context;
/* perform a side-effect at mount using the value of MyContext */
}
componentDidUpdate() {
let value = this.context;
/* ... */
}
componentWillUnmount() {
let value = this.context;
/* ... */
}
render() {
let value = this.context;
/* render something based on the value of MyContext */
}
}
MyClass.contextType = MyContext;
- Static field
You can use a static class field to initialize your contextType using public class field syntax.
class MyClass extends React.Component {
static contextType = MyContext;
render() {
let value = this.context;
/* render something based on the value */
}
}
75 How do you solve performance corner cases while using context? Medium
The context uses reference identity to determine when to re-render, there are some gotchas that could trigger unintentional renders in consumers when a provider’s parent re-renders.
For example, the code below will re-render all consumers every time the Provider re-renders because a new object is always created for value.
class App extends React.Component {
render() {
return (
<Provider value={{ something: "something" }}>
<Toolbar />
</Provider>
);
}
}
This can be solved by lifting up the value to parent state,
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
value: { something: "something" },
};
}
render() {
return (
<Provider value={this.state.value}>
<Toolbar />
</Provider>
);
}
}
All 75 questions loaded
Frequently Asked Questions About React Interviews
What do hiring managers evaluate in React technical rounds?
Technical interviewers look for foundational fluency, idiomatic syntax, clarity when communicating complex logic, and awareness of performance trade-offs (e.g. memory footprint, render performance, and network latency) in production environments.
What are the best interview tips for practicing React questions?
Use active recall: summarize each answer in your own words before revealing the model solution. Focus on explaining why a certain approach is chosen rather than just memorizing code syntax.