Top ReactJS Interview Questions for Developers
Try Aihirely for
Smarter Interview Prep
Experience real-time AI support tailored to your Resume.
Boost your confidence and ace every question with
AI Mock Interview.
Question: What are higher-order components (HOCs) in React?
Answer:
A Higher-Order Component (HOC) is a function in React that takes a component and returns a new component with additional functionality. HOCs are a pattern used for reusing component logic. They don’t modify the original component directly; instead, they enhance the component by adding extra behavior or props.
Key Characteristics of HOCs:
- Pure Functions: HOCs are pure functions, meaning they do not modify the original component but return a new component with enhanced behavior.
- Reusable Logic: HOCs allow you to abstract out reusable logic and apply it to multiple components without duplicating code.
- Props Management: They can modify or inject props into the wrapped component, enabling you to enhance or control its behavior.
Syntax:
const EnhancedComponent = higherOrderComponent(WrappedComponent);
Common Use Cases for HOCs:
- Conditional Rendering: Add logic to display a loading indicator, error boundary, or authentication check.
- Code Splitting: Dynamically load components only when needed.
- State Management: Share state or business logic across multiple components without duplicating code.
- Props Manipulation: Modify or inject props into the wrapped component.
Example of a Higher-Order Component:
Let’s say we want to create a HOC that adds a loading state to a component, displaying a loading spinner until data is fetched.
import React, { useState, useEffect } from 'react';
// HOC that adds loading functionality
const withLoading = (WrappedComponent) => {
return (props) => {
const [loading, setLoading] = useState(true);
useEffect(() => {
// Simulate a data fetching
setTimeout(() => setLoading(false), 2000);
}, []);
if (loading) {
return <div>Loading...</div>;
}
// If not loading, render the wrapped component
return <WrappedComponent {...props} />;
};
};
// A simple component
const UserList = () => {
return <div>User List Content</div>;
};
// Wrap the UserList component with the loading HOC
const UserListWithLoading = withLoading(UserList);
// Usage in the app
const App = () => {
return (
<div>
<h1>My App</h1>
<UserListWithLoading />
</div>
);
};
export default App;
How HOCs Work:
- The
withLoadingHOC takes theUserListcomponent as an argument. - It returns a new component that has additional behavior (showing a loading indicator until the state changes).
- When the component is rendered, it checks the
loadingstate, and if the state istrue, it shows the “Loading…” text. Once the data is “fetched” (simulated bysetTimeout), it renders the originalUserListcomponent.
Benefits of HOCs:
- Code Reusability: HOCs enable the reuse of logic that can be applied to multiple components.
- Separation of Concerns: By using HOCs, you can separate concerns like authentication, state management, and lifecycle management from the component’s presentation logic.
- Enhanced Readability: HOCs can make components more concise and easier to read by abstracting out logic into reusable functions.
Important Considerations:
- Don’t Mutate the Original Component: HOCs should never modify the original component directly. Instead, they return a new component with enhanced functionality.
- Props Handling: When creating a HOC, you must ensure that all props from the wrapped component are passed down correctly using
...props. - Naming Conventions: It’s common practice to give the HOC a name that reflects its functionality. For example,
withLoading,withAuth,withErrorBoundary.
Drawbacks of HOCs:
- Wrapper Hell: HOCs can result in deeply nested components, which may make the component tree harder to debug and understand (though React hooks can often help mitigate this).
- Static Methods and Ref Forwarding: If your component has static methods or refs, HOCs may need additional handling (e.g., using
forwardRefto pass refs down the component tree).
Conclusion:
Higher-Order Components are a powerful pattern in React for reusing logic across components. They allow developers to compose components with additional behavior, improving code maintainability and reducing duplication. However, with the advent of React hooks, some use cases for HOCs are being replaced by more flexible and cleaner solutions.
Question: What are React Hooks?
Answer:
React Hooks are functions that allow you to use state and other React features in functional components, which were previously only available in class components. They were introduced in React 16.8 to provide a simpler, more readable way to manage state, side effects, context, refs, and other React features in functional components.
Before Hooks, managing state and lifecycle methods required class components. With Hooks, you can now use all of these features in functional components without needing to write classes.
Commonly Used React Hooks:
-
useState: The
useStatehook is used to add state to functional components. It returns an array with two elements: the current state value and a function to update it.import React, { useState } from 'react'; const Counter = () => { const [count, setCount] = useState(0); // Initial state is 0 return ( <div> <p>Count: {count}</p> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); };useState(0)initializes the state with a value of0.setCountis the function used to update the state.
-
useEffect: The
useEffecthook is used to perform side effects in function components, such as data fetching, subscriptions, or manually updating the DOM. It replaces lifecycle methods likecomponentDidMount,componentDidUpdate, andcomponentWillUnmountin class components.import React, { useState, useEffect } from 'react'; const DataFetcher = () => { const [data, setData] = useState(null); useEffect(() => { fetch('https://api.example.com/data') .then(response => response.json()) .then(data => setData(data)); }, []); // The empty array means this effect runs once, similar to componentDidMount return ( <div> {data ? <p>{data}</p> : <p>Loading...</p>} </div> ); };- The
useEffecthook runs after the component renders. - The second argument (
[]) is a dependency array. If empty, the effect runs once after the initial render, simulatingcomponentDidMount.
- The
-
useContext: The
useContexthook allows you to subscribe to a context value without needing to use aContext.Consumer. It provides a simpler way to manage global state.import React, { useContext } from 'react'; const ThemeContext = React.createContext('light'); const ThemedComponent = () => { const theme = useContext(ThemeContext); return ( <div> <p>The current theme is: {theme}</p> </div> ); };useContext(ThemeContext)allows you to access the value provided byThemeContext.Provider.
-
useRef: The
useRefhook is used to create mutable object references that persist across re-renders. It is commonly used to access DOM elements directly, similar toReact.createRef()in class components.import React, { useRef } from 'react'; const InputFocus = () => { const inputRef = useRef(null); const focusInput = () => { inputRef.current.focus(); }; return ( <div> <input ref={inputRef} type="text" /> <button onClick={focusInput}>Focus the input</button> </div> ); };useRefreturns a mutablerefobject. Thecurrentproperty is used to store a reference to the DOM element.
-
useReducer: The
useReducerhook is an alternative touseState, used for managing more complex state logic. It is similar to how Redux works, using a reducer function to specify how the state should change based on actions.import React, { useReducer } from 'react'; const counterReducer = (state, action) => { switch (action.type) { case 'increment': return { count: state.count + 1 }; case 'decrement': return { count: state.count - 1 }; default: return state; } }; const Counter = () => { const [state, dispatch] = useReducer(counterReducer, { count: 0 }); return ( <div> <p>Count: {state.count}</p> <button onClick={() => dispatch({ type: 'increment' })}>Increment</button> <button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button> </div> ); };useReduceris useful for managing state with complex logic, such as when you need to handle multiple actions that affect the same piece of state.
-
useMemo: The
useMemohook memoizes the result of an expensive function call to prevent it from being recalculated on every render.import React, { useMemo } from 'react'; const ExpensiveComponent = ({ num }) => { const calculate = (n) => { console.log('Expensive calculation'); return n * 2; }; const result = useMemo(() => calculate(num), [num]); return <div>Result: {result}</div>; };useMemoensures that thecalculatefunction is only called whennumchanges, optimizing performance.
-
useCallback: The
useCallbackhook is used to memoize functions, ensuring that a function is not re-created on every render.import React, { useState, useCallback } from 'react'; const Button = ({ onClick }) => { console.log('Button rendered'); return <button onClick={onClick}>Click me</button>; }; const App = () => { const [count, setCount] = useState(0); const handleClick = useCallback(() => { setCount(count + 1); }, [count]); return ( <div> <p>Count: {count}</p> <Button onClick={handleClick} /> </div> ); };useCallbackmemoizes thehandleClickfunction to prevent unnecessary re-creations of the function on each render.
Benefits of React Hooks:
- Cleaner Code: Hooks provide a cleaner and more concise way to write React components without the need for classes.
- Reusability: Hooks allow you to reuse stateful logic between components without modifying the component hierarchy.
- Better Readability: Hooks help avoid the complexity of class-based components, making code more readable and easier to understand.
- Functional Components: You can now perform side effects, manage state, and interact with context in functional components, making them as powerful as class components.
Conclusion:
React Hooks revolutionized how we work with functional components by bringing state and lifecycle methods into them. They offer a more flexible, cleaner, and reusable approach for writing React components. By using hooks like useState, useEffect, useContext, and useReducer, developers can manage state, side effects, and context in a functional, declarative way without the need for classes.
Read More
If you can’t get enough from this article, Aihirely has plenty more related information, such as ReactJS interview questions, ReactJS interview experiences, and details about various ReactJS job positions. Click here to check it out.
