React Interview Questions 1743963763
React Interview Questions 1743963763
Answer: The key prop helps React identify which items have changed, been added, or removed,
enabling efficient re-rendering of lists.
Explanation: Keys should be unique among siblings (but don't need to be globally unique). Using indexes
as keys is discouraged if the list order may change.
Explanation: Props are for configuration, state is for interactivity. Changing props re-renders the child
component, changing state re-renders the current component.
function Input() {
const [value, setValue] = useState('');
Page 1 of 16
return <input value={value} onChange={(e) => setValue(e.target.value)}
}
Answer: It schedules an update to the component's state object and triggers a re-render.
Explanation: setState is asynchronous - multiple calls may be batched. You can pass a function to
access previous state: setState(prev => prev + 1) .
Answer: It lets you group elements without adding extra DOM nodes.
Explanation: Helpful when a component needs to return multiple adjacent elements. Short syntax:
<>...</> .
Page 2 of 16
Answer: By passing callback functions as props:
function Parent() {
const handleChildEvent = (data) => console.log(data);
return <Child onEvent={handleChildEvent} />;
}
Explanation: This can become cumbersome in deep component trees, solved by Context API or state
management libraries.
Example:
ReactDOM.createPortal(child, domNode)
Use case: Modals, tooltips that need to break out of container CSS.
Answer: useLayoutEffect fires synchronously after DOM mutations but before paint, while
useEffect fires asynchronously after render and paint.
Page 4 of 16
What is code splitting in React?
Answer: Splitting code into smaller bundles loaded on demand:
Implementation:
Page 5 of 16
a new "virtual DOM," which is a lightweight representation of the actual DOM. React then compares the
new virtual DOM with the previous version (this process is called "diffing") and calculates the minimal
number of changes required to update the real DOM. This ensures that React only makes necessary
updates, improving performance.
Key points:
Heuristic O(n) algorithm: React uses a heuristic approach with an O(n) time complexity to efficiently
update the DOM, even for large applications.
Element comparison and keys: React compares the element types (e.g., div vs. span) to check if they
have changed. For lists, React uses key attributes to uniquely identify list elements, which helps
optimize updates by reusing components if their keys haven't changed.
function usePrevious(value) {
const ref = useRef(); // Create a mutable reference
useEffect(() => {
ref.current = value; // Update the reference with the current value
}, [value]); // Run this effect whenever 'value' changes
return ref.current; // Return the previous value
}
This hook is useful when you need to compare the previous and current values of a prop or state, such
as when tracking changes in an input field or comparing the current and previous states.
Page 6 of 16
<Toggle>
<Toggle.On>The button is on</Toggle.On>
<Toggle.Off>The button is off</Toggle.Off>
<Toggle.Button />
</Toggle>
In this example:
Toggle is the parent component, and it holds the shared state (whether the button is on or off).
Toggle.On, Toggle.Off, and Toggle.Button are children that are implicitly aware of the parent
component’s state. The parent manages the state and passes it down to the children components
without the need for props.
This pattern makes it easy to create components like toggles, modals, or tabs that have interconnected
behavior.
In this hook:
1. The debouncedValue state is updated after the value has stopped changing for a specified delay.
2. This is useful for preventing unnecessary function calls, especially in situations like form input
fields, where you don't want to trigger an API call every time the user types.
What is the Context API and when should you use it?
Page 7 of 16
Answer: The Context API is a feature in React that allows you to share data (such as theme settings,
authentication, or language preference) across components without having to manually pass down
props at every level. It is particularly useful when you need to share state across many components at
different levels of the component tree.
function Child() {
const theme = useContext(ThemeContext);
return <div>{theme}</div>;
}
In this example:
1. ThemeContext is created with createContext(), and the value is provided at the top level of the app
using ThemeContext.Provider.
2. Any child component can access the shared theme value using useContext(ThemeContext).
3. Context is useful for state that needs to be accessed by many components, like user
authentication status or theme preferences.
1. Time slicing: Divides rendering work into small chunks to allow the browser to do other tasks,
ensuring that the app remains responsive.
Page 8 of 16
2. Suspense: Helps to manage asynchronous rendering by "suspending" parts of the app while
waiting for data (e.g., loading a component or fetching data).
3. Transition updates: Lets you mark certain updates as less urgent, so React can prioritize
important ones, like user interactions.
Here:
1. The List component only renders items that fit in the height of the list container.
Jest: A JavaScript test runner used to run tests and assert conditions.
React Testing Library: A library that helps you test components by rendering them in a way that
simulates how users interact with them (via the DOM).
Mocking: You can use jest.mock to mock dependencies and isolate components for testing.
Page 9 of 16
test('renders the correct text', () => {
render(<MyComponent />);
expect(screen.getByText('Hello World')).toBeInTheDocument();
});
Server Components:
1. Rendered entirely on the server, meaning they don't contribute to the JavaScript bundle size.
2. Can access backend resources directly and fetch data without affecting the client-side bundle.
3. Support progressive enhancement, where only certain parts of the page are enhanced on the
client-side after initial load.
4. Complement SSR, allowing for better server-side integration without overloading the client-side
bundle.
SSR:
1. Renders the entire component on the server and sends HTML to the client, often requiring a full
page reload or hydration of the client-side application.
2. Server Components are more lightweight and efficient in certain scenarios, as they avoid sending
unnecessary JavaScript to the client.
function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log(count);
}, [count]);
Page 10 of 16
return <button onClick={() => setCount(c => c + 1)}>Click</button>;
}
function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log(count);
}, [count]);
return <button onClick={() => setCount(c => c + 1)}>Click</button>;
}
Explanation:
The useEffect hook is triggered on mount (initial render) and on every update to the count state. When
the component mounts, count is 0, and the effect logs it. After each button click, the setCount function
updates the count, and the effect logs the updated value. The update is asynchronous, so the effect will
log the updated value after each render.
function MyComponent() {
console.log('render');
return <div>Hello</div>;
}
Explanation:
The component simply logs "render" to the console each time it renders. Since there are no state
updates or props changing in this component, it will only log the message once during the initial render.
Page 11 of 16
If the parent component re-renders, this component will also re-render, and "render" will be logged
again.
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
const id = setInterval(() => {
setCount(count + 1);
}, 1000);
return () => clearInterval(id);
}, []);
return <div>{count}</div>;
}
Explanation:
The useEffect hook sets up an interval that increments the count every second. However, the setCount
function uses the count value from the initial render (due to a stale closure). This means it will only
increment to 1 and stop. The fix is to use the functional update form of setCount, which will always
receive the latest value of count.
Explanation:
When the component first mounts, the render method is called, followed by componentDidMount. After
Page 12 of 16
any subsequent updates to the component, the render method will be called again, followed by
componentDidUpdate. The order of the logs is determined by the lifecycle methods in React.
Explanation:
React's useContext hook allows a component to consume values provided by a Context.Provider. In this
case, the nearest Context.Provider around the Child component provides the value "B", so that is what
gets rendered. Even though there is another Context.Provider higher up the tree with the value "A", the
nearest Provider takes precedence.
function App() {
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(count + 1);
setCount(count + 1);
};
return <button onClick={handleClick}>{count}</button>;
}
Page 13 of 16
Output: Count increments by 1 (state updates are batched).
Explanation:
In React, state updates within the same event handler are batched together for performance. So, both
setCount(count + 1) calls are executed together, but React uses the initial count value for both calls. As a
result, the state is updated only once, and the displayed count is incremented by 1 instead of 2.
function useCounter(initial) {
const [count, setCount] = useState(initial);
const increment = useCallback(() => setCount(c => c + 1), []);
return [count, increment];
}
Explanation:
This custom hook returns the count and an increment function that can be used to increase the count.
The useCallback hook ensures that the increment function is stable and doesn't change unless its
dependencies (which are empty in this case) change. This prevents unnecessary re-renders of
components that use this hook.
Output: Renders list but with potential issues if items reorder (index keys).
Explanation:
The key prop in React helps optimize re-renders by uniquely identifying elements in a list. However,
Page 14 of 16
using the index (i) as the key can cause issues when the list is reordered because React might not
correctly associate items with their previous state. It is better to use a unique identifier as the key if
possible.
function EffectDemo() {
const [data, setData] = useState(null);
useEffect(() => {
async function fetchDataAsync() {
const result = await fetchData();
setData(result);
}
fetchDataAsync();
}, []);
return <div>{data}</div>;
}
Explanation:
React's useEffect callback cannot be an async function directly. This is because async functions return
a Promise, and React expects the callback to return either undefined or a cleanup function. The solution
is to define an async function inside the useEffect and call it, as shown in the fixed version.
function Example() {
const [value, setValue] = useState(0);
useEffect(() => {
if (value === 0) {
setValue(10);
}
}, [value]);
return <div>{value}</div>;
}
Page 15 of 16
Output: Initially 0 , then 10 (effect triggers state update).
Explanation:
The useEffect hook runs after every render, and it checks if value is 0. Initially, value is 0, so setValue(10)
is called, causing a re-render. On the second render, value is 10, and the effect no longer updates the
state since the condition value === 0 is not met.
Page 16 of 16