1. What are React Hooks and how do they work?
Answer: React Hooks are functions that let you use state and other React features without writing a class. They were introduced in React 16.8.
Example:
import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
2. Explain the useEffect Hook and its usage.
Answer: The useEffect
Hook lets you perform side effects in function components. It serves the same purpose as componentDidMount
, componentDidUpdate
, and componentWillUnmount
in React classes.
Example:
import React, { useEffect } from 'react';
function Example() {
useEffect(() => {
console.log('Component did mount');
return () => {
console.log('Component will unmount');
};
}, []);
return <div>Check the console logs</div>;
}
3. How do you optimize performance in a large React application?
Answer: Performance optimization in React can be achieved through various techniques such as memoization, code splitting, lazy loading, and avoiding unnecessary re-renders using React.memo
and useCallback
.
Example:
import React, { useState, useCallback } from 'react';
const ExpensiveComponent = React.memo(({ compute }) => {
console.log('Expensive component rendered');
return <div>Result: {compute()}</div>;
});
function App() {
const [count, setCount] = useState(0);
const compute = useCallback(() => {
return count * 2;
}, [count]);
return (
<div>
<ExpensiveComponent compute={compute} />
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
4. What is the Context API and how is it used?
Answer: The Context API allows you to pass data through the component tree without having to pass props down manually at every level.
Example:
import React, { createContext, useContext } from 'react';
const MyContext = createContext();
function ComponentA() {
return (
<MyContext.Provider value="Hello, World!">
<ComponentB />
</MyContext.Provider>
);
}
function ComponentB() {
return <ComponentC />;
}
function ComponentC() {
const value = useContext(MyContext);
return <div>{value}</div>;
}
5. Describe the useReducer Hook and its benefits.
Answer: The useReducer
Hook is used for state management in React when you have complex state logic that involves multiple sub-values or when the next state depends on the previous one.
Example:
import React, { useReducer } from 'react';
const initialState = { count: 0 };
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
</div>
);
}
6. How can you handle forms in React?
Answer: Handling forms in React involves using controlled components where form data is handled by the component’s state.
Example:
import React, { useState } from 'react';
function MyForm() {
const [name, setName] = useState('');
const handleSubmit = (event) => {
event.preventDefault();
alert(`Form submitted with name: ${name}`);
};
return (
<form onSubmit={handleSubmit}>
<label>
Name:
<input type="text" value={name} onChange={(e) => setName(e.target.value)} />
</label>
<button type="submit">Submit</button>
</form>
);
}
7. What is the difference between controlled and uncontrolled components?
Answer: Controlled components are those where form data is handled by the component’s state, whereas uncontrolled components rely on the DOM to handle form data.
Example (Controlled):
import React, { useState } from 'react';
function ControlledComponent() {
const [value, setValue] = useState('');
return (
<input type="text" value={value} onChange={(e) => setValue(e.target.value)} />
);
}
Example (Uncontrolled):
import React, { useRef } from 'react';
function UncontrolledComponent() {
const inputRef = useRef();
const handleClick = () => {
alert(`Input value: ${inputRef.current.value}`);
};
return (
<div>
<input type="text" ref={inputRef} />
<button onClick={handleClick}>Alert Input Value</button>
</div>
);
}
8. Explain the concept of Higher-Order Components (HOC).
Answer: A Higher-Order Component (HOC) is a function that takes a component and returns a new component, enhancing the original component with additional props or behavior.
Example:
import React from 'react';
function withLogger(WrappedComponent) {
return function EnhancedComponent(props) {
console.log('Rendering', WrappedComponent.name);
return <WrappedComponent {...props} />;
};
}
function MyComponent() {
return <div>My Component</div>;
}
const MyComponentWithLogger = withLogger(MyComponent);
9. What is React Suspense and how does it work?
Answer: React Suspense is a feature for managing asynchronous operations in a declarative way. It allows you to specify the loading state of part of your component tree.
Example:
import React, { Suspense } from 'react';
const LazyComponent = React.lazy(() => import('./LazyComponent'));
function MyComponent() {
return (
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
);
}
10. How do you manage side effects in a functional component?
Answer: Side effects in a functional component are managed using the useEffect
Hook. This Hook allows you to perform actions like data fetching, subscriptions, and manual DOM manipulations after the component renders.
Example:
import React, { useEffect, useState } from 'react';
function DataFetcher() {
const [data, setData] = useState(null);
useEffect(() => {
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => setData(data));
}, []);
return (
<div>
{data ? <div>Data: {JSON.stringify(data)}</div> : <div>Loading...</div>}
</div>
);
}
11. Explain the purpose and usage of React.memo.
Answer: React.memo
is a higher-order component that memoizes the rendered output of a function component. It helps to optimize performance by preventing unnecessary re-renders if the props have not changed.
Example:
import React from 'react';
const MyComponent = React.memo(({ name }) => {
console.log('Rendering MyComponent');
return <div>{name}</div>;
});
function App() {
const [name, setName] = useState('John');
return (
<div>
<MyComponent name={name} />
<button onClick={() => setName('John')}>Set Name to John</button>
</div>
);
}
12. What is the difference between useState and useReducer?
Answer: useState
is suitable for simple state management, while useReducer
is preferable for complex state logic that involves multiple sub-values or when the next state depends on the previous one.
Example (useState):
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
Example (useReducer):
import React, { useReducer } from 'react';
const initialState = { count: 0 };
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
</div>
);
}
13. How do you handle error boundaries in React?
Answer: Error boundaries are React components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI.
Example:
import React, { Component } from 'react';
class ErrorBoundary extends Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
console.error("Error caught:", error, errorInfo);
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
function MyComponent() {
throw new Error("I crashed!");
return <div>My Component</div>;
}
function App() {
return (
<ErrorBoundary>
<MyComponent />
</ErrorBoundary>
);
}
14. What are render props in React?
Answer: Render props are a technique for sharing code between React components using a prop whose value is a function. A component with a render prop takes a function that returns a React element and calls it instead of implementing its own render logic.
Example:
import React, { Component } from 'react';
class Mouse extends Component {
constructor(props) {
super(props);
this.state = { x: 0, y: 0 };
}
handleMouseMove = (event) => {
this.setState({
x: event.clientX,
y: event.clientY
});
};
render() {
return (
<div style={{ height: '100vh' }} onMouseMove={this.handleMouseMove}>
{this.props.render(this.state)}
</div>
);
}
}
function App() {
return (
<Mouse render={({ x, y }) => (
<h1>The mouse position is ({x}, {y})</h1>
)} />
);
}
15. How can you achieve code splitting in a React application?
Answer: Code splitting in a React application can be achieved using dynamic import()
and React’s React.lazy
for lazy loading components. This helps in reducing the initial load time of the application.
Example:
import React, { Suspense } from 'react';
const LazyComponent = React.lazy(() => import('./LazyComponent'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
);
}
16. Explain the significance of keys in React lists.
Answer: Keys help React identify which items have changed, are added, or are removed. They should be given to the elements inside the array to give the elements a stable identity.
Example:
import React from 'react';
function List({ items }) {
return (
<ul>
{items.map(item => (
<li key={item.id}>{item.text}</li>
))}
</ul>
);
}
17. What is the useLayoutEffect Hook and how does it differ from useEffect?
Answer: useLayoutEffect
fires synchronously after all DOM mutations. You can use it to read layout from the DOM and synchronously re-render. It’s similar to useEffect
, but it fires before the browser repaints the screen.
Example:
import React, { useLayoutEffect, useRef } from 'react';
function LayoutEffectComponent() {
const divRef = useRef();
useLayoutEffect(() => {
console.log('useLayoutEffect: Div width is', divRef.current.offsetWidth);
});
return <div ref={divRef}>Check console for layout effect</div>;
}
18. How do you create a custom hook in React?
Answer: A custom hook is a function that starts with “use” and may call other hooks inside it. It allows you to extract component logic into reusable functions.
Example:
import { useState, useEffect } from 'react';
function useWindowWidth() {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
const handleResize = () => setWidth(window.innerWidth);
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
}, []);
return width;
}
function App() {
const width = useWindowWidth();
return <div>Window width: {width}</div>;
}
19. Explain the use of the forwardRef
function.
Answer: forwardRef
is a React function that allows you to forward refs to child components. It’s used to pass refs through component layers.
Example:
import React, { forwardRef } from 'react';
const FancyButton = forwardRef((props, ref) => (
<button ref={ref} className="fancy-button">
{props.children}
</button>
));
function App() {
const buttonRef = React.createRef();
return (
<FancyButton ref={buttonRef}>Click me!</FancyButton>
);
}
20. How do you handle asynchronous data fetching in React with hooks?
Answer: Asynchronous data fetching in React can be handled using the useEffect
hook along with async functions.
Example:
import React, { useState, useEffect } from 'react';
function DataFetcher() {
const [data, setData] = useState(null);
useEffect(() => {
async function fetchData() {
const response = await fetch('https://api.example.com/data');
const result = await response.json();
setData(result);
}
fetchData();
}, []);
return (
<div>
{data ? <div>Data: {JSON.stringify(data)}</div> : <div>Loading...</div>}
</div>
);
}
Let me know if you need more batches!