Table of Contents
- Introduction
- Basic Questions
- 1. What is React?
- 2. What are the main features of React?
- 3. What is JSX?
- 4. What is the difference between a Class component and a Functional component?
- 5. What is the virtual DOM?
- 6. What is the role of ReactDOM.render() in React?
- 7. What is a React component?
- 8. How do you create a component in React?
- 9. What is state in React?
- 10. What are props in React?
- 11. What is the difference between state and props?
- 12. What are the React lifecycle methods?
- 13. What is the purpose of super() in React?
- 14. What is the purpose of render() in React?
- 15. What is a Steady Component? Give a relevant code example.
- 16. What is an Uncontrolled Component?
- 17. What is the use of keys in React?
- 18. What is a higher order component?
- 19. What is a fragment in React?
- 20. What is Context API in React?
- 21. What are hooks in React?
- 22. What is the use of useEffect in React?
- 23. How to apply validation on props in React?
- 24. What is the use of React Router?
- 25. What are synthetic events in React?
- 26. How to conditionally render components in React?
- 27. What is ‘Lifting State Up’ in React?
- 28. How can you handle events in React?
- 29. What is the use of refs in React?
- 30. What are the limitations of React?
- Intermediate Questions
- 1. What is the React Context API and how is it used?
- 2. What are Pure Components in React?
- 3. What is a higher-order component (HOC)? Can you provide an example?
- 4. Explain the concept of “Lifting State Up” in React.
- 5. How do you handle forms in React?
- 6. How do you implement Error Boundaries in React for error handling?
- 7. Explain the use of arrow functions in React.
- 8. What is Redux and how is it related to React?
- 9. What is the significance of Store in Redux?
- 10. What is a reducer in Redux?
- 11. Explain how Redux Thunk works.
- 12. How would you handle asynchronous actions in Redux?
- 13. What are the middleware functions in Redux?
- 14. How do you make use of the ‘connect’ function in Redux?
- 15. What is the purpose of ‘mapStateToProps’ and ‘mapDispatchToProps’ in Redux?
- 16. How do you implement routing in React?
- 17. What is the difference between ‘react-router’ and ‘react-router-dom’?
- 18. What is a render prop?
- 19. What is a controlled component in React?
- 20. What are hooks in React?
- 21. Explain the use of the useEffect hook in React.
- 22. What is the useState hook in React?
- 23. What are React PropTypes and how do you use them?
- 24. What are Synthetic Events in React?
- 25. Explain the lifecycle methods in React Components.
- 26. How do you implement server-side rendering or isomorphic rendering in React?
- 27. What is the significance of keys in React lists?
- 28. Explain how to do code-splitting in React.
- 29. What are the benefits of using React.memo()?
- 30. How can you optimize a React application’s performance?
- Advanced Questions
- 1. What is reconciliation in React?
- 2. What is the Flux architecture? How is it different from Redux?
- 3. Can you explain the concept of “Immutable State”?
- 4. What is the significance of the shouldComponentUpdate lifecycle method in React?
- 5. How does React handle or prevent XSS attacks?
- 6. How would you handle side effects on component unmount?
- 7. What are React Portals, and where can they be used?
- 8. What are Suspense and lazy functions in React?
- 9. How does Error Boundary handle errors in the whole application or part of the application?
- 10. How do you handle an API request error in React?
- 11. Explain how to use React.forwardRef.
- 12. What is Concurrent Mode in React?
- 13. What are the rules for Hooks usage in React?
- 14. What are custom hooks? Provide an example.
- 15. Explain how to use the useReducer hook.
- 16. What is the purpose of the useCallback hook?
- 17. What is the purpose of the useMemo hook?
- 18. Explain how you would implement a dark mode in React.
- 19. How do you optimize large lists in React?
- 20. What are your strategies for managing complex state interactions?
- 21. How do you handle actions that have side effects?
- 22. What are the downsides of using ReactJS?
- 23. Explain the difference between the useState and useReducer hooks. When would you use one over the other?
- 24. What is server-side rendering, and what are its benefits?
- 25. What is React.lazy, and when would you use it?
- 26. How would you handle multiple API calls?
- 27. How do you test React components?
- 28. What is Snapshot testing in React?
- 29. What is the difference between Real DOM and Virtual DOM?
- 30. What is the context in React, and how and when would you use it?
- 31. What is Redux Saga?
- 32. Explain the concept of Middleware in Redux.
- 33. What are the common performance issues in React, and how would you optimize them?
- 34. How do you ensure component methods have the correct ‘this’ context in React?
- 35. What are the different ways to style a React component?
- MCQ Questions
- 1. What is React?
- 2. Who developed React?
- 3. What is the virtual DOM in React?
- 4. What is JSX in React?
- 5. What is the purpose of render() in React?
- 6. What are React components?
- 7. What is state in React?
- 8. What is props in React?
- 9. What is the purpose of keys in React lists?
- 10. What is the significance of React’s componentDidMount() lifecycle method?
- 11. What is the purpose of React Router?
- 12. What is Redux in React?
- 13. What is the purpose of React’s PureComponent?
- 14. What is the role of the shouldComponentUpdate() lifecycle method in React?
- 15. What is the purpose of React’s useContext() hook?
- 16. What is the significance of React’s useMemo() hook?
- 17. What is the purpose of React’s useCallback() hook?
- 18. What is the role of React’s useRef() hook?
- 19. What is the purpose of React’s useReducer() hook?
- 20. What is the concept of React Fragments?
- 21. What is the purpose of React’s useEffect() hook?
- 22. What is the concept of React Context?
- 23. What is the role of React’s useState() hook?
- 24. What is the purpose of React’s forwardRef() function?
- 25. What is the role of React’s useContext() hook?
- 26. What is the significance of React’s memo() function?
- 27. What is the concept of React Router?
- 28. What is the purpose of React’s useReducer() hook?
- 29. What is the role of React’s useCallback() hook?
- 30. What is the concept of React Fragments?
Introduction
Are you preparing for a React interview and looking for a user-friendly introduction to common interview questions? Look no further! React is a popular JavaScript library used for building user interfaces. During interviews, you might encounter questions about React components, state management, lifecycle methods, and more. These questions aim to assess your understanding of React concepts and your ability to solve real-world problems. In this guide, we’ll provide concise and easy-to-understand explanations of commonly asked React interview questions, helping you prepare effectively and confidently for your upcoming interview. Let’s dive in and enhance your React knowledge!
Basic Questions
1. What is React?
React is a popular JavaScript library for building user interfaces. It allows developers to create reusable UI components and efficiently manage the state of the application. Here’s a simple example of a React component:
import React from 'react';
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
export default Welcome;
2. What are the main features of React?
The main features of React include:
- Components and reusability
- Virtual DOM for efficient rendering
- JSX syntax for declarative UI
- One-way data binding with props
- State management
- Lifecycle methods for control over component behavior
- React Native for mobile app development
3. What is JSX?
JSX (JavaScript XML) is a syntax extension for React that allows you to write HTML-like code within JavaScript. It helps in creating React elements more intuitively. Here’s an example:
import React from 'react';
const element = <h1>Hello, JSX!</h1>;
export default element;
4. What is the difference between a Class component and a Functional component?
Class components are created using ES6 classes and have more features like state and lifecycle methods. Functional components, on the other hand, are simpler and mainly used for rendering UI based on props. Here’s a comparison:
Class Component example:
import React from 'react';
class Greeting extends React.Component {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
export default Greeting;
Functional Component example:
import React from 'react';
const Greeting = (props) => {
return <h1>Hello, {props.name}!</h1>;
};
export default Greeting;
5. What is the virtual DOM?
The virtual DOM is a lightweight copy of the actual DOM maintained by React. It helps improve rendering performance by minimizing direct manipulation of the real DOM. Here’s an example of how it works:
import React from 'react';
import ReactDOM from 'react-dom';
// Instead of directly rendering to the real DOM, React renders to the virtual DOM first
const virtualElement = <h1>Hello, Virtual DOM!</h1>;
// Then, React compares the virtual DOM with the actual DOM and performs only necessary updates
ReactDOM.render(virtualElement, document.getElementById('root'));
6. What is the role of ReactDOM.render() in React?
ReactDOM.render()
is used to render React elements to the real DOM. It takes a React element and attaches it to a specific HTML element in the document. Here’s an example:
import React from 'react';
import ReactDOM from 'react-dom';
const element = <h1>Hello, ReactDOM!</h1>;
ReactDOM.render(element, document.getElementById('root'));
7. What is a React component?
A React component is a reusable piece of UI that can have its own state and properties (props). It can be a class component or a functional component. Here’s an example:
import React from 'react';
class Button extends React.Component {
render() {
return <button>{this.props.label}</button>;
}
}
export default Button;
8. How do you create a component in React?
In React, you can create a component by defining a class or a function. Here’s an example of both class and functional components:
Class Component example:
import React from 'react';
class Greeting extends React.Component {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
export default Greeting;
Functional Component example:
import React from 'react';
const Greeting = (props) => {
return <h1>Hello, {props.name}!</h1>;
};
export default Greeting;
9. What is state in React?
State is a mechanism to store and manage data within a React component. It allows components to change and re-render based on changes to the data. Here’s an example of using state in a class component:
import React from 'react';
class Counter extends React.Component {
constructor() {
super();
this.state = {
count: 0,
};
}
increment = () => {
this.setState((prevState) => ({ count: prevState.count + 1 }));
};
render() {
return (
<div>
<p>Count: {this.state.count}</p>
<button onClick={this.increment}>Increment</button>
</div>
);
}
}
export default Counter;
10. What are props in React?
Props (short for properties) are used to pass data from a parent component to a child component. They are immutable and help to make components more dynamic and reusable. Here’s an example:
import React from 'react';
const Greeting = (props) => {
return <h1>Hello, {props.name}!</h1>;
};
export default Greeting;
Usage of the component:
import React from 'react';
import Greeting from './Greeting';
const App = () => {
return <Greeting name="John" />;
};
export default App;
11. What is the difference between state and props?
Feature | State | Props |
---|---|---|
Mutability | Can be changed within the component using setState | Immutable and passed from parent component |
Usage | Used for managing internal component data | Used for passing data from parent to child component |
Owned by | Owned and managed by the component | Owned and managed by the parent component |
Modification | Can be modified by the component itself | Cannot be modified by the component, read-only |
Update triggers | Changes in state trigger a re-render of the component | Changes in props trigger a re-render of the component |
Example | See the state example in the previous question | See the props example in the previous question |
12. What are the React lifecycle methods?
React lifecycle methods allow you to hook into specific moments during the lifecycle of a component. Here are some of the commonly used lifecycle methods:
import React from 'react';
class LifecycleDemo extends React.Component {
constructor() {
super();
console.log('Constructor called.');
}
componentDidMount() {
console.log('Component did mount.');
}
componentDidUpdate() {
console.log('Component did update.');
}
componentWillUnmount() {
console.log('Component will unmount.');
}
render() {
console.log('Render called.');
return <h1>Hello, Lifecycle!</h1>;
}
}
export default LifecycleDemo;
13. What is the purpose of super()
in React?
In React class components, super()
is used to call the constructor of the parent class (i.e., React.Component). It is necessary to call super()
if you define a constructor in a subclass to properly initialize the component.
import React from 'react';
class ChildComponent extends React.Component {
constructor() {
super(); // Call to the parent class constructor
// Other component-specific initialization here
}
render() {
return <h1>Hello, I'm the child component!</h1>;
}
}
export default ChildComponent;
14. What is the purpose of render()
in React?
The render()
method is a required lifecycle method in a React class component. It returns the JSX or React elements that make up the UI of the component.
import React from 'react';
class Greeting extends React.Component {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
export default Greeting;
15. What is a Steady Component? Give a relevant code example.
I’m not aware of the term “Steady Component” in the context of React. It might be an obsolete term or a term used in a specific context not covered in my training data.
16. What is an Uncontrolled Component?
An Uncontrolled Component is a form element (like input, textarea, etc.) that manages its own state internally rather than being controlled by React’s state. It typically uses a ref
to access its current value.
import React from 'react';
class UncontrolledForm extends React.Component {
inputRef = React.createRef();
handleSubmit = (event) => {
event.preventDefault();
console.log('Submitted value:', this.inputRef.current.value);
};
render() {
return (
<form onSubmit={this.handleSubmit}>
<input type="text" ref={this.inputRef} />
<button type="submit">Submit</button>
</form>
);
}
}
export default UncontrolledForm;
17. What is the use of keys in React?
Keys in React are used to help identify individual elements in a list. They aid React in efficiently updating and reordering elements without re-rendering all of them. Keys should be unique within the list.
import React from 'react';
const TodoList = () => {
const todos = [
{ id: 1, text: 'Buy groceries' },
{ id: 2, text: 'Walk the dog' },
{ id: 3, text: 'Clean the house' },
];
return (
<ul>
{todos.map((todo) => (
<li key={todo.id}>{todo.text}</li>
))}
</ul>
);
};
export default TodoList;
18. What is a higher order component?
A Higher Order Component (HOC) is a pattern in React where a function takes a component and returns a new component with additional props or behavior.
import React from 'react';
const withTitle = (WrappedComponent, title) => {
return (props) => (
<>
<h1>{title}</h1>
<WrappedComponent {...props} />
</>
);
};
const Greeting = (props) => {
return <p>Hello, {props.name}!</p>;
};
const GreetingWithTitle = withTitle(Greeting, 'Welcome');
export default GreetingWithTitle;
19. What is a fragment in React?
A Fragment is a built-in component in React that allows you to group multiple elements without adding an additional DOM element to the output.
import React from 'react';
const MyFragment = () => {
return (
<>
<h1>Title</h1>
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</>
);
};
export default MyFragment;
20. What is Context API in React?
The Context API in React allows you to pass data down the component tree without explicitly passing it through props at every level. It is useful when data needs to be accessed by many components at different nesting levels.
import React, { createContext, useContext } from 'react';
// Create a context
const MyContext = createContext();
// Provide data using the context provider
const App = () => {
return (
<MyContext.Provider value="Hello from Context">
<ChildComponent />
</MyContext.Provider>
);
};
// Consume data from the context
const ChildComponent = () => {
const dataFromContext = useContext(MyContext);
return <p>{dataFromContext}</p>;
};
export default App;
21. What are hooks in React?
Hooks are functions that allow you to use React features like state and lifecycle methods in functional components. Some commonly used hooks include useState
, useEffect
, useContext
, etc.
import React, { useState } from 'react';
const Counter = () => {
const [count, setCount] = useState(0);
const increment = () => {
setCount((prevCount) => prevCount + 1);
};
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
</div>
);
};
export default Counter;
22. What is the use of useEffect in React?
The useEffect
hook in React is used to perform side effects in functional components, such as data fetching, subscriptions, or manual DOM manipulation. It runs after every render of the component.
import React, { useState, useEffect } from 'react';
const DataFetching = () => {
const [data, setData] = useState([]);
useEffect(() => {
// Simulating data fetching with setTimeout
const fetchData = () => {
setTimeout(() => {
setData(['Item 1', 'Item 2', 'Item 3']);
}, 1000);
};
fetchData();
}, []);
return (
<ul>
{data.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
);
};
export default DataFetching;
23. How to apply validation on props in React?
You can use the prop-types
library to apply validation on props in React. It helps to define the expected type and presence of props.
import React from 'react';
import PropTypes from 'prop-types';
const Greeting = (props) => {
return <h1>Hello, {props.name}!</h1>;
};
Greeting.propTypes = {
name: PropTypes.string.isRequired,
};
export default Greeting;
24. What is the use of React Router?
React Router is a library that allows you to handle routing and navigation in a React application. It helps in creating Single Page Applications (SPAs)
by rendering different components based on the URL.
import React from 'react';
import { BrowserRouter as Router, Switch, Route, Link } from 'react-router-dom';
const Home = () => <h1>Welcome to the Home page!</h1>;
const About = () => <h1>About Us</h1>;
const Contact = () => <h1>Contact Us</h1>;
const App = () => {
return (
<Router>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/contact">Contact</Link>
</li>
</ul>
</nav>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/contact" component={Contact} />
</Switch>
</Router>
);
};
export default App;
25. What are synthetic events in React?
Synthetic events in React are synthetic wrappers around the native browser events. They provide cross-browser compatibility and automatic event pooling.
import React from 'react';
const Button = () => {
const handleClick = (event) => {
console.log('Button clicked!', event.target.value);
};
return <button onClick={handleClick}>Click Me</button>;
};
export default Button;
26. How to conditionally render components in React?
You can use conditional statements like if-else
or ternary operators to conditionally render components in React.
Using if-else
:
import React from 'react';
const ConditionalComponent = ({ showComponent }) => {
if (showComponent) {
return <h1>Show this component!</h1>;
} else {
return <h1>Don't show this component!</h1>;
}
};
export default ConditionalComponent;
Using ternary operator:
import React from 'react';
const ConditionalComponent = ({ showComponent }) => {
return showComponent ? <h1>Show this component!</h1> : <h1>Don't show this component!</h1>;
};
export default ConditionalComponent;
27. What is ‘Lifting State Up’ in React?
‘Lifting State Up’ is the process of moving the state from a child component to its parent component when multiple child components need to share the same state.
import React, { useState } from 'react';
const ChildComponent = ({ count, increment }) => {
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
</div>
);
};
const ParentComponent = () => {
const [count, setCount] = useState(0);
const increment = () => {
setCount((prevCount) => prevCount + 1);
};
return <ChildComponent count={count} increment={increment} />;
};
export default ParentComponent;
28. How can you handle events in React?
In React, you can handle events by passing event handlers as props to the components.
import React from 'react';
const Button = ({ onClick }) => {
return <button onClick={onClick}>Click Me</button>;
};
const App = () => {
const handleClick = () => {
console.log('Button clicked!');
};
return <Button onClick={handleClick} />;
};
export default App;
29. What is the use of refs in React?
Refs in React are used to get direct access to a DOM element or a component instance. They should be used sparingly, as they bypass React’s usual data flow.
import React, { useRef } from 'react';
const InputComponent = () => {
const inputRef = useRef();
const handleButtonClick = () => {
inputRef.current.focus();
};
return (
<div>
<input type="text" ref={inputRef} />
<button onClick={handleButtonClick}>Focus Input</button>
</div>
);
};
export default InputComponent;
30. What are the limitations of React?
Some of the limitations of React include:
- Steeper learning curve for beginners due to the concepts of components and state management.
- React focuses on the view layer of the application, and developers may need to use additional libraries for complex state management and routing.
- Large React applications can face performance issues, and optimization might be needed.
- Using React for SEO can be challenging due to server-side rendering requirements.
- React Native, while great for cross-platform mobile apps, may have limitations in accessing certain native device functionalities compared to native development.
Intermediate Questions
1. What is the React Context API and how is it used?
The React Context API is used to manage global state in React applications without having to pass props through all levels of the component tree. It allows data to be shared and accessed by any component within a specific context.
Example:
// Create a context
const MyContext = React.createContext();
// Create a provider component to wrap around components that need access to the context data
function MyProvider({ children }) {
const sharedData = "This is the shared data.";
return (
<MyContext.Provider value={sharedData}>
{children}
</MyContext.Provider>
);
}
// A component that consumes data from the context
function MyComponent() {
const data = useContext(MyContext);
return <div>{data}</div>;
}
// Wrap the components that need access to the context data with the provider
function App() {
return (
<MyProvider>
<MyComponent />
</MyProvider>
);
}
2. What are Pure Components in React?
Pure Components are a type of React component that automatically implements a shallow comparison of their props and state to determine if a re-render is necessary. They can help improve performance by avoiding unnecessary re-renders.
Example:
// Regular Component
class RegularComponent extends React.Component {
render() {
return <div>{this.props.name}</div>;
}
}
// Pure Component
class PureComponentExample extends React.PureComponent {
render() {
return <div>{this.props.name}</div>;
}
}
3. What is a higher-order component (HOC)? Can you provide an example?
A Higher-Order Component (HOC) is a function that takes a component and returns a new component with extended functionality. HOCs are used for code reuse, logic sharing, and adding additional props to components.
Example:
// Higher-Order Component
function withLogger(WrappedComponent) {
return class extends React.Component {
componentDidMount() {
console.log("Component was mounted.");
}
render() {
return <WrappedComponent {...this.props} />;
}
};
}
// Component to be wrapped with the HOC
class MyComponent extends React.Component {
render() {
return <div>Hello, {this.props.name}</div>;
}
}
// Wrap the component with the HOC
const MyComponentWithLogger = withLogger(MyComponent);
// Render the wrapped component
function App() {
return <MyComponentWithLogger name="John" />;
}
4. Explain the concept of “Lifting State Up” in React.
“Lifting State Up” is a pattern in React where state is moved from a child component to its parent component, so multiple child components can share and modify the same state.
Example:
// Child component
function TemperatureInput(props) {
return (
<input
type="number"
value={props.temperature}
onChange={(e) => props.onTemperatureChange(e.target.value)}
/>
);
}
// Parent component
class Calculator extends React.Component {
constructor(props) {
super(props);
this.state = { temperature: 0 };
}
handleTemperatureChange = (temperature) => {
this.setState({ temperature });
};
render() {
const { temperature } = this.state;
return (
<div>
<TemperatureInput
temperature={temperature}
onTemperatureChange={this.handleTemperatureChange}
/>
<TemperatureInput
temperature={temperature}
onTemperatureChange={this.handleTemperatureChange}
/>
</div>
);
}
}
In this example, the Calculator
component lifts the temperature
state up from the TemperatureInput
components, allowing both inputs to share and update the same state.
5. How do you handle forms in React?
In React, you can handle forms using controlled components. Controlled components tie the form elements to the component state, allowing React to control the form’s values.
Example:
class LoginForm extends React.Component {
constructor(props) {
super(props);
this.state = {
username: '',
password: ''
};
}
handleInputChange = (e) => {
const { name, value } = e.target;
this.setState({ [name]: value });
};
handleSubmit = (e) => {
e.preventDefault();
// Perform form submission logic here
console.log("Submitted data:", this.state);
};
render() {
const { username, password } = this.state;
return (
<form onSubmit={this.handleSubmit}>
<input
type="text"
name="username"
value={username}
onChange={this.handleInputChange}
/>
<input
type="password"
name="password"
value={password}
onChange={this.handleInputChange}
/>
<button type="submit">Login</button>
</form>
);
}
}
6. How do you implement Error Boundaries in React for error handling?
Error Boundaries in React are components that catch JavaScript errors during rendering, in lifecycle methods, and during the constructor execution of the whole tree below them. They help prevent the entire application from crashing due to a single component error.
Example:
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
// Log the error or send it to an error reporting service
console.error("Error caught by ErrorBoundary:", error, errorInfo);
}
render() {
if (this.state.hasError) {
return <div>Something went wrong!</div>;
}
return this.props.children;
}
}
// Usage of ErrorBoundary
function App() {
return (
<ErrorBoundary>
<ComponentThatMightThrowAnError />
</ErrorBoundary>
);
}
7. Explain the use of arrow functions in React.
Arrow functions in React are used for defining concise and inline function expressions. They automatically bind the value of this
based on the surrounding context and help avoid common pitfalls with this
keyword scoping.
Example:
// Regular function component
function MyComponent() {
return (
<button onClick={function() { console.log("Clicked!"); }}>
Click Me
</button>
);
}
// Using arrow function
function MyComponent() {
return (
<button onClick={() => { console.log("Clicked!"); }}>
Click Me
</button>
);
}
In the above example, the arrow function does not need to explicitly bind this
because it automatically inherits the surrounding context, whereas the regular function would require explicit binding or it would not work as expected.
8. What is Redux and how is it related to React?
Redux is a predictable state container for JavaScript applications. It is often used with React to manage the state of an application and provide a centralized store that holds the application state.
Example:
// Redux store setup
import { createStore } from 'redux';
// Reducer function
const initialState = { count: 0 };
function counterReducer(state = initialState, action) {
switch (action.type) {
case 'INCREMENT':
return { count: state.count + 1 };
case 'DECREMENT':
return { count: state.count - 1 };
default:
return state;
}
}
// Create the Redux store
const store = createStore(counterReducer);
// React component using Redux
import { useSelector, useDispatch } from 'react-redux';
function Counter() {
const count = useSelector(state => state.count);
const dispatch = useDispatch();
return (
<div>
<span>Count: {count}</span>
<button onClick={() => dispatch({ type: 'INCREMENT' })}>Increment</button>
<button onClick={() => dispatch({ type: 'DECREMENT' })}>Decrement</button>
</div>
);
}
In the above example, the Redux store is set up with a reducer function that handles state changes based on dispatched actions. The Counter
component uses Redux hooks (useSelector
and useDispatch
) to access the state from the store and dispatch actions to update the state.
9. What is the significance of Store in Redux?
The Store in Redux is a single source of truth that holds the state of the entire application. It plays a crucial role in managing the application state and ensuring that the state is updated in a predictable manner. The store helps to:
- Hold the application state in one place, making it easy to access and manage the state from any component.
- Provide a mechanism to subscribe to state changes, enabling components to react to changes in the state.
- Dispatch actions to modify the state in a controlled and predictable way through reducers.
10. What is a reducer in Redux?
In Redux, a reducer is a pure function that takes the current state and an action as arguments and returns a new state based on that action. It specifies how the state should change in response to the action dispatched to the Redux store.
Example:
// Reducer function
const initialState = { count: 0 };
function counterReducer(state = initialState, action) {
switch (action.type) {
case 'INCREMENT':
return { count: state.count + 1 };
case 'DECREMENT':
return { count: state.count - 1 };
default:
return state;
}
}
In this example, counterReducer
takes the state
and an action
as arguments and returns a new state based on the action type. When the action type is 'INCREMENT'
, the count is increased by 1, and when the action type is 'DECREMENT'
, the count is decreased by 1.
11. Explain how Redux Thunk works.
Redux Thunk is a middleware that allows asynchronous actions to be dispatched in Redux. It extends the capabilities of Redux to handle asynchronous operations such as making API calls before dispatching an action.
Example:
// Redux Thunk action creator
function fetchData() {
return (dispatch) => {
dispatch({ type: 'FETCH_DATA_START' });
// Simulate an API call
setTimeout(() => {
const data = [1, 2, 3, 4];
dispatch({ type: 'FETCH_DATA_SUCCESS', payload: data });
}, 1000);
};
}
// Usage of the thunk action creator
import { useDispatch, useSelector } from 'react-redux';
function MyComponent() {
const dispatch = useDispatch();
const data = useSelector((state) => state.data);
const handleFetchData = () => {
dispatch(fetchData());
};
return (
<div>
<button onClick={handleFetchData}>Fetch Data</button>
<ul>
{data.map((item) => (
<li key={item}>{item}</li>
))}
</ul>
</div>
);
}
In this example, the fetchData
action creator returns a function instead of a plain object. Redux Thunk intercepts this function and provides the dispatch
method as an argument. This allows the function to perform asynchronous operations and dispatch multiple actions at different times.
12. How would you handle asynchronous actions in Redux?
Asynchronous actions in Redux can be handled using Redux Thunk or other middleware libraries like Redux Saga or Redux Observable. Here’s an example using Redux Thunk:
// Redux Thunk action creator
function fetchData() {
return async (dispatch) => {
dispatch({ type: 'FETCH_DATA_START' });
try {
// Simulate an API call
const response = await fetch('https://api.example.com/data');
const data = await response.json();
dispatch({ type: 'FETCH_DATA_SUCCESS', payload: data });
} catch (error) {
dispatch({ type: 'FETCH_DATA_ERROR', payload: error.message });
}
};
}
// Usage of the thunk action creator
import { useDispatch, useSelector } from 'react-redux';
function MyComponent() {
const dispatch = useDispatch();
const data = useSelector((state) => state.data);
const error = useSelector((state) => state.error);
const handleFetchData = () => {
dispatch(fetchData());
};
return (
<div>
<button onClick={handleFetchData}>Fetch Data</button>
{data ? (
<ul>
{data.map((item) => (
<li key={item}>{item}</li>
))}
</ul>
) : (
<p>{error || 'No data available.'}</p>
)}
</div>
);
}
In this example, the fetchData
action creator uses async/await to handle the asynchronous API call. It dispatches different actions based on the success or failure of the API call.
13. What are the middleware functions in Redux?
Middleware functions in Redux provide a way to extend the behavior of dispatch
and allow additional processing to be done before an action reaches the reducer. Middleware sits between the action being dispatched and reaching the reducer.
Example using custom middleware:
// Custom middleware
const loggerMiddleware = (store) => (next) => (action) => {
console.log('Dispatching action:', action);
const result = next(action);
console.log('Updated state:', store.getState());
return result;
};
// Applying the middleware to the Redux store
import { createStore, applyMiddleware } from 'redux';
import rootReducer from './reducers';
const store =
createStore(rootReducer, applyMiddleware(loggerMiddleware));
In this example, the loggerMiddleware
logs the dispatched action and the updated state after every action. The applyMiddleware
function is used to include this middleware when creating the Redux store.
14. How do you make use of the ‘connect’ function in Redux?
The connect
function from react-redux
library is used to connect a React component to the Redux store. It allows the component to access the state and dispatch actions as props.
Example:
import { connect } from 'react-redux';
// Component
function MyComponent(props) {
return <div>Count: {props.count}</div>;
}
// mapStateToProps function
const mapStateToProps = (state) => {
return {
count: state.count
};
};
// Connect the component to the Redux store
const ConnectedComponent = connect(mapStateToProps)(MyComponent);
// Usage of the connected component
function App() {
return <ConnectedComponent />;
}
In this example, the mapStateToProps
function specifies which parts of the state should be mapped to the component’s props. The connect
function connects the component to the Redux store and makes the count
state available as a prop in the MyComponent
.
15. What is the purpose of ‘mapStateToProps’ and ‘mapDispatchToProps’ in Redux?
mapStateToProps
: It is a function used inconnect
to specify which parts of the Redux state should be mapped to the component’s props. It is used to extract data from the Redux store’s state and pass it as props to the component.
Example:
const mapStateToProps = (state) => {
return {
count: state.count
};
};
mapDispatchToProps
: It is a function used inconnect
to specify which action creators from Redux should be mapped to the component’s props. It is used to pass action creators as props to the component, making it easy to dispatch actions from the component.
Example:
const mapDispatchToProps = (dispatch) => {
return {
increment: () => dispatch({ type: 'INCREMENT' }),
decrement: () => dispatch({ type: 'DECREMENT' })
};
};
In the above example, the increment
and decrement
action creators are mapped to the component’s props using mapDispatchToProps
, allowing the component to dispatch these actions.
16. How do you implement routing in React?
Routing in React can be implemented using libraries like React Router. React Router provides components that help you define different routes in your application and navigate between them.
Example using React Router:
// Installation: npm install react-router-dom
// App.js
import { BrowserRouter as Router, Switch, Route, Link } from 'react-router-dom';
function Home() {
return <div>Welcome to the Home page!</div>;
}
function About() {
return <div>This is the About page.</div>;
}
function Contact() {
return <div>Contact us at example@example.com</div>;
}
function App() {
return (
<Router>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/contact">Contact</Link>
</li>
</ul>
</nav>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/contact" component={Contact} />
</Switch>
</Router>
);
}
In this example, we use BrowserRouter
as the router implementation and set up different routes using Route
components. The Switch
component ensures that only the first matched route is rendered, preventing multiple components from being shown simultaneously.
17. What is the difference between ‘react-router’ and ‘react-router-dom’?
react-router | react-router-dom |
---|---|
Core package for React Router, containing the routing logic. | Contains DOM bindings specific to React Router for web apps. |
Typically used for routing in non-web environments (e.g., React Native). | Designed for web applications and includes BrowserRouter . |
Doesn’t provide BrowserRouter or other DOM-specific components. | Includes components like BrowserRouter , Link , etc. |
Both packages work together, but react-router-dom
is the more commonly used package for web applications.
18. What is a render prop?
A render prop is a pattern in React where a component receives a function as a prop, and that function is responsible for rendering content. It allows the parent component to share its internal state or logic with the child component.
Example:
// Parent component with a render prop
class MouseTracker extends React.Component {
render() {
return (
<div onMouseMove={(e) => this.props.render(e)}>
{/* Some other content */}
</div>
);
}
}
// Usage of the MouseTracker component with a render prop
function App() {
return (
<MouseTracker
render={(e) => <div>Mouse position: {e.clientX}, {e.clientY}</div>}
/>
);
}
In this example, the MouseTracker
component takes a render prop, which is a function that receives the mouse event and returns JSX to be rendered. The App
component uses the MouseTracker
and defines how the mouse position is displayed.
19. What is a controlled component in React?
A controlled component in React is a component where the form data and its behavior are controlled by React. The component receives its current value and onChange event handler through props and notifies the parent component about any changes.
Example:
class InputForm extends React.Component {
constructor(props) {
super(props);
this.state = { inputValue: '' };
}
handleInputChange = (e) => {
this.setState({ inputValue: e.target.value });
};
handleSubmit = (e) => {
e.preventDefault();
// Submit the form data
console.log("Submitted value:", this.state.inputValue);
};
render() {
return (
<form onSubmit={this.handleSubmit}>
<input
type="text"
value={this.state.inputValue}
onChange={this.handleInputChange}
/>
<button type="submit">Submit</button>
</form>
);
}
}
In this example, the InputForm
component is a controlled component because the value of the input field is controlled by the component’s state and changes to the input value are handled through the handleInputChange
method.
20. What are hooks in React?
Hooks are functions in React that allow you to use state and other React features in functional components. They were introduced in React 16.8 to provide a simpler and more concise way to work with stateful logic in functional components.
Example:
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
const increment = () => {
setCount(count + 1);
};
const decrement = () => {
setCount(count - 1);
};
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Decrement</button>
</div>
);
}
In this example, the useState
hook allows us to add state to a functional component. The count
and setCount
variables are used to store and update the state, and the component’s UI reflects the current state.
21. Explain the use of the useEffect hook in React.
The useEffect
hook in React is used to perform side effects in functional components. It is similar to lifecycle methods like componentDidMount
, componentDidUpdate
, and componentWillUnmount
.
Example:
import React, { useState, useEffect } from 'react';
function ExampleComponent() {
const [data, setData] = useState([]);
useEffect(() => {
// Fetch data from an API
fetch('https://api.example.com/data')
.then((response) => response.json())
.then((data) => setData(data))
.catch((error) => console.error('Error fetching data:', error));
}, []); // Empty dependency array means the effect runs only once (on mount)
return (
<ul>
{data.map((item) => (
<li key={item.id}>{item.name}</li>
))}
</ul>
);
}
In this example, the useEffect
hook is used to fetch data from an API when the component mounts. The effect is set to run only once, as the dependency array is empty ([]
). If you provide a non-empty dependency array, the effect will run whenever the dependencies change.
22. What is the useState hook in React?
The useState
hook is used to add state to functional components in React. It returns a pair of values: the current state and a function to update that state.
Example:
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
const increment = () => {
setCount(count + 1);
};
const decrement = () => {
setCount(count - 1);
};
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Decrement</button>
</div>
);
}
In this example, the useState
hook is used to create a count
state variable with an initial value of 0. The setCount
function is used to update the value of count
when the buttons are clicked.
23. What are React PropTypes and how do you use them?
React PropTypes are used for type checking the props passed to a component. They help to ensure that the correct data types are being passed to components, which can prevent potential bugs and improve code maintainability.
Example:
import PropTypes from 'prop-types';
function Greeting(props) {
return <div>Hello, {props.name}</div>;
}
Greeting.propTypes = {
name: PropTypes.string.isRequired
};
In this example, the propTypes
property is used to define the expected types and constraints for the name
prop of the Greeting
component. In this case, name
should be a string and is required (marked with isRequired
). If the prop is missing or of the wrong type, a warning will be shown in the console during development.
24. What are Synthetic Events in React?
Synthetic Events in React are a cross-browser wrapper around the browser’s native events. They are similar to native events but provide consistent behavior across different browsers.
Example:
function Button() {
const handleClick = (e) => {
e.preventDefault();
console.log('Button clicked!');
};
return (
<button onClick={handleClick}>Click Me</button>
);
}
In this example, the onClick
event is a synthetic event provided by React. The handleClick
function is called when the button is clicked, and e.preventDefault()
prevents the default behavior of the event (e.g., form submission or link navigation).
25. Explain the lifecycle methods in React Components.
React class components have several lifecycle methods that allow you to hook into the different phases of a component’s life. These methods can be used for performing actions at specific points in the component’s lifecycle.
Here are the main lifecycle methods:
componentDidMount
: This method is called after the component has been rendered to the screen. It is commonly used for making AJAX requests or setting up subscriptions.c
omponentDidUpdate
: This method is called whenever the component is updated or re-rendered. It can be used for performing actions after an update, such as updating the DOM based on new data.componentWillUnmount
: This method is called just before the component is removed from the DOM. It can be used for cleanup, such as removing event listeners or canceling subscriptions.shouldComponentUpdate
: This method allows you to control whether the component should re-render or not. By default, the component re-renders whenever its state or props change, but you can implement this method to optimize performance by preventing unnecessary re-renders.getDerivedStateFromProps
: This static method is called before rendering and is used to update the state based on changes in props. It is rarely used, as you should prefer using controlled components.
26. How do you implement server-side rendering or isomorphic rendering in React?
Server-side rendering (SSR) or isomorphic rendering in React means rendering the initial page content on the server before sending it to the client. It can improve the initial load time and SEO of the application.
Example using Node.js and Express:
// server.js
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import App from './App';
import express from 'express';
const app = express();
app.get('/', (req, res) => {
const html = ReactDOMServer.renderToString(<App />);
res.send(`
<html>
<head>
<title>My React App</title>
</head>
<body>
<div id="root">${html}</div>
</body>
</html>
`);
});
app.listen(3000, () => {
console.log('Server is running on http://localhost:3000');
});
In this example, we use ReactDOMServer.renderToString
to render the React
App component to a string on the server. The server responds with the generated HTML containing the initial content of the React app.
27. What is the significance of keys in React lists?
Keys are a special attribute used in React when rendering lists of elements. They help React identify which items have changed, been added, or been removed from the list. When a list is re-rendered, React uses keys to efficiently update the DOM, minimizing unnecessary DOM manipulations and improving performance.
Example:
function ListComponent() {
const items = ['Item 1', 'Item 2', 'Item 3'];
return (
<ul>
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
);
}
In this example, each list item is given a unique key based on its index. If the order of the list changes, or an item is added or removed, React can identify which elements need to be updated, moved, or inserted based on their keys.
28. Explain how to do code-splitting in React.
Code-splitting is a technique in React that allows you to split your bundled JavaScript code into smaller chunks, which can be loaded on-demand. This can help reduce the initial loading time of the application.
Example using dynamic import (available in modern environments with native dynamic import support or using a tool like Webpack):
import React, { useState } from 'react';
const LazyComponent = React.lazy(() => import('./LazyComponent'));
function App() {
const [showLazyComponent, setShowLazyComponent] = useState(false);
const handleClick = () => {
setShowLazyComponent(true);
};
return (
<div>
<button onClick={handleClick}>Load Lazy Component</button>
{showLazyComponent && (
<React.Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</React.Suspense>
)}
</div>
);
}
In this example, we use React.lazy
to dynamically import the LazyComponent
when the button is clicked. The React.Suspense
component is used to show a fallback while the component is being loaded.
29. What are the benefits of using React.memo()?
React.memo()
is a higher-order component provided by React to optimize functional components by preventing unnecessary re-renders. When you wrap a component with React.memo()
, it will only re-render when its props change.
Benefits of using React.memo()
:
- Performance improvement: It reduces re-renders for components that receive the same props, improving the application’s performance.
- Reduction in unnecessary calculations: Components wrapped in
React.memo()
avoid unnecessary calculations in therender
function when their props haven’t changed. - Easy to use: It is easy to implement; you just wrap your functional component with
React.memo()
.
Example:
import React from 'react';
const MemoizedComponent = React.memo(MyComponent);
In this example, MyComponent
will be memoized, and it will only re-render when its props change.
30. How can you optimize a React application’s performance?
To optimize a React application’s performance, you can follow these practices:
- Use functional components and hooks: Functional components have better performance than class components. Hooks, like
useState
,useEffect
, anduseMemo
, allow you to optimize the component’s behavior and reduce unnecessary re-renders. - Use
React.memo()
: As mentioned earlier,React.memo()
helps prevent unnecessary re-renders for functional components by caching the result of the component’s rendering. - Code-splitting: Use code-splitting techniques to load only the required parts of the application when needed. This can reduce the initial loading time of the application.
- Use
shouldComponentUpdate
orReact.memo()
with custom comparison functions: In class components, you can useshouldComponentUpdate
to prevent unnecessary renders. With functional components, you can useReact.memo()
and provide a custom comparison function to control when the component should re-render. - Optimize list rendering: When rendering lists, use unique keys for each item to optimize updates. Avoid using the index as the key if the list items can be reordered.
- Use production build: Make sure to use the production build of React for your production environment. It includes performance optimizations and removes development-only features.
- Profiling: Use React’s built-in profiler or third-party tools to identify performance bottlenecks in your application and optimize them.
- Optimize images and assets: Compress images and other assets to reduce their size and improve the application’s loading time.
- Use memoization and caching: Use memoization techniques, like
useMemo
or memoization libraries, to cache the results of expensive computations and avoid redundant calculations. - Avoid unnecessary state updates: Make sure to update the state only when necessary, and use functional updates when modifying the state based on its previous value.
Advanced Questions
1. What is reconciliation in React?
Reconciliation is the process in React where the virtual DOM is compared to the actual DOM and any differences are updated efficiently to minimize unnecessary DOM manipulations. This process helps improve performance by reducing the number of updates needed to keep the UI in sync.
Example:
// Initial state
const data = ['Item 1', 'Item 2', 'Item 3'];
// Initial rendering
const element = (
<ul>
{data.map((item) => (
<li key={item}>{item}</li>
))}
</ul>
);
ReactDOM.render(element, document.getElementById('root'));
// Updated state
const updatedData = ['Item 1', 'Item 3', 'Item 4'];
// Updated rendering
const updatedElement = (
<ul>
{updatedData.map((item) => (
<li key={item}>{item}</li>
))}
</ul>
);
// React performs reconciliation and efficiently updates only the necessary changes in the actual DOM
ReactDOM.render(updatedElement, document.getElementById('root'));
2. What is the Flux architecture? How is it different from Redux?
Flux is a design pattern for managing application state in a predictable way. It has four major components: Actions, Dispatcher, Stores, and Views (React components). Flux emphasizes unidirectional data flow, where data changes flow in a single direction from Actions through the Dispatcher to the Stores, and then to the Views.
Redux is a state management library inspired by Flux but simplifies the architecture by having a single store instead of multiple stores. Redux also emphasizes immutability and a pure reducer function to update state.
Example of Flux (simplified version):
// Action
const ActionTypes = {
UPDATE_DATA: 'UPDATE_DATA',
};
const updateDataAction = (data) => ({
type: ActionTypes.UPDATE_DATA,
payload: data,
});
// Dispatcher
class Dispatcher {
constructor() {
this.callbacks = [];
}
register(callback) {
this.callbacks.push(callback);
}
dispatch(action) {
this.callbacks.forEach((callback) => callback(action));
}
}
const dispatcher = new Dispatcher();
// Store
let data = [];
const dataStore = (state = data, action) => {
switch (action.type) {
case ActionTypes.UPDATE_DATA:
return action.payload;
default:
return state;
}
};
// View
const renderView = (data) => {
// Render the view using the updated data
};
// Subscribe to store changes
dispatcher.register((action) => {
data = dataStore(data, action);
renderView(data);
});
// Initial dispatch to update data
dispatcher.dispatch(updateDataAction(['Item 1', 'Item 2']));
Example of Redux (simplified version):
import { createStore } from 'redux';
// Action
const ActionTypes = {
UPDATE_DATA: 'UPDATE_DATA',
};
const updateDataAction = (data) => ({
type: ActionTypes.UPDATE_DATA,
payload: data,
});
// Reducer
const dataReducer = (state = [], action) => {
switch (action.type) {
case ActionTypes.UPDATE_DATA:
return action.payload;
default:
return state;
}
};
// Store
const store = createStore(dataReducer);
// View
const renderView = () => {
const data = store.getState();
// Render the view using the updated data
};
// Subscribe to store changes
const unsubscribe = store.subscribe(renderView);
// Initial dispatch to update data
store.dispatch(updateDataAction(['Item 1', 'Item 2']));
3. Can you explain the concept of “Immutable State”?
Immutable state means that the state object cannot be modified directly after it’s created. Instead of mutating the state, you create a new state object with the required changes. This concept is important because it helps avoid unwanted side effects and makes it easier to track changes in the application.
Example:
import { useState } from 'react';
// Incorrect mutable state update
const mutableStateExample = () => {
const [data, setData] = useState(['Item 1', 'Item 2']);
const addItem = (item) => {
data.push(item); // Mutating the state directly (wrong)
setData(data); // Will not trigger re-render because the reference is the same
};
addItem('Item 3'); // This will not update the UI as expected
};
To achieve immutable state, you should create a new state object:
import { useState } from 'react';
// Correct immutable state update
const immutableStateExample = () => {
const [data, setData] = useState(['Item 1', 'Item 2']);
const addItem = (item) => {
setData((prevData) => [...prevData, item]); // Creating a new array with the updated data
};
addItem('Item 3'); // This will update the UI correctly
};
4. What is the significance of the shouldComponentUpdate lifecycle method in React?
The shouldComponentUpdate
method is a lifecycle hook in React that allows you to control whether a component should re-render or not. By default, React will re-render a component whenever its state or props change. However, in some cases, re-rendering may not be necessary, and that’s where shouldComponentUpdate
becomes significant.
Example:
class MyComponent extends React.Component {
state = {
count: 0,
};
shouldComponentUpdate(nextProps, nextState) {
// Check if the count has changed
if (this.state.count !== nextState.count) {
return true; // Allow re-rendering
}
return false; // Prevent re-rendering
}
incrementCount = () => {
this.setState((prevState) => ({ count: prevState.count + 1 }));
};
render() {
return (
<div>
<p>Count: {this.state.count}</p>
<button onClick={this.incrementCount}>Increment</button>
</div>
);
}
}
In this example, the shouldComponentUpdate
method checks if the count
state has changed. If it hasn’t, the component will not re-render when the button is clicked, saving unnecessary rendering cycles and improving performance.
5. How does React handle or prevent XSS attacks?
React protects against XSS (Cross-Site Scripting) attacks by automatically escaping the values rendered into the DOM. This means that any user-generated content will be sanitized and treated as plain text, preventing malicious code execution.
Example:
import React from 'react';
const userInput = '<script>alert("XSS Attack!");</script>';
const App = () => {
return (
<div>
{/* React automatically escapes the userInput */}
<p>{userInput}</p>
</div>
);
};
export default App;
In the example above, even though userInput
contains potential script tags, React will render it as plain text, displaying it as-is without executing any script.
6. How would you handle side effects on component unmount?
To handle side effects when a component is unmounted (i.e., it is being removed from the DOM), you can use the useEffect
hook and return a cleanup function. The cleanup function will be executed when the component is unmounted, allowing you to perform necessary cleanup tasks like clearing timers, unsubscribing from event listeners, etc.
Example:
import { useState, useEffect } from 'react';
const SideEffectExample = () => {
const [data, setData] = useState('');
useEffect(() => {
const fetchData = async () => {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
setData(data);
};
fetchData();
// Cleanup function to be executed on unmount
return () => {
// Perform cleanup tasks here (e.g., clear timers, remove event listeners, etc.)
console.log('Component unmounted. Cleaning up...');
};
}, []);
return <div>{data}</div>;
};
In this example, the useEffect
hook fetches data from an API and sets it in the component’s state. The cleanup function returned from useEffect
will be executed when the component is unmounted, logging a message to the console as an example of cleanup.
7. What are React Portals, and where can they be used?
React Portals allow you to render components outside their parent component’s DOM hierarchy. This can be useful for scenarios like creating modal dialogs, tooltips, or dropdown menus that need to be rendered at the top-level of the DOM, separate from the parent component.
Example:
import ReactDOM from 'react-dom';
const Modal = ({ isOpen, onClose, children }) => {
if (!isOpen) return null;
return ReactDOM.createPortal(
<div className="modal-overlay">
<div className="modal">
{children}
<button onClick={onClose}>Close</button>
</div>
</div>,
document.getElementById('modal-root') // The container element outside the main app
);
};
const App = () => {
const [isModalOpen, setIsModalOpen] = useState(false);
const openModal = () => setIsModalOpen(true);
const closeModal = () => setIsModalOpen(false);
return (
<div>
<button onClick={openModal}>Open Modal</button>
<Modal isOpen={isModalOpen} onClose={closeModal}>
<h2>Modal Content</h2>
<p>Modal body text goes here...</p>
</Modal>
</div>
);
};
export default App;
In this example, the Modal
component is rendered using ReactDOM.createPortal
inside the container element with the id modal-root
. It allows the modal to be rendered outside the main app component’s DOM hierarchy while still being part of the React component tree.
8. What are Suspense and lazy functions in React?
Suspense is a React feature that allows components to wait for something, such as lazy-loaded components or data fetching, before rendering. It is commonly used with React’s code-splitting capabilities to load components asynchronously, improving application performance.
lazy
is a function provided by React that enables lazy loading of components. It returns a promise for the module containing the component and allows you to load it only when it’s needed, rather than upfront.
Example:
import React, { Suspense } from 'react';
// Lazy loading a component
const LazyComponent = React.lazy(() => import('./LazyComponent'));
const App = () => {
return (
<div>
{/* Suspense with fallback while LazyComponent is loading */}
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
</div>
);
};
export default App;
In this example, LazyComponent
is loaded asynchronously only when it’s needed. The Suspense
component acts as a boundary and shows a fallback content (e.g., “Loading…”) while the component is being loaded. Once the component is ready, it will be rendered in place of the fallback content.
9. How does Error Boundary handle errors in the whole application or part of the application?
Error Boundaries in React are components that catch JavaScript errors during rendering, in lifecycle methods, and in the constructors of the whole component tree below them. They help prevent entire parts of the UI from crashing due to errors in specific components. When an error occurs, the Error Boundary component can gracefully display a fallback UI.
Example:
class ErrorBoundary extends React.Component {
state = {
hasError: false,
error: null,
errorInfo: null,
};
componentDidCatch(error, errorInfo) {
this.setState({ hasError: true, error, errorInfo });
}
render() {
if (this.state.hasError) {
// Render fallback UI
return (
<div>
<h2>Something went wrong.</h2>
<details style={{ whiteSpace: 'pre-wrap' }}>
{this.state.error && this.state.error.toString()}
<br />
{this.state.errorInfo.componentStack}
</details>
</div>
);
}
return this.props.children;
}
}
const MyComponent = () => {
if (Math.random() < 0.5) {
throw new Error('Error occurred in MyComponent.');
}
return <div>This is MyComponent.</div>;
};
const App = () => {
return (
<ErrorBoundary>
<MyComponent />
</ErrorBoundary>
);
};
export default App;
In this example, the ErrorBoundary
component is used to wrap the MyComponent
. If an error occurs in MyComponent
, the ErrorBoundary
catches it and renders the fallback UI. As a result, the entire application doesn’t crash, and the error is gracefully handled.
10. How do you handle an API request error in React?
Handling API request errors in React typically involves using a combination of try
and catch
blocks when making the API call with fetch
or using a library like Axios that provides error handling mechanisms.
Example using fetch
:
import React, { useState } from 'react';
const App = () => {
const [data, setData] = useState(null);
const [error, setError] = useState(null);
const fetchData = async () => {
try {
const response = await fetch('https://api.example.com/data');
if (!response.ok) {
throw new Error('Network response was not ok.');
}
const data = await response.json();
setData(data);
} catch (error) {
setError(error.message);
}
};
return (
<div>
{data ? (
<div>Data loaded successfully: {JSON.stringify(data)}</div>
) : error ? (
<div>Error occurred: {error}</div>
) : (
<
button onClick={fetchData}>Fetch Data</button>
)}
</div>
);
};
export default App;
In this example, the fetchData
function uses try
and catch
to handle any errors that might occur during the API call. If an error occurs, it is caught and stored in the error
state, which will be displayed in the UI. If the API call is successful, the data is set in the data
state, and it will be displayed in the UI as well.
11. Explain how to use React.forwardRef.
React.forwardRef
is a feature in React that allows you to pass a ref from a parent component to a child component that needs access to a DOM element or a React component instance. This is useful when you want to interact with child components directly from a parent component.
Example:
import React, { useRef } from 'react';
const ChildComponent = React.forwardRef((props, ref) => {
return <input ref={ref} />;
});
const ParentComponent = () => {
const inputRef = useRef(null);
const focusInput = () => {
inputRef.current.focus();
};
return (
<div>
<ChildComponent ref={inputRef} />
<button onClick={focusInput}>Focus Input</button>
</div>
);
};
export default ParentComponent;
In this example, the ChildComponent
is wrapped with React.forwardRef
, allowing the parent component (ParentComponent
) to pass a ref (inputRef
) directly to the input
element inside ChildComponent
. The focusInput
function in ParentComponent
uses the forwarded ref to programmatically focus on the input
element when the “Focus Input” button is clicked.
12. What is Concurrent Mode in React?
Concurrent Mode is an experimental feature in React that aims to improve the responsiveness and performance of the UI. It allows React to work on rendering components and handling updates concurrently, breaking the rendering work into smaller units to provide a more fluid user experience.
Example:
import { unstable_concurrentAct as act } from 'react-dom/test-utils'; // Only for testing Concurrent Mode
const App = () => {
const [data, setData] = useState(null);
// Simulating an asynchronous operation
useEffect(() => {
// Start fetching data
act(() => {
setTimeout(() => {
setData('Data loaded successfully.');
}, 2000);
});
}, []);
return <div>{data ? data : 'Loading...'}</div>;
};
export default App;
In this example, we’re using unstable_concurrentAct
from react-dom/test-utils
to simulate Concurrent Mode (Note: this API is intended for testing only and may change in the future). The App
component sets a timeout to simulate an asynchronous operation, and during this time, the component can still respond to user interactions and update the UI.
13. What are the rules for Hooks usage in React?
The rules for using Hooks in React are as follows:
- Hooks should only be used at the top level of the functional component or inside other custom hooks. They should not be used inside loops, conditions, or nested functions.
- Hooks should always be called in the same order. This rule ensures that React can keep track of the state and props correctly.
- Custom hooks should always start with the prefix “use” (e.g.,
useCustomHook
). This convention helps identify custom hooks easily. - Hooks should not be called in regular JavaScript functions. They are meant to be used in functional components or other custom hooks.
- Only call Hooks from React functional components or other custom Hooks. Avoid calling them in regular JavaScript functions, class components, or event handlers.
14. What are custom hooks? Provide an example.
Custom hooks are functions in React that allow you to reuse stateful logic between different components. They follow the “use” prefix convention and can encapsulate complex logic, making it easier to share code among components.
Example:
import { useState, useEffect } from 'react';
// Custom hook to fetch data
const useFetchData = (url) => {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch(url);
const data = await response.json();
setData(data);
} catch (error) {
console.error('Error fetching data:', error);
} finally {
setLoading(false);
}
};
fetchData();
}, [url]);
return { data, loading };
};
// Using the custom hook in a component
const MyComponent = () => {
const { data, loading } = useFetchData('https://api.example.com/data');
if (loading) {
return <div>Loading...</div>;
}
return <div>{data ? JSON.stringify(data) : 'No data available.'}</div>;
};
export default MyComponent;
In this example, the useFetchData
custom hook encapsulates the data-fetching logic. The MyComponent
uses this custom hook to fetch data from the given URL and handle loading states. By using the custom hook, the data-fetching logic can be reused across multiple components, promoting code reusability and readability.
15. Explain how to use the useReducer hook.
The useReducer
hook is an alternative to useState
for managing complex state logic in React. It takes a reducer function and an initial state, returns the current state and a dispatch function to update the state.
Example:
import { useReducer } from 'react';
// Reducer function
const reducer = (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 initialState = { count: 0 };
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({ type: 'INCREMENT' })}>Increment</button>
<button onClick={() => dispatch({ type: 'DECREMENT' })}>Decrement</button>
</div>
);
};
export default Counter;
In this example, the useReducer
hook manages the state of the count. The reducer
function specifies how the state should be updated based on different actions (e.g., INCREMENT, DECREMENT). The dispatch
function is used to trigger the corresponding actions, and the state is updated accordingly.
16. What is the purpose of the useCallback hook?
The useCallback
hook is used to memoize functions to prevent unnecessary re-creations of function instances, especially when passed down to child components. It is particularly useful when dealing with performance optimizations and preventing excessive re-rendering of child components.
Example:
import { useState, useCallback } from 'react';
const ParentComponent = () => {
const [count, setCount] = useState(0);
const increment = useCallback(() => {
setCount((prevCount) => prevCount + 1);
}, []); // Empty dependency array ensures the same instance is used for the callback
return (
<div>
<p>Count: {count}</p>
<ChildComponent increment={increment} />
</div>
);
};
const ChildComponent = ({ increment }) => {
return (
<div>
<button onClick={increment}>Increment</button>
</div>
);
};
export default ParentComponent;
In this example, the increment
function is wrapped in useCallback
. This ensures that the same instance of the increment
function is used across renders of ParentComponent
, preventing unnecessary re-creation of the function and potential re-renders of ChildComponent
.
17. What is the purpose of the useMemo hook?
The useMemo
hook is used to memoize the result of a computation, allowing you to avoid unnecessary re-computation of expensive functions when the dependencies haven’t changed. It is useful for optimizing performance by preventing redundant calculations.
Example:
import { useState, useMemo } from 'react';
const ExpensiveComputationComponent = () => {
const [count, setCount] = useState(1);
const expensiveResult = useMemo(() => {
console.log('Expensive computation is performed.'); // This log will only appear when the count changes
return count * 1000; // Some expensive computation based on count
}, [count]); // Dependency array ensures re-computation only when count changes
return (
<div>
<p>Count: {count}</p>
<p>Expensive Result: {expensiveResult}</p>
<button onClick={() => setCount((prevCount) => prevCount + 1)}>Increment</button>
</div>
);
};
export default ExpensiveComputationComponent;
In this example, the expensiveResult
is calculated using useMemo
. The function inside useMemo
will be executed only when the value of count
changes, ensuring that the expensive computation is performed only when necessary.
18. Explain how you would implement a dark mode in React.
Implementing dark mode in React can be achieved using state management, CSS variables, or third-party libraries like styled-components
. Below is an example using CSS variables:
import React, { useState, useEffect } from 'react';
const DarkModeComponent = () => {
const [darkMode, setDarkMode] = useState(false);
// Check local storage for saved dark mode preference on initial load
useEffect(() => {
const savedDarkMode = localStorage.getItem('darkMode');
if (savedDarkMode) {
setDarkMode(savedDarkMode === 'true');
}
}, []);
// Save dark mode preference to local storage whenever it changes
useEffect(() => {
localStorage.setItem('darkMode', darkMode.toString());
}, [darkMode]);
return (
<div className={darkMode ? 'dark-mode' : 'light-mode'}>
<h1>Dark Mode Example</h1>
<button onClick={() => setDarkMode((prevDarkMode) => !prevDarkMode)}>
Toggle Dark Mode
</button>
</div>
);
};
export default DarkModeComponent;
In this example, we store the dark mode preference in local storage to persist the user’s preference across page reloads. When the user toggles dark mode, the darkMode
state is updated, and the class name is changed dynamically to apply the dark or light mode styles using CSS variables.
19. How do you optimize large lists in React?
Optimizing large lists in React can be achieved using the react-window
library or the react-virtualized
library. These libraries use windowing techniques to render only the visible items, which significantly improves performance when dealing with long lists.
Here’s an example using react-window
:
npm install react-window
import React from 'react';
import { FixedSizeList as List } from 'react-window';
const LargeList = () => {
// Sample data with 1000 items
const data = Array.from(Array(1000).keys());
// Render an individual item
const renderItem = ({ index, style }) => {
return <div style={style}>{data[index]}</div>;
};
return (
<List
height={500} // Height of the visible window
width={300} // Width of the visible window
itemCount={data.length} // Total number of items
itemSize={30} // Height of each item
>
{renderItem}
</List>
);
};
export default LargeList;
In this example, react-window
is used to render the list efficiently by rendering only the visible items, no matter how large the list is. The FixedSizeList
component takes care of the windowing technique, and you provide it with the height
, width
, itemCount
, and itemSize
to determine the list’s dimensions and item heights.
20. What are your strategies for managing complex state interactions?
When managing complex state interactions in React, you can follow these strategies:
- State Normalization: Normalize your state to keep it flat and avoid redundancy. Use data structures like objects and arrays to organize data efficiently.
- Stateful Components: Use stateful components (class components or
useState
hook) to manage local component-specific state. - State Lifting: If state needs to be shared between components, lift the state to the closest common ancestor of those components and pass it down as props.
- UseReducer: For complex state logic, use
useReducer
to encapsulate state updates and actions in a single reducer function. - Custom Hooks: Create custom hooks to encapsulate reusable state logic and share it across different components.
- Context API: Use the Context API to provide state globally to components that need it without passing props manually.
- Immutability: Always update state immutably to avoid side effects and ensure proper re-renders.
21. How do you handle actions that have side effects?
For actions that have side effects, such as data fetching or interacting with external APIs, you can use middleware in Redux or useEffect
in React.
Example using useEffect
:
import React, { useState, useEffect } from 'react';
const DataFetchingComponent = () => {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
setData(data);
} catch (error) {
console.error('Error fetching data:', error);
} finally
{
setLoading(false);
}
};
fetchData();
}, []);
return (
<div>
{loading ? <div>Loading...</div> : <div>{JSON.stringify(data)}</div>}
</div>
);
};
export default DataFetchingComponent;
In this example, the useEffect
hook is used to fetch data from an API when the component mounts. The side effect of fetching data is handled within the useEffect
function. The component displays “Loading…” while the data is being fetched and then renders the fetched data once it’s available.
22. What are the downsides of using ReactJS?
While ReactJS is a popular and powerful framework, it does have some downsides:
- Learning Curve: ReactJS has a steep learning curve for beginners, especially when dealing with advanced concepts like Redux and React Router.
- Fragmentation: The ecosystem of ReactJS has a vast number of libraries and tools, which can lead to fragmentation and make it challenging to choose the right tools for your project.
- Boilerplate Code: ReactJS can lead to a lot of boilerplate code, especially when managing state and props manually in class components.
- Performance Concerns: ReactJS’s Virtual DOM can sometimes lead to performance issues when handling large and complex component trees.
- Overhead: ReactJS might be overkill for small projects, adding unnecessary complexity.
Example of boilerplate code in class components:
import React, { Component } from 'react';
class Counter extends Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
incrementCount = () => {
this.setState((prevState) => ({ count: prevState.count + 1 }));
};
render() {
return (
<div>
<p>Count: {this.state.count}</p>
<button onClick={this.incrementCount}>Increment</button>
</div>
);
}
}
export default Counter;
In this example, the class component introduces more boilerplate code, like the constructor and manually binding methods. This can be avoided using functional components and hooks.
23. Explain the difference between the useState and useReducer hooks. When would you use one over the other?
useState
and useReducer
are both hooks used to manage state in React, but they have some differences:
- useState:
useState
is a simpler hook that is commonly used for managing simple state updates. It returns a state variable and a function to update that state.
Example:
import { useState } from 'react';
const Counter = () => {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount((prevCount) => prevCount + 1)}>Increment</button>
</div>
);
};
export default Counter;
- useReducer:
useReducer
is more powerful and flexible for managing complex state logic. It takes a reducer function and an initial state, and it returns the current state and a dispatch function to update the state. It is commonly used for state that involves multiple actions and transitions.
Example:
import { useReducer } from 'react';
const initialState = { count: 0 };
const reducer = (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(reducer, initialState);
return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({ type: 'INCREMENT' })}>Increment</button>
<button onClick={() => dispatch({ type: 'DECREMENT' })}>Decrement</button>
</div>
);
};
export default Counter;
When to use useState
over useReducer
:
- For simple state updates that involve a single value.
- For components with less complex state management.
When to use useReducer
over useState
:
- For complex state logic with multiple actions and transitions.
- When you need to pass down dispatch functions to deeply nested components.
24. What is server-side rendering, and what are its benefits?
Server-Side Rendering (SSR) is a technique where the initial render of a web application is performed on the server, and the resulting HTML is sent to the client. It enables search engines to crawl the content and improves the initial loading time for users.
Example using Next.js (a popular framework for SSR in React):
npx create-next-app my-app
cd my-app
npm run dev
In this example, Next.js automatically enables SSR by default. When you run the application and check the page source, you will see the rendered HTML on the server.
Benefits of Server-Side Rendering:
- Improved SEO: Search engines can index the content as it’s rendered on the server, leading to better SEO rankings.
- Faster Initial Load: Users see the content more quickly since the server sends the initial HTML, reducing the time to first meaningful paint.
- Accessibility: Users with slow internet connections or non-JavaScript browsers can still view the content.
25. What is React.lazy, and when would you use it?
React.lazy
is a function that allows you to lazy-load components and their dependencies, making it possible to split your code into smaller chunks and load them on-demand, improving the performance of your application.
Example:
import React, { lazy, Suspense } from 'react';
const LazyComponent = lazy(() => import('./LazyComponent'));
const App = () => {
return (
<div>
{/* Suspense with fallback while LazyComponent is loading */}
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
</div>
);
};
export default App;
In this example, LazyComponent
is lazy-loaded using React.lazy
. When App
is rendered, LazyComponent
is loaded only when it’s needed (e.g., when the component is mounted). While LazyComponent
is loading, the Suspense
component displays a fallback UI (e.g., “Loading…”) until the actual component is ready to be rendered.
26. How would you handle multiple API calls?
Handling multiple API calls can be done using Promise.all
, which allows you to make several asynchronous requests concurrently and wait for all of them to resolve.
Example:
import React, { useEffect, useState } from 'react';
const App = () => {
const [data1, setData1] = useState(null);
const [data2, setData2] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchData = async () => {
try {
const [response1, response2] = await Promise.all([
fetch('https://api.example.com/data1'),
fetch('https://api.example.com/data2'),
]);
const data1 = await response1.json();
const data2 = await response2.json();
setData1(data1);
setData2(data2);
} catch (error) {
console.error('Error fetching data:', error);
} finally {
setLoading(false);
}
};
fetchData();
}, []);
if (loading) {
return <div>Loading...</div>;
}
return (
<div>
<p>Data 1: {data1 ? JSON.stringify(data1) : 'No data available.'}</p>
<p>Data 2: {data2 ? JSON.stringify(data2) : 'No data available.'}</p>
</div>
);
};
export default App;
In this example, two API calls are made simultaneously using Promise.all
. The component waits for both requests to resolve, and once they are both ready, it sets the data in the state and renders the results.
27. How do you test React components?
Testing React components can be done using testing libraries like @testing-library/react
or Enzyme
. The following is an example using @testing-library/react
:
Example using @testing-library/react
and jest
:
npm install @testing-library/react @testing-library/jest-dom --save-dev
// Counter.js
import React, { useState } from 'react';
const Counter = () => {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount((prevCount) => prevCount + 1)}>Increment</button>
</div>
);
};
export default Counter;
// Counter.test.js
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
import Counter from './Counter';
test('counter increments when the button is clicked', () => {
render(<Counter />);
const countElement = screen.getByText('Count: 0');
const buttonElement = screen.getByText('Increment');
expect(countElement).toBeInTheDocument();
expect(countElement).toHaveTextContent('Count: 0');
fireEvent.click(buttonElement);
expect(countElement).toHaveTextContent('Count: 1');
});
In this example, we test the Counter
component using @testing-library/react
. We render the component, interact with the button using fireEvent.click
, and then assert that the count has incremented correctly using expect
and toHaveTextContent
.
28. What is Snapshot testing in React?
Snapshot testing is a form of testing in React that allows you to capture a rendered component’s output and compare it against a previously saved “snapshot” of the component’s output. It’s a quick way to detect unexpected changes in the UI.
Example using @testing-library/react
and jest
:
npm install @testing-library/react @testing-library/jest-dom --save-dev
// Counter.js
import React, { useState } from 'react';
const Counter = () => {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount((prevCount) => prevCount + 1)}>Increment</button>
</div>
);
};
export default Counter;
// Counter.test.js
import React from 'react';
import { render } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
import Counter from './Counter';
test('snapshot testing for Counter component', () => {
const { asFragment } = render(<Counter />);
expect(asFragment()).toMatchSnapshot();
});
In this example, we use asFragment
from @testing-library/react
to capture the rendered output of the Counter
component and compare it with a previously saved snapshot. If there are any unexpected changes, the test will fail, and you can review and update the snapshot accordingly.
29. What is the difference between Real DOM and Virtual DOM?
Real DOM | Virtual DOM |
---|---|
Represents the actual HTML structure of a web page | Represents a lightweight copy of the Real DOM in memory |
Any changes to the DOM result in reflow and repaint, which can be slow | Changes to the Virtual DOM are made in memory and don’t cause reflow and repaint |
Updating the Real DOM directly is relatively slower and less efficient | Updating the Virtual DOM is faster and more efficient |
Manipulating the Real DOM can lead to performance issues, especially in large and complex applications | Virtual DOM reduces the risk of performance issues by batching and optimizing updates |
Accessing the Real DOM elements is more expensive in terms of time and memory | Virtual DOM allows for more efficient access to elements for comparison and update |
Real DOM updates can cause screen flickering and a poor user experience | Virtual DOM updates minimize flickering and improve user experience |
30. What is the context in React, and how and when would you use it?
React Context is a feature that allows you to pass data through the component tree without having to pass props explicitly at every level. It provides a way to share state or data between components that are not directly related.
You can use React Context when you have data that needs to be accessed by multiple components, like themes, user authentication, or language preferences. It helps avoid prop drilling, where props are passed through multiple levels of components just to reach the component that needs the data.
You create a context using React.createContext()
and provide a value to the context using a Provider
. Any component wrapped in the Provider
can access the value using the useContext
hook or Consumer
.
Example:
import React, { useContext } from 'react';
// Create a context
const ThemeContext = React.createContext('light');
// Provide the value using a Provider
const App = () => {
return (
<ThemeContext.Provider value="dark">
<ChildComponent />
</ThemeContext.Provider>
);
};
// Use the context value in ChildComponent using useContext hook
const ChildComponent = () => {
const theme = useContext(ThemeContext);
return (
<div>
<p>Theme: {theme}</p>
</div>
);
};
In this example, the ThemeContext
is created with the default value 'light'
. The App
component wraps ChildComponent
in the ThemeContext.Provider
, providing the value 'dark'
. ChildComponent
uses the useContext
hook to access the theme value provided by the ThemeContext.Provider
.
31. What is Redux Saga?
Redux Saga is a middleware library for Redux that allows you to handle side effects like data fetching and asynchronous actions in a more structured and testable way. It uses ES6 Generators to write asynchronous code that is easier to read and maintain.
Example:
npm install redux redux-saga
// actions.js
export const fetchUserRequest = () => ({
type: 'FETCH_USER_REQUEST',
});
export const fetchUserSuccess = (user) => ({
type: 'FETCH_USER_SUCCESS',
payload: user,
});
export const fetchUserFailure = (error) => ({
type: 'FETCH_USER_FAILURE',
payload: error,
});
// reducer.js
const initialState = {
user: {},
loading: false,
error: null,
};
const userReducer = (state = initialState, action) => {
switch (action.type) {
case 'FETCH_USER_REQUEST':
return { ...state, loading: true, error: null };
case 'FETCH_USER_SUCCESS':
return { ...state, user: action.payload, loading: false, error: null };
case 'FETCH_USER_FAILURE':
return { ...state, loading: false, error: action.payload };
default:
return state;
}
};
export default userReducer;
// saga.js
import { takeEvery, call, put } from 'redux-saga/effects';
import { fetchUserSuccess, fetchUserFailure } from './actions';
function* fetchUser() {
try {
// Simulating an API call
const response = yield call(fetch, 'https://api.example.com/user');
const user = yield call([response, 'json']);
yield put(fetchUserSuccess(user));
} catch (error) {
yield put(fetchUserFailure(error.message));
}
}
function* userSaga() {
yield takeEvery('FETCH_USER_REQUEST', fetchUser);
}
export default userSaga;
// store.js
import { createStore, applyMiddleware } from 'redux';
import createSagaMiddleware from 'redux-saga';
import userReducer from './reducer';
import userSaga from './saga';
const sagaMiddleware = createSagaMiddleware();
const store = createStore(userReducer, applyMiddleware(sagaMiddleware));
sagaMiddleware.run(userSaga);
export default store;
In this example, we have a simple Redux setup with actions, reducer, and a Saga. The Saga listens for 'FETCH_USER_REQUEST'
actions and performs an asynchronous API call. If the call is successful, it dispatches 'FETCH_USER_SUCCESS'
with the user data, or if there’s an error, it dispatches 'FETCH_USER_FAILURE'
with the error message.
32. Explain the concept of Middleware in Redux.
Middleware in Redux provides a way to intercept dispatched actions before they reach the reducer. It allows you to add additional functionality to Redux, such as logging, asynchronous actions, or other side effects.
Middleware is applied using applyMiddleware
from the Redux library. It sits between the dispatch
function and the reducer and can modify or handle actions as they flow through.
Each middleware receives the store
object and next
function as arguments. Middleware can choose to let the action pass to the next middleware using next(action)
or prevent it from reaching the reducer altogether.
Example of a simple logger middleware:
const loggerMiddleware = (store) => (next) => (action) => {
console.log('Action:', action);
const result = next(action);
console.log('New State:', store.getState());
return result;
};
// Usage in store.js
import { createStore, applyMiddleware } from 'redux';
import userReducer from './reducer';
import loggerMiddleware from './loggerMiddleware';
const store = createStore(userReducer, applyMiddleware(loggerMiddleware));
In this example, the loggerMiddleware
logs the action before it reaches the reducer and the new state after the reducer updates the state. You can add multiple middleware functions by passing them as arguments to applyMiddleware
.
33. What are the common performance issues in React, and how would you optimize them?
Common performance issues in React and their optimizations include:
- Unnecessary Re-renders: Optimize rendering by using
React.memo
orshouldComponentUpdate
to prevent re-renders of components when their props or state haven’t changed. - Excessive State Updates: Reduce state updates using
useReducer
or batch state updates withsetState
oruseState
functional updates. - Inefficient List Rendering: Use windowing libraries like
react-window
orreact-virtualized
for rendering large lists efficiently. - Large Component Trees: Split components into smaller, more manageable pieces using composition or React’s Context API.
- Inefficient DOM Manipulation: Use CSS classes for styling changes instead of direct DOM manipulation. Consider using libraries like
styled-components
for better performance. - Deep Nesting of Components: Avoid excessive nesting, as it can lead to reduced performance. Flatten component hierarchies where possible.
- Excessive Event Listeners: Remove or optimize event listeners to avoid unnecessary computations on each event trigger.
- Unoptimized Images: Compress and resize images to reduce their size and improve page load time.
34. How do you ensure component methods have the correct ‘this’ context in React?
In class components, to ensure that component methods have the correct this
context, you can bind the method in the constructor or use class properties syntax.
- Binding in the Constructor:
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0,
};
this.increment = this.increment.bind(this);
}
increment() {
// Now, 'this' refers to the component instance
this.setState((prevState) => ({ count: prevState.count + 1 }));
}
render() {
return (
<div>
<p>Count: {this.state.count}</p>
<button onClick={this.increment}>Increment</button>
</div>
);
}
}
- Class Properties Syntax (with Babel):
class MyComponent extends React.Component {
state = {
count: 0,
};
increment = () => {
// Now, 'this' refers to the component instance
this.setState((prevState) => ({ count: prevState.count + 1 }));
};
render() {
return (
<div>
<p>Count: {this.state.count}</p>
<button onClick={this.increment}>Increment</button>
</div>
);
}
}
In functional components, the this
context is not an issue because there are no instances involved. However, if you need to use a value or a function that depends on the component’s instance, you can use the useRef
hook to hold the reference to the component instance.
Example:
import React, { useRef } from 'react';
const MyComponent = () => {
const countRef = useRef(0);
const increment = () => {
countRef.current += 1;
console.log('Count:', countRef.current);
};
return (
<div>
<button onClick={increment}>Increment</button>
</div>
);
};
export default MyComponent;
In this example, we use useRef
to create a mutable reference countRef
, which holds the value of count
. The increment
function accesses and updates countRef.current
to maintain the state across renders.
35. What are the different ways to style a React component?
There are several ways to style a React component:
- Inline Styling: You can apply styles directly to a component using the
style
prop, which accepts an object with CSS properties.
const InlineStyledComponent = () => {
const styles = {
color: 'red',
fontSize: '18px',
fontWeight: 'bold',
};
return <div style={styles}>Inline Styled Component</div>;
};
- CSS Stylesheets: You can use traditional CSS stylesheets and import them into your component.
/* styles.css */
.container {
color: blue;
font-size: 20px;
}
import React from 'react';
import './styles.css';
const CSSStyledComponent = () => {
return <div className="container">CSS Styled Component</div>;
};
- CSS Modules: CSS Modules allow you to create local CSS classes specific to a component and avoid class name collisions.
/* styles.module.css */
.container {
color: green;
font-size: 24px;
}
import React from 'react';
import styles from './styles.module.css';
const CSSModuleStyledComponent = () => {
return <div className={styles.container}>CSS Module Styled Component</div>;
};
- CSS-in-JS Libraries: There are libraries like
styled-components
andemotion
that allow you to write CSS directly in your JavaScript code.
Using styled-components
:
npm install styled-components
import React from 'react';
import styled from 'styled-components';
const StyledComponent = styled.div`
color: purple;
font-size: 22px;
`;
const StyledComponentExample = () => {
return <StyledComponent>Styled Component Example</StyledComponent>;
};
MCQ Questions
1. What is React?
a) A JavaScript library for building user interfaces.
b) A programming language.
c) An operating system.
d) A database management system.
Answer: a) A JavaScript library for building user interfaces.
2. Who developed React?
a) Microsoft
b) Apple
c) Google
d) Facebook
Answer: d) Facebook
3. What is the virtual DOM in React?
a) A JavaScript framework.
b) A lightweight version of the DOM.
c) A concept used in server-side rendering.
d) A data structure that represents the actual DOM tree.
Answer: d) A data structure that represents the actual DOM tree.
4. What is JSX in React?
a) A programming language.
b) A templating engine.
c) A syntax extension for JavaScript.
d) A query language for databases.
Answer: c) A syntax extension for JavaScript.
5. What is the purpose of render() in React?
a) To define the initial state of a component.
b) To handle user events.
c) To update the UI based on the component’s state.
d) To perform asynchronous operations.
Answer: c) To update the UI based on the component’s state.
6. What are React components?
a) Functions that return HTML.
b) CSS stylesheets.
c) Data structures for storing component state.
d) Mathematical formulas.
Answer: a) Functions that return HTML.
7. What is state in React?
a) A CSS property for styling components.
b) A data structure for storing component-specific data.
c) An event triggered by user interactions.
d) A method for rendering components.
Answer: b) A data structure for storing component-specific data.
8. What is props in React?
a) A method for updating component state.
b) A data structure for passing data between components.
c) A virtual DOM representation of a component.
d) A styling technique for React components.
Answer: b) A data structure for passing data between components.
9. What is the purpose of keys in React lists?
a) To optimize rendering performance.
b) To uniquely identify elements in a list.
c) To define component lifecycle methods.
d) To handle user input in forms.
Answer: b) To uniquely identify elements in a list.
10. What is the significance of React’s componentDidMount() lifecycle method?
a) It is called before rendering a component.
b) It is called after a component has been updated.
c) It is called when a component is about to be removed from the DOM.
d) It is called when a component has been inserted into the DOM.
Answer: d) It is called when a component has been inserted into the DOM.
11. What is the purpose of React Router?
a) To handle asynchronous API requests.
b) To manage state in React components.
c) To navigate between different pages in a single-page application.
d) To optimize rendering performance.
Answer: c) To navigate between different pages in a single-page application.
12. What is Redux in React?
a) A server-side rendering framework.
b) A state management library.
c) A CSS-in-JS solution.
d) A database management system.
Answer: b) A state management library.
13. What is the purpose of React’s PureComponent?
a) To optimize rendering performance.
b) To handle user interactions.
c)To define component lifecycle methods.
d) To encapsulate CSS styles.
Answer: a) To optimize rendering performance.
14. What is the role of the shouldComponentUpdate() lifecycle method in React?
a) It is called before rendering a component.
b) It is called after a component has been updated.
c) It determines whether a component should re-render or not.
d) It handles errors that occur during rendering.
Answer: c) It determines whether a component should re-render or not.
15. What is the purpose of React’s useContext() hook?
a) To handle user authentication.
b) To manage component state.
c) To consume values from a React context.
d) To perform server-side rendering.
Answer: c) To consume values from a React context.
16. What is the significance of React’s useMemo() hook?
a) To optimize rendering performance.
b) To handle user interactions.
c) To define component lifecycle methods.
d) To perform asynchronous operations.
Answer: a) To optimize rendering performance.
17. What is the purpose of React’s useCallback() hook?
a) To handle user events.
b) To define component lifecycle methods.
c) To memoize functions and optimize performance.
d) To perform server-side rendering.
Answer: c) To memoize functions and optimize performance.
18. What is the role of React’s useRef() hook?
a) To manage component state.
b) To handle user events.
c) To create references to DOM elements.
d) To perform server-side rendering.
Answer: c) To create references to DOM elements.
19. What is the purpose of React’s useReducer() hook?
a) To manage component state.
b) To handle user authentication.
c) To optimize rendering performance.
d) To perform asynchronous operations.
Answer: a) To manage component state.
20. What is the concept of React Fragments?
a) A feature for creating reusable components.
b) A syntax for defining inline styles in React components.
c) A way to render multiple elements without using a wrapper element.
d) A technique for server-side rendering in React.
Answer: c) A way to render multiple elements without using a wrapper element.
21. What is the purpose of React’s useEffect() hook?
a) To handle user interactions.
b) To define component lifecycle methods.
c) To perform server-side rendering.
d) To manage side effects in functional components.
Answer: d) To manage side effects in functional components.
22. What is the concept of React Context?
a) A state management solution in React.
b) A mechanism for sharing data between components without passing props.
c) A library for handling form validation in React.
d) A tool for optimizing rendering performance in React applications.
Answer: b) A mechanism for sharing data between components without passing props.
23. What is the role of React’s useState() hook?
a) To handle user authentication.
b) To manage component state in functional components.
c) To define component lifecycle methods.
d) To perform server-side rendering.
Answer: b) To manage component state in functional components.
24. What is the purpose of React’s forwardRef() function?
a) To optimize rendering performance in React applications.
b) To create reusable higher-order components.
c) To pass refs to child components in React.
d) To handle asynchronous operations in React.
Answer: c) To pass refs to child components in React.
25. What is the role of React’s useContext() hook?
a) To handle user authentication.
b) To manage component state.
c) To consume values from a React context.
d) To perform server-side rendering.
Answer: c) To consume values from a React context
26. What is the significance of React’s memo() function?
a) To optimize rendering performance in React applications.
b) To create reusable higher-order components.
c) To handle user interactions.
d) To perform server-side rendering.
Answer: a) To optimize rendering performance in React applications.
27. What is the concept of React Router?
a) A state management library in React.
b) A mechanism for handling user interactions in React.
c) A library for handling routing and navigation in React applications.
d) A tool for optimizing rendering performance in React.
Answer: c) A library for handling routing and navigation in React applications
28. What is the purpose of React’s useReducer() hook?
a) To manage component state.
b) To handle user authentication.
c) To optimize rendering performance.
d) To perform asynchronous operations.
Answer: a) To manage component state.
29. What is the role of React’s useCallback() hook?
a) To handle user events.
b) To define component lifecycle methods.
c) To memoize functions and optimize performance.
d) To perform server-side rendering.
Answer: c) To memoize functions and optimize performance.
30. What is the concept of React Fragments?
a) A feature for creating reusable components.
b) A syntax for defining inline styles in React components.
c) A way to render multiple elements without using a wrapper element.
d) A technique for server-side rendering in React.
c) A way to render multiple elements without using a wrapper element.