React Interview Questions
1.What is React and why is it used?
React is a JavaScript library for building user interfaces with reusable components.
Key Benefits:
- Component-Based: Build encapsulated components that manage their own state
- Declarative: Design simple views for each state in your application
- Learn Once, Write Anywhere: Develop new features without rewriting existing code
- Virtual DOM: React uses Virtual DOM for efficient rendering
- Unidirectional Data Flow: Easier to debug and understand data changes
- Large Community: Extensive resources and third-party libraries
Use Cases:
- Single Page Applications (SPAs)
- Real-time applications
- Progressive Web Apps (PWAs)
- Mobile applications (React Native)
Example:
function App() {
return <h1>Hello, React!</h1>;
}
2.What is JSX and how does it work?
JSX is a syntax extension to JavaScript that looks similar to HTML. It produces React "elements".
Basic Syntax:
const element = <h1>Hello, World!</h1>;
How It Works: JSX is not valid JavaScript. It must be compiled to JavaScript function calls:
// JSX
const element = <h1 className="greeting">Hello!</h1>;
// Compiled to:
const element = React.createElement(
'h1',
{ className: 'greeting' },
'Hello!'
);
Rules:
- Single root element
- Use className instead of class
- Attributes are camelCase (onClick, onChange)
- Self-closing tags must end with />
- Use {} for JavaScript expressions
Example:
const name = 'John';
const element = <h1>Hello, {name}!</h1>;
3.What are components in React?
Components are reusable pieces of UI that return JSX elements.
Two Types of Components:
1. Functional Components (Recommended):
function Welcome() {
return <h1>Hello, World!</h1>;
}
2. Class Components (Legacy):
class Welcome extends React.Component {
render() {
return <h1>Hello, World!</h1>;
}
}
Key Points:
- Component names must start with capital letter
- Return a single root JSX element
- Accept props as input
- Are reusable and composable
- Should be pure functions (same input = same output)
Example: Reusable Component
function Greeting({ name }) {
return <h1>Hello, {name}!</h1>;
}
// Usage
<Greeting name="Alice" />
<Greeting name="Bob" />
4.What are props in React?
Props are arguments passed into React components, similar to function parameters.
Key Characteristics:
- Read-only (immutable)
- Pass data from parent to child
- Can be any data type (string, number, object, function)
- Default props can be provided
Example:
function Welcome({ name, age }) {
return <p>I am {name}, {age} years old</p>;
}
// Usage
<Welcome name="John" age={25} />
Props with Children:
function Card({ children }) {
return <div className="card">{children}</div>;
}
// Usage
<Card>
<h1>Card Title</h1>
<p>Card content</p>
</Card>
Default Props:
function Greeting({ name = 'Guest' }) {
return <p>Hello, {name}!</p>;
}
Props Destructuring:
// Instead of: function MyComponent(props) { props.name }
// Use: function MyComponent({ name }) { name }
5.What is state in React and how is it different from props?
State is data that changes over time, managed within a component. Props are passed from parent.
Differences:
| Feature | State | Props |
|---|---|---|
| Mutability | Mutable (can change) | Immutable (read-only) |
| Scope | Local to component | Parent to child |
| Modification | setState or setVariable | Pass from parent |
| Triggers re-render | Yes | Yes |
| Purpose | Internal data | External data |
Example: State vs Props
function Counter() {
// State - local data
const [count, setCount] = React.useState(0);
return (
<>
<p>Count: {count}</p>
{/* Props - pass to child */}
<Button count={count} onClick={() => setCount(count + 1)} />
</>
);
}
function Button({ count, onClick }) {
// count is a prop (read-only)
return <button onClick={onClick}>Increment ({count})</button>;
}
When to Use:
- State: Component's internal data (user input, toggles, counters)
- Props: Data from parent, configuration, callbacks
6.What is the useState hook?
useState is a React hook that lets you add state to functional components.
Syntax:
const [state, setState] = useState(initialValue);
Parameters:
initialValue: The initial state value
Returns:
state: Current state valuesetState: Function to update state
Example: Simple Counter
function Counter() {
const [count, setCount] = useState(0);
return (
<>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</>
);
}
Multiple State Variables:
function Form() {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [age, setAge] = useState(0);
return (
<>
<input value={name} onChange={(e) => setName(e.target.value)} />
<input value={email} onChange={(e) => setEmail(e.target.value)} />
</>
);
}
Updating State:
// Direct value
setCount(5);
// Using previous state (recommended for dependent updates)
setCount(prevCount => prevCount + 1);
7.What is the useEffect hook?
useEffect is a React hook that runs side effects (like data fetching, subscriptions) in functional components.
Syntax:
useEffect(() => {
// Side effect code
}, [dependencies]);
Basic Example:
function Component() {
const [data, setData] = useState(null);
useEffect(() => {
// This runs after component renders
fetch('/api/data')
.then(res => res.json())
.then(data => setData(data));
}, []); // Empty dependency array = run once on mount
return <div>{data}</div>;
}
Dependency Array:
// No dependency array - runs after every render
useEffect(() => { console.log('Rendered'); });
// Empty array - runs once on mount
useEffect(() => { console.log('Mounted'); }, []);
// With dependencies - runs when dependencies change
useEffect(() => { console.log('Count:', count); }, [count]);
Cleanup Function (Unmount/Before re-run):
useEffect(() => {
const timer = setInterval(() => console.log('tick'), 1000);
// Cleanup function
return () => clearInterval(timer);
}, []);
Common Use Cases:
- Fetching data
- Setting up subscriptions
- Updating document title
- Cleaning up resources
8.How do you handle events in React?
React handles events through synthetic events with camelCase names.
Event Handling:
function Button() {
const handleClick = () => {
console.log('Button clicked!');
};
return <button onClick={handleClick}>Click Me</button>;
}
With Parameters:
function List() {
const handleDelete = (id) => {
console.log('Delete item:', id);
};
return (
<button onClick={() => handleDelete(123)}>
Delete
</button>
);
}
Common Events:
onClick: Mouse clickonChange: Input/select changeonSubmit: Form submissiononMouseEnter: Mouse entersonFocus: Element focusedonKeyDown: Keyboard key pressed
Form Input Example:
function Form() {
const [email, setEmail] = useState('');
return (
<input
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Enter email"
/>
);
}
Preventing Default Behavior:
function Form() {
const handleSubmit = (e) => {
e.preventDefault();
console.log('Form submitted');
};
return <form onSubmit={handleSubmit}><button>Submit</button></form>;
}
9.What is conditional rendering in React?
Conditional rendering allows you to render different content based on conditions.
Method 1: If-Else Statement:
function Greeting({ isLoggedIn }) {
if (isLoggedIn) {
return <h1>Welcome back!</h1>;
}
return <h1>Please sign in</h1>;
}
Method 2: Ternary Operator:
function Greeting({ isLoggedIn }) {
return isLoggedIn ? <h1>Welcome!</h1> : <h1>Sign in</h1>;
}
Method 3: Logical AND (&&):
function Notification({ unreadCount }) {
return (
<>
{unreadCount > 0 && <div>You have {unreadCount} unread messages</div>}
</>
);
}
Method 4: Switch Statement:
function Status({ status }) {
switch(status) {
case 'loading':
return <div>Loading...</div>;
case 'error':
return <div>Error!</div>;
case 'success':
return <div>Success!</div>;
default:
return <div>Unknown</div>;
}
}
Best Practices:
- Keep conditions simple
- Extract complex conditions to variables
- Avoid rendering null in ternary operators
10.How do you render lists in React?
Lists are rendered using the .map() function with a key prop for each item.
Basic Example:
function FruitList() {
const fruits = ['Apple', 'Banana', 'Orange'];
return (
<ul>
{fruits.map((fruit, index) => (
<li key={index}>{fruit}</li>
))}
</ul>
);
}
With Objects:
function UserList() {
const users = [
{ id: 1, name: 'John' },
{ id: 2, name: 'Jane' },
{ id: 3, name: 'Bob' }
];
return (
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
Important: The Key Prop
- Always use a unique identifier as key
- Don't use index as key (unless list is static)
- Key helps React identify which items changed
// ✓ Good: Unique ID
{items.map(item => <li key={item.id}>{item.name}</li>)}
// ✗ Bad: Index as key
{items.map((item, index) => <li key={index}>{item.name}</li>)}
Filter and Map:
const adults = users.filter(u => u.age >= 18).map(u => (
<div key={u.id}>{u.name}</div>
));
11.What is the difference between controlled and uncontrolled components?
Controlled components have their state managed by React, uncontrolled let the DOM manage state.
Controlled Component:
function ControlledInput() {
const [value, setValue] = useState('');
return (
<input
value={value}
onChange={(e) => setValue(e.target.value)}
/>
);
}
Benefits:
- Easy validation
- Instant feedback
- Can modify value programmatically
- Single source of truth
Uncontrolled Component:
function UncontrolledInput() {
const inputRef = useRef();
const handleSubmit = () => {
console.log(inputRef.current.value);
};
return (
<>
<input ref={inputRef} />
<button onClick={handleSubmit}>Submit</button>
</>
);
}
Benefits:
- Simpler code
- Works with non-React code
- Faster typing (no re-renders)
When to Use:
- Controlled: Complex forms, validation, conditional logic
- Uncontrolled: File inputs, integration with jQuery, simple forms
12.What are keys in lists and why are they important?
Keys help React identify which items have changed, been added, or removed.
Why Keys Matter:
- Preserve component state: Without keys, state gets mixed up
- Maintain focus: Input focus is preserved correctly
- Performance: React can reuse DOM nodes
Problem Without Keys:
// ❌ No keys - items shuffle
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
// If item removed, indices change and state gets confused
Solution With Unique Keys:
// ✓ Unique ID as key
{items.map(item => (
<li key={item.id}>{item.name}</li>
))}
Example: Importance of Keys
function TodoList() {
const [todos, setTodos] = useState([
{ id: 1, text: 'Learn React' },
{ id: 2, text: 'Build project' }
]);
// ✓ Correct: Use unique ID
return todos.map(todo => (
<TodoItem key={todo.id} todo={todo} />
));
}
Key Guidelines:
- Use stable, unique identifiers (database IDs)
- Don't use array index as key
- Keys only need to be unique among siblings
13.How do you pass data between components?
Data flows from parent to child via props, child to parent via callbacks.
Parent to Child (Props):
function Parent() {
return <Child name="John" age={25} />;
}
function Child({ name, age }) {
return <p>{name} is {age} years old</p>;
}
Child to Parent (Callbacks):
function Parent() {
const [count, setCount] = useState(0);
return <Child count={count} onIncrement={() => setCount(count + 1)} />;
}
function Child({ count, onIncrement }) {
return (
<>
<p>Count: {count}</p>
<button onClick={onIncrement}>Increment</button>
</>
);
}
Multiple Levels (Prop Drilling):
function GrandParent() {
const [theme, setTheme] = useState('light');
return <Parent theme={theme} />;
}
function Parent({ theme }) {
return <Child theme={theme} />;
}
function Child({ theme }) {
return <div style={{ background: theme }}>Content</div>;
}
Problem: Prop Drilling Passing props through many levels becomes cumbersome. Solution: Use Context API (advanced).
14.What are React fragments and when do you use them?
Fragments allow you to group multiple elements without adding extra DOM nodes.
Problem:
// ❌ Extra wrapper div
function Component() {
return (
<div>
<h1>Title</h1>
<p>Content</p>
</div>
);
}
Solution with Fragment:
// ✓ No wrapper div
function Component() {
return (
<>
<h1>Title</h1>
<p>Content</p>
</>
);
}
Long Form (Rarely needed):
function Component() {
return (
<React.Fragment>
<h1>Title</h1>
<p>Content</p>
</React.Fragment>
);
}
Use Cases:
- Avoiding wrapper divs: Cleaner HTML
- Lists of fragments:
function List() {
return (
{items.map(item => (
<React.Fragment key={item.id}>
<h2>{item.title}</h2>
<p>{item.description}</p>
</React.Fragment>
))}
);
}
Benefits:
- Cleaner HTML output
- Prevents CSS issues (flexbox, grid)
- Better semantics
15.What are React hooks?
Hooks are functions that let you use state and other React features in functional components.
What They Enable:
- Use state in functional components
- Use lifecycle methods in functional components
- Share logic between components
- Organize component logic
Common Hooks:
1. useState - Manage state
const [count, setCount] = useState(0);
2. useEffect - Side effects
useEffect(() => {
// Code runs after render
}, [dependencies]);
3. useContext - Access context
const theme = useContext(ThemeContext);
4. useRef - Access DOM directly
const inputRef = useRef();
Rules of Hooks:
- Only call hooks at the top level
- Don't call hooks inside loops, conditions, or nested functions
- Only call hooks from React components or custom hooks
Correct:
function Component() {
const [state, setState] = useState(0); // Top level
return <div>{state}</div>;
}
Wrong:
function Component() {
if (condition) {
const [state, setState] = useState(0); // ❌ Inside condition
}
}
16.What is the useRef hook?
useRef is a hook that allows you to create a persistent reference to a DOM element or value.
Syntax:
const ref = useRef(initialValue);
Accessing DOM Element:
function TextInput() {
const inputRef = useRef();
const handleClick = () => {
inputRef.current.focus();
};
return (
<>
<input ref={inputRef} />
<button onClick={handleClick}>Focus Input</button>
</>
);
}
Storing Mutable Values:
function Timer() {
const intervalRef = useRef();
const handleStart = () => {
intervalRef.current = setInterval(() => {
console.log('tick');
}, 1000);
};
const handleStop = () => {
clearInterval(intervalRef.current);
};
return (
<>
<button onClick={handleStart}>Start</button>
<button onClick={handleStop}>Stop</button>
</>
);
}
Key Points:
- useRef returns the same object every render
- Mutating ref.current doesn't cause re-render
- Don't use refs for things that can be declarative
Use Cases:
- Managing focus, text selection
- Triggering animations
- Integrating with third-party DOM libraries
17.How do you handle forms in React?
React provides controlled components for form handling with automatic state updates.
Simple Form:
function LoginForm() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
console.log('Email:', email, 'Password:', password);
};
return (
<form onSubmit={handleSubmit}>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Email"
/>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Password"
/>
<button type="submit">Login</button>
</form>
);
}
Select and Textarea:
function Form() {
const [country, setCountry] = useState('');
const [message, setMessage] = useState('');
return (
<>
<select value={country} onChange={(e) => setCountry(e.target.value)}>
<option value="">Select country</option>
<option value="usa">USA</option>
<option value="uk">UK</option>
</select>
<textarea
value={message}
onChange={(e) => setMessage(e.target.value)}
/>
</>
);
}
Checkbox:
function Checkbox() {
const [agree, setAgree] = useState(false);
return (
<label>
<input
type="checkbox"
checked={agree}
onChange={(e) => setAgree(e.target.checked)}
/>
I agree to terms
</label>
);
}
18.What is the component lifecycle?
The lifecycle describes the sequence of events from component creation to destruction.
Functional Components (with Hooks):
Mount (Component created and inserted to DOM):
useEffect(() => {
console.log('Component mounted');
return () => {
console.log('Component unmounting');
};
}, []); // Empty dependency = run once on mount
Update (Component re-renders due to props/state change):
useEffect(() => {
console.log('Component updated (count changed)');
return () => {
console.log('Cleanup before next effect');
};
}, [count]); // Dependency = run when count changes
Unmount (Component removed from DOM):
useEffect(() => {
return () => {
console.log('Component unmounted');
};
}, []);
Lifecycle Flow:
1. Mount → useEffect with [] dependency
2. Update → useEffect with [dependencies]
3. Unmount → Return function from useEffect
Complete Example:
function Component() {
const [count, setCount] = useState(0);
// Runs once on mount
useEffect(() => {
console.log('Mounted');
return () => console.log('Unmounting');
}, []);
// Runs when count changes
useEffect(() => {
console.log('Count updated to:', count);
}, [count]);
return <button onClick={() => setCount(count + 1)}>Count: {count}</button>;
}
19.What is React.memo and when should you use it?
React.memo is a higher-order component that memoizes components to prevent unnecessary re-renders.
Basic Usage:
const MyComponent = React.memo(function MyComponent({ name }) {
return <div>Hello, {name}</div>;
});
// Component only re-renders if 'name' prop changes
Without Memo (Re-renders every time parent renders):
function Parent() {
const [count, setCount] = useState(0);
return (
<>
<button onClick={() => setCount(count + 1)}>Count: {count}</button>
<Child name="John" /> {/* Re-renders even though name didn't change */}
</>
);
}
function Child({ name }) {
return <p>Hello, {name}</p>;
}
With Memo (Only re-renders if props change):
const Child = React.memo(function Child({ name }) {
return <p>Hello, {name}</p>;
});
Custom Comparison:
const MyComponent = React.memo(
function MyComponent({ name, age }) {
return <div>{name}, {age}</div>;
},
(prevProps, nextProps) => {
// Return true if props are equal (skip re-render)
// Return false if props changed (re-render)
return prevProps.name === nextProps.name;
}
);
When to Use:
- Expensive components (complex calculations)
- Large lists of items
- Components with large prop objects
20.What is Context API and how do you use it?
Context API allows you to share data between components without passing props down every level.
Basic Setup:
// Create context
const ThemeContext = React.createContext();
// Provider component
function App() {
const [theme, setTheme] = useState('light');
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
<Header />
<Main />
<Footer />
</ThemeContext.Provider>
);
}
// Consume context anywhere
function Header() {
const { theme, setTheme } = useContext(ThemeContext);
return (
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
Current theme: {theme}
</button>
);
}
Use Cases:
- Theme (light/dark mode)
- User authentication
- Language/Localization
- Global UI state
Avoiding Prop Drilling:
// Without Context (prop drilling)
<GrandParent theme={theme}>
<Parent theme={theme}>
<Child theme={theme} />
</Parent>
</GrandParent>
// With Context
<ThemeContext.Provider value={theme}>
<GrandParent>
<Parent>
<Child /> {/* Accesses theme via useContext */}
</Parent>
</GrandParent>
</ThemeContext.Provider>
21.What is prop drilling and how do you solve it?
Prop drilling is passing props through many levels of components that don't use them.
The Problem:
function GrandParent() {
const user = { name: 'John' };
return <Parent user={user} />; // Parent doesn't need user
}
function Parent({ user }) {
return <Child user={user} />; // Child doesn't need user
}
function Child({ user }) {
return <p>{user.name}</p>; // Only Child uses user
}
Solution 1: Context API
const UserContext = React.createContext();
function GrandParent() {
const user = { name: 'John' };
return (
<UserContext.Provider value={user}>
<Parent />
</UserContext.Provider>
);
}
function Parent() {
return <Child />;
}
function Child() {
const user = useContext(UserContext);
return <p>{user.name}</p>;
}
Solution 2: Composition
function Parent({ children }) {
return <div>{children}</div>;
}
function GrandParent() {
const user = { name: 'John' };
return <Parent><Child user={user} /></Parent>;
}
Solution 3: State Management Library
- Redux
- Zustand
- Jotai
When to Use Each:
- Context: Global state (theme, auth, language)
- Props: Direct parent-child communication
- Redux: Large applications with complex state
22.What is a custom hook?
A custom hook is a JavaScript function that uses React hooks and can be reused across components.
Rules:
- Name must start with 'use'
- Can call other hooks
- Can be called only from components or other hooks
Example: useCounter Hook
function useCounter(initialValue = 0) {
const [count, setCount] = useState(initialValue);
const increment = () => setCount(count + 1);
const decrement = () => setCount(count - 1);
const reset = () => setCount(initialValue);
return { count, increment, decrement, reset };
}
// Usage
function Counter() {
const { count, increment, decrement } = useCounter(0);
return (
<>
<p>Count: {count}</p>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
</>
);
}
Example: useFetch Hook
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetch(url)
.then(res => res.json())
.then(data => { setData(data); setLoading(false); })
.catch(err => { setError(err); setLoading(false); });
}, [url]);
return { data, loading, error };
}
// Usage
function App() {
const { data, loading } = useFetch('/api/users');
if (loading) return <p>Loading...</p>;
return <div>{JSON.stringify(data)}</div>;
}
Benefits:
- Code reuse
- Cleaner components
- Easier to test
- Shareable logic
23.How do you optimize React applications?
Optimization techniques to improve React app performance.
1. Code Splitting with React.lazy()
const HeavyComponent = React.lazy(() => import('./HeavyComponent'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<HeavyComponent />
</Suspense>
);
}
2. Use React.memo for expensive components
const UserCard = React.memo(({ user }) => {
return <div>{user.name}</div>;
});
3. Use useCallback to memoize functions
const handleClick = useCallback(() => {
doSomething();
}, []);
4. Use useMemo for expensive calculations
const expensiveValue = useMemo(() => {
return complexCalculation(data);
}, [data]);
5. Proper key usage in lists
{items.map(item => <Item key={item.id} item={item} />)}
6. Virtual scrolling for long lists
import { FixedSizeList } from 'react-window';
7. Image optimization
- Use compressed images
- Lazy load images below the fold
- Use modern formats (WebP)
8. Bundle analysis
- Check bundle size
- Remove unused dependencies
- Tree shake imports
24.What are PropTypes and how do you use them?
PropTypes is a library for type-checking props in React components.
Installation:
npm install prop-types
Basic Usage:
import PropTypes from 'prop-types';
function Greeting({ name, age }) {
return <p>{name} is {age} years old</p>;
}
Greeting.propTypes = {
name: PropTypes.string.isRequired,
age: PropTypes.number.isRequired
};
Common PropTypes:
Component.propTypes = {
string: PropTypes.string,
number: PropTypes.number,
boolean: PropTypes.bool,
array: PropTypes.array,
object: PropTypes.object,
function: PropTypes.func,
node: PropTypes.node, // Anything renderable
element: PropTypes.element, // JSX element
// Required
requiredString: PropTypes.string.isRequired,
// One of several values
status: PropTypes.oneOf(['active', 'inactive', 'pending']),
// Array of specific type
ids: PropTypes.arrayOf(PropTypes.number),
// Object with specific shape
user: PropTypes.shape({
name: PropTypes.string,
age: PropTypes.number
}),
// Custom validator
customProp: function(props, propName, componentName) {
if (!/matchme/.test(props[propName])) {
return new Error('Validation failed');
}
}
};
Note: PropTypes only check in development. For production type-checking, use TypeScript.
25.What is React Router and how do you use it?
React Router is a library for routing and navigation in single-page applications.
Installation:
npm install react-router-dom
Basic Setup:
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
<Link to="/users/john">John's Profile</Link>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/users/:name" element={<Profile />} />
</Routes>
</BrowserRouter>
);
}
Using Route Parameters:
import { useParams } from 'react-router-dom';
function Profile() {
const { name } = useParams();
return <h1>Profile of {name}</h1>;
}
Navigation Programmatically:
import { useNavigate } from 'react-router-dom';
function LoginButton() {
const navigate = useNavigate();
const handleLogin = () => {
navigate('/dashboard');
};
return <button onClick={handleLogin}>Login</button>;
}
Nested Routes:
<Routes>
<Route path="/profile" element={<Profile />}>
<Route path="overview" element={<Overview />} />
<Route path="settings" element={<Settings />} />
</Route>
</Routes>
26.What is the difference between useEffect and useLayoutEffect?
Both hooks run side effects, but at different times in the render cycle.
Execution Timing:
useEffect:
1. Component renders
2. Browser paints to screen
3. useEffect runs (async)
useLayoutEffect:
1. Component renders
2. useLayoutEffect runs (sync) ← blocks painting
3. Browser paints to screen
useEffect (Recommended for most cases):
useEffect(() => {
console.log('Runs after render');
// Good for: data fetching, subscriptions, etc.
}, []);
useLayoutEffect (Use sparingly):
useLayoutEffect(() => {
console.log('Runs before paint');
// Good for: measuring DOM, calculating positions
}, []);
Example: Measuring DOM with useLayoutEffect
function Tooltip() {
const [position, setPosition] = useState(null);
const ref = useRef();
useLayoutEffect(() => {
if (ref.current) {
const rect = ref.current.getBoundingClientRect();
setPosition(rect);
}
}, []);
return <div ref={ref} style={position}>Tooltip</div>;
}
When to Use:
- useEffect (99% of cases): Data fetching, subscriptions, timers
- useLayoutEffect (rare): DOM measurements, positioning, animations
27.How do you handle errors in React?
Error handling techniques in React applications.
1. Try-Catch for Synchronous Code:
function Component() {
try {
const result = riskyOperation();
return <div>{result}</div>;
} catch (error) {
return <div>Error: {error.message}</div>;
}
}
2. Error Boundaries for Component Errors:
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
console.log(error, errorInfo);
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong</h1>;
}
return this.props.children;
}
}
// Usage
<ErrorBoundary>
<MyComponent />
</ErrorBoundary>
3. Handling Async Errors:
function Component() {
const [error, setError] = useState(null);
useEffect(() => {
fetch('/api/data')
.catch(err => setError(err));
}, []);
if (error) return <div>Error: {error.message}</div>;
return <div>Content</div>;
}
4. Error Alert:
function Form() {
const [error, setError] = useState(null);
const handleSubmit = (e) => {
try {
validateForm(formData);
submitForm(formData);
} catch (err) {
setError(err.message);
}
};
return (
<>
{error && <div className="error">{error}</div>}
<form onSubmit={handleSubmit}>...</form>
</>
);
}
28.What is the difference between state and props?
A detailed comparison of state and props.
Key Differences:
| Aspect | State | Props |
|---|---|---|
| Definition | Data managed within component | Data passed from parent |
| Mutable | Yes (can change with setState) | No (read-only) |
| Scope | Local to component | Parent to child |
| Modification | setState/setVariable | Pass from parent only |
| Trigger Re-render | Yes | Yes |
| Initial Value | Set in component | Passed by parent |
| Purpose | Component's own data | Configuration/values |
Example Comparison:
function Parent() {
const [darkMode, setDarkMode] = useState(false); // State
return <Child isDarkMode={darkMode} onToggle={setDarkMode} />; // Props
}
function Child({ isDarkMode, onToggle }) {
// isDarkMode and onToggle are props (read-only)
return <button onClick={() => onToggle(!isDarkMode)}>Toggle</button>;
}
State Example:
function Counter() {
const [count, setCount] = useState(0); // Can be modified
return (
<button onClick={() => setCount(count + 1)}>
Count: {count}
</button>
);
}
Props Example:
function Message({ title }) {
// title is a prop (cannot change it here)
return <h1>{title}</h1>;
}
// Parent passes props
<Message title="Hello" /> // title is a prop
29.How do you import and use external libraries in React?
Using npm/yarn to install and import libraries in React projects.
Installation:
npm install library-name
# or
yarn add library-name
Example: Using Axios for HTTP requests
npm install axios
import axios from 'axios';
function App() {
const [data, setData] = useState(null);
useEffect(() => {
axios.get('/api/data')
.then(response => setData(response.data))
.catch(error => console.error(error));
}, []);
return <div>{data}</div>;
}
Example: Using a UI Library (Material-UI)
npm install @mui/material @emotion/react @emotion/styled
import Button from '@mui/material/Button';
function App() {
return <Button variant="contained">Click me</Button>;
}
Example: Using Lodash for utilities
npm install lodash
import { debounce } from 'lodash';
const debouncedSearch = debounce((query) => {
search(query);
}, 300);
Checking Package.json:
{
"dependencies": {
"react": "^18.0.0",
"axios": "^1.0.0",
"lodash": "^4.17.21"
}
}
30.What is a side effect and what are examples?
Side effects are operations that interact with the outside world or affect the application beyond the current component.
Common Side Effects:
1. Data Fetching:
useEffect(() => {
fetch('/api/users')
.then(res => res.json())
.then(data => setUsers(data));
}, []);
2. Updating DOM Directly:
useEffect(() => {
document.title = 'My App';
}, []);
3. Subscriptions:
useEffect(() => {
const subscription = eventEmitter.subscribe('event', handleEvent);
return () => subscription.unsubscribe();
}, []);
4. Setting Timers:
useEffect(() => {
const timer = setTimeout(() => {
console.log('Timeout!');
}, 1000);
return () => clearTimeout(timer);
}, []);
5. Local Storage:
useEffect(() => {
localStorage.setItem('theme', theme);
}, [theme]);
6. Analytics:
useEffect(() => {
trackPageView(location.pathname);
}, [location]);
Why useEffect? side effects shouldn't run in the component body because they would run on every render. useEffect manages when they run.
31.What is the virtual DOM?
The Virtual DOM is an in-memory representation of the real DOM that React uses to optimize updates.
How It Works:
1. Render Phase:
Component state/props change
↓
Component re-renders
↓
New Virtual DOM created
2. Reconciliation:
React compares new and old Virtual DOM
↓
Finds differences (diffing)
↓
Determines minimal changes needed
3. Commit Phase:
Applies changes to real DOM
↓
Browser re-paints affected elements
Example:
function App() {
const [count, setCount] = useState(0);
// When count changes:
// 1. New Virtual DOM created with new count
// 2. React compares old and new Virtual DOM
// 3. Only the <p> tag and <button> text are updated in real DOM
// 4. Browser doesn't re-render entire page
return (
<>
<h1>Title (not updated)</h1>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</>
);
}
Benefits:
- Performance optimization: Only updates changed elements
- Abstraction: Developers don't manage DOM directly
- Cross-platform: Same Virtual DOM works for React Native
- Predictable: Changes are batched and optimized
Note: The Virtual DOM is not specific to React, but React popularized it.
32.What are React Developer Tools?
React Developer Tools is a browser extension for debugging React applications.
Installation:
- Install extension for Chrome or Firefox
- Open DevTools (F12)
- Go to "React" tab
Features:
1. Component Tree:
View all components in the app
See component hierarchy
Expand/collapse components
2. Props and State:
Inspect props values
Inspect state values
See what changed
3. Search Components:
Find components by name
Quick navigation
4. Profiling:
// Check component render times
// Identify performance bottlenecks
// See why components re-render
Usage Example:
1. Open a React app in browser
2. Open DevTools (F12)
3. Click "React" tab
4. Click on component in the tree
5. See props/state on the right panel
6. Click on a component in the DOM to inspect it
Common Tasks:
- Find why a component is not updating
- Check if props are correct
- Monitor re-renders
- Test state changes
- Profile performance
Tips:
- Hover over element in DevTools to highlight it in the page
- Right-click component → inspect element
- Use $r in console to access selected component
33.How do you test React components?
Testing React components using Jest and React Testing Library.
Setup:
npm install --save-dev jest @testing-library/react @testing-library/jest-dom
Simple Test:
import { render, screen } from '@testing-library/react';
import Button from './Button';
test('renders button with text', () => {
render(<Button>Click me</Button>);
const button = screen.getByText('Click me');
expect(button).toBeInTheDocument();
});
Testing Props:
test('displays user name', () => {
render(<UserCard name="John" age={25} />);
expect(screen.getByText('John')).toBeInTheDocument();
expect(screen.getByText('25')).toBeInTheDocument();
});
Testing Events:
import { render, screen, fireEvent } from '@testing-library/react';
test('button click increments count', () => {
render(<Counter />);
const button = screen.getByRole('button', { name: 'Increment' });
fireEvent.click(button);
expect(screen.getByText('Count: 1')).toBeInTheDocument();
});
Testing Async Code:
test('fetches and displays data', async () => {
render(<UserList />);
// Wait for async operation
const user = await screen.findByText('John');
expect(user).toBeInTheDocument();
});
Testing State:
test('updates state on input change', () => {
render(<Form />);
const input = screen.getByRole('textbox');
fireEvent.change(input, { target: { value: 'John' } });
expect(input.value).toBe('John');
});
34.What is lazy loading and code splitting?
Techniques to reduce initial bundle size by loading code only when needed.
Code Splitting: Breaks code into smaller chunks that load on demand.
Lazy Loading: Defers loading of components until they're needed.
Using React.lazy():
import React, { Suspense } from 'react';
const HeavyComponent = React.lazy(() => import('./HeavyComponent'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<HeavyComponent />
</Suspense>
);
}
Route-based Code Splitting:
import { lazy, Suspense } from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
const Home = lazy(() => import('./pages/Home'));
const About = lazy(() => import('./pages/About'));
const Dashboard = lazy(() => import('./pages/Dashboard'));
function App() {
return (
<BrowserRouter>
<Suspense fallback={<div>Loading...</div>}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/dashboard" element={<Dashboard />} />
</Routes>
</Suspense>
</BrowserRouter>
);
}
Benefits:
- Smaller initial bundle size
- Faster first page load
- Load code only when needed
- Better user experience
Bundle Size Reduction Example:
Before:
app.js: 500KB
After:
app.js: 100KB
Home.chunk.js: 50KB (loaded on /')
About.chunk.js: 80KB (loaded on /about)
Dashboard.chunk.js: 200KB (loaded on /dashboard)
35.What is the difference between uncontrolled and controlled forms?
Two approaches to managing form state in React.
Controlled Form (React manages state):
function LoginForm() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
return (
<form onSubmit={(e) => {
e.preventDefault();
// email and password are in state
submitForm(email, password);
}}>
<input
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<button>Submit</button>
</form>
);
}
Benefits:
- Single source of truth (state)
- Real-time validation
- Can disable submit button conditionally
- Easy to reset form
Uncontrolled Form (DOM manages state):
function LoginForm() {
const emailRef = useRef();
const passwordRef = useRef();
const handleSubmit = (e) => {
e.preventDefault();
// Access values from DOM
const email = emailRef.current.value;
const password = passwordRef.current.value;
submitForm(email, password);
};
return (
<form onSubmit={handleSubmit}>
<input ref={emailRef} />
<input ref={passwordRef} type="password" />
<button>Submit</button>
</form>
);
}
Benefits:
- Simpler code
- Works with non-React code
- Less re-renders
When to Use:
- Controlled: Most cases, especially with validation
- Uncontrolled: File inputs, simple forms, integration with third-party
36.What is the Fragment component and when to use it?
Fragment allows grouping multiple elements without adding extra DOM nodes.
Problem (Extra Wrapper Div):
function Component() {
return (
<div>
<h1>Title</h1>
<p>Content</p>
</div>
);
}
// Renders:
// <div>
// <h1>Title</h1>
// <p>Content</p>
// </div>
Solution with Fragment:
function Component() {
return (
<>
<h1>Title</h1>
<p>Content</p>
</>
);
}
// Renders (no wrapper):
// <h1>Title</h1>
// <p>Content</p>
Long Form (with key prop):
function List() {
return items.map(item => (
<React.Fragment key={item.id}>
<h2>{item.title}</h2>
<p>{item.description}</p>
</React.Fragment>
));
}
Use Cases:
- Avoiding wrapper divs: Cleaner HTML
- CSS Grid/Flexbox: Wrapper affects layout
- Table structure:
function TableRow() {
return (
<>
<td>Cell 1</td>
<td>Cell 2</td>
</>
);
}
Comparison:
// With div wrapper (affects styling)
<div style={{ display: 'flex' }}>
<h1>Title</h1>
<p>Content</p>
</div>
// With Fragment (no wrapper, cleaner)
<>
<h1>Title</h1>
<p>Content</p>
</>
37.How do you handle async data fetching in React?
Patterns for fetching data asynchronously in React.
Basic Fetch with useEffect:
function UserList() {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetch('/api/users')
.then(res => res.json())
.then(data => {
setUsers(data);
setLoading(false);
})
.catch(err => {
setError(err);
setLoading(false);
});
}, []);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<ul>
{users.map(user => <li key={user.id}>{user.name}</li>)}
</ul>
);
}
Async/Await:
function UserList() {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchUsers = async () => {
try {
const res = await fetch('/api/users');
const data = await res.json();
setUsers(data);
} finally {
setLoading(false);
}
};
fetchUsers();
}, []);
if (loading) return <div>Loading...</div>;
return <ul>{users.map(u => <li key={u.id}>{u.name}</li>)}</ul>;
}
Custom Hook:
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetch(url)
.then(res => res.json())
.then(data => { setData(data); setLoading(false); })
.catch(err => { setError(err); setLoading(false); });
}, [url]);
return { data, loading, error };
}
// Usage
function App() {
const { data, loading } = useFetch('/api/users');
if (loading) return <div>Loading...</div>;
return <div>{JSON.stringify(data)}</div>;
}
38.What are higher-order components (HOC)?
A higher-order component is a function that takes a component and returns a new component with added functionality.
Basic Pattern:
function withSubscription(Component) {
return function WrappedComponent(props) {
const [data, setData] = useState(null);
useEffect(() => {
// Subscribe to data
const subscription = DataSource.subscribe(setData);
return () => DataSource.unsubscribe(subscription);
}, []);
return <Component data={data} {...props} />;
};
}
Usage:
function MyComponent({ data }) {
return <div>Data: {data}</div>;
}
const EnhancedComponent = withSubscription(MyComponent);
Example: withRouter (Legacy React Router):
function withRouter(Component) {
return (props) => {
const location = useLocation();
const navigate = useNavigate();
return <Component {...props} location={location} navigate={navigate} />;
};
}
const MyComponent = ({ location, navigate }) => {
return <div>Current path: {location.pathname}</div>;
};
const Enhanced = withRouter(MyComponent);
Example: withTheme:
function withTheme(Component) {
return (props) => {
const [theme, setTheme] = useState('light');
return (
<Component
{...props}
theme={theme}
toggleTheme={() => setTheme(t => t === 'light' ? 'dark' : 'light')}
/>
);
};
}
Drawbacks:
- Wrapper hell (multiple HOCs)
- Difficult to debug
- Static methods not copied
Modern Alternative: Custom Hooks Hooks are now preferred for code reuse.
39.What is TypeScript and why use it in React?
TypeScript adds type safety to JavaScript, reducing bugs and improving code quality.
What is TypeScript? JavaScript with types. It compiles to plain JavaScript.
Basic Types:
const name: string = 'John';
const age: number = 25;
const active: boolean = true;
const hobbies: string[] = ['reading', 'coding'];
React with TypeScript:
import { FC, useState } from 'react';
interface Props {
name: string;
age: number;
onClick?: (id: number) => void;
}
const Greeting: FC<Props> = ({ name, age, onClick }) => {
const [count, setCount] = useState<number>(0);
return (
<div>
{name}, {age} years old
<button onClick={() => onClick?.(1)}>Click</button>
</div>
);
};
Benefits:
- Type Safety: Catch errors at compile time
- Better IDE Support: Autocomplete and refactoring
- Documentation: Types serve as documentation
- Prevents Bugs: Reduces runtime errors
- Refactoring: Safer code changes
Common React Types:
// Functional component
const MyComponent: React.FC<Props> = (props) => {};
// Event handler
const handleClick: React.MouseEventHandler<HTMLButtonElement> = (e) => {};
// Form input
const handleChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {};
Setup:
npx create-react-app my-app --template typescript
40.What is the React DevTools Profiler?
React DevTools Profiler analyzes component performance and render times.
How to Use:
- Open React DevTools (F12 → React tab)
- Click "Profiler" tab
- Click red record button
- Interact with your app
- Stop recording
What It Shows:
1. Render Duration: How long each component took to render
2. Why Components Render:
- State changed
- Props changed
- Parent re-rendered
- Context changed
3. Component Rank: Components ranked by render time
Example Analysis:
Component Render Time Reason
─────────────────────────────────────────
App 15ms State changed (count)
List 8ms Parent re-rendered
Item 2ms Props changed (item)
Item 2ms Props changed (item)
Item 2ms Props changed (item)
How to Improve:
1. Use React.memo to prevent unnecessary renders:
const Item = React.memo(({ item }) => {
return <div>{item.name}</div>;
});
2. Use useCallback for event handlers:
const handleClick = useCallback(() => {
doSomething();
}, [dependency]);
3. Use useMemo for expensive calculations:
const value = useMemo(() => expensiveCalc(), [dependency]);
Tips:
- Profile on slower devices
- Look for unexpected re-renders
- Check component render times
- Identify bottlenecks
41.How do you pass functions as props in React?
Functions are often passed as props to handle events in child components.
Basic Example:
function Parent() {
const handleClick = () => {
console.log('Button clicked');
};
return <Button onClick={handleClick} />;
}
function Button({ onClick }) {
return <button onClick={onClick}>Click me</button>;
}
With Parameters:
function Parent() {
const handleDelete = (id) => {
console.log('Delete item:', id);
};
return <Item id={123} onDelete={handleDelete} />;
}
function Item({ id, onDelete }) {
return <button onClick={() => onDelete(id)}>Delete</button>;
}
With Event Object:
function Parent() {
const handleChange = (e) => {
console.log('Input value:', e.target.value);
};
return <Input onChange={handleChange} />;
}
function Input({ onChange }) {
return <input onChange={onChange} />;
}
Best Practice: Naming Convention:
function Parent() {
// Prefix callbacks with "on"
const handleChange = (value) => {};
const handleSubmit = () => {};
const handleError = (error) => {};
return (
<Child
onChange={handleChange}
onSubmit={handleSubmit}
onError={handleError}
/>
);
}
Multiple Parameters:
function Parent() {
const handleUpdate = (id, newValue) => {
console.log(`Update ${id} to ${newValue}`);
};
return (
<Item
onUpdate={(id) => handleUpdate(id, 'newValue')}
/>
);
}
42.What is the dependency array in useEffect?
The dependency array controls when useEffect runs.
No Dependency Array - Runs After Every Render:
useEffect(() => {
console.log('Runs after EVERY render');
});
Empty Dependency Array - Runs Once on Mount:
useEffect(() => {
console.log('Runs once on mount');
// Good for fetching initial data
}, []);
With Dependencies - Runs When Dependencies Change:
const [count, setCount] = useState(0);
const [name, setName] = useState('');
useEffect(() => {
console.log('Runs when count changes');
}, [count]);
useEffect(() => {
console.log('Runs when count or name changes');
}, [count, name]);
Example: API Call on Prop Change:
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
useEffect(() => {
// Fetch whenever userId changes
fetch(`/api/users/${userId}`)
.then(res => res.json())
.then(setUser);
}, [userId]); // Dependency: userId
}
Common Mistakes:
Missing Dependency:
const [count, setCount] = useState(0);
// ❌ Missing count in dependencies
useEffect(() => {
console.log('Count:', count); // Stale value!
}, []); // Should be [count]
Too Many Dependencies:
// ❌ Runs on every render
useEffect(() => {
fetch('/api/data');
}, [data, userData, settings, theme]); // Too many!
// ✓ Better
const dependencies = useMemo(() => [data], [data]);
useEffect(() => {
fetch('/api/data');
}, dependencies);
43.How do you create reusable components?
Guidelines for building flexible, reusable React components.
Make Components Generic:
// ❌ Specific
function UserCard() {
return <div>User info</div>;
}
// ✓ Reusable
function Card({ title, children }) {
return (
<div className="card">
{title && <h2>{title}</h2>}
{children}
</div>
);
}
Use Props for Customization:
function Button({ label, type = 'button', onClick, disabled = false }) {
return (
<button
type={type}
onClick={onClick}
disabled={disabled}
className={`btn btn-${type}`}
>
{label}
</button>
);
}
// Many variations
<Button label="Click me" />
<Button label="Submit" type="submit" />
<Button label="Delete" type="danger" />
Composition Over Inheritance:
// ✓ Good: Compose smaller components
function UserProfile({ user }) {
return (
<Card>
<Avatar src={user.avatar} />
<UserInfo name={user.name} email={user.email} />
<UserStats followers={user.followers} />
</Card>
);
}
Accept Event Handlers as Props:
function Input({ value, onChange, onBlur, placeholder }) {
return (
<input
value={value}
onChange={onChange}
onBlur={onBlur}
placeholder={placeholder}
/>
);
}
Provide Default Props:
function Pagination({ current = 1, total = 10, onPageChange }) {
return (
<div>
<span>Page {current} of {total}</span>
<button onClick={() => onPageChange(current - 1)}>Prev</button>
<button onClick={() => onPageChange(current + 1)}>Next</button>
</div>
);
}
44.What is destructuring and how is it used in React?
Destructuring is a JavaScript feature to extract values from objects/arrays into variables.
Object Destructuring:
const person = { name: 'John', age: 25, city: 'NYC' };
// Traditional
const name = person.name;
const age = person.age;
// Destructuring
const { name, age } = person;
In React Props:
// Without destructuring
function Greeting(props) {
return <h1>Hello, {props.name}!</h1>;
}
// With destructuring
function Greeting({ name, age }) {
return <h1>Hello, {name}! You are {age}</h1>;
}
Array Destructuring:
const colors = ['red', 'green', 'blue'];
// Without destructuring
const first = colors[0];
const second = colors[1];
// With destructuring
const [first, second, third] = colors;
In useState:
// Same as useState hook
const [count, setCount] = useState(0);
// Equivalent to:
const state = useState(0);
const count = state[0];
const setCount = state[1];
Nested Destructuring:
const user = {
name: 'John',
address: {
city: 'NYC',
zip: '10001'
}
};
const { name, address: { city } } = user;
console.log(name); // 'John'
console.log(city); // 'NYC'
Default Values:
const { name = 'Guest', age = 0 } = {};
console.log(name); // 'Guest'
console.log(age); // 0
45.How do you manage state in larger applications?
Strategies for managing complex state in large React applications.
1. Lifting State Up:
function Parent() {
const [items, setItems] = useState([]);
const [filter, setFilter] = useState('');
return (
<>
<Filter value={filter} onChange={setFilter} />
<ItemList items={items} filter={filter} />
</>
);
}
2. Context API for Global State:
const AppContext = createContext();
function Provider({ children }) {
const [user, setUser] = useState(null);
const [theme, setTheme] = useState('light');
return (
<AppContext.Provider value={{ user, setUser, theme, setTheme }}>
{children}
</AppContext.Provider>
);
}
function useAppContext() {
return useContext(AppContext);
}
3. useReducer for Complex State:
function reducer(state, action) {
switch(action.type) {
case 'ADD_ITEM':
return { ...state, items: [...state.items, action.payload] };
case 'DELETE_ITEM':
return { ...state, items: state.items.filter(i => i.id !== action.payload) };
default:
return state;
}
}
function App() {
const [state, dispatch] = useReducer(reducer, { items: [] });
return (
<button onClick={() => dispatch({ type: 'ADD_ITEM', payload: newItem })}>
Add
</button>
);
}
4. State Management Libraries:
- Redux: For complex applications
- Zustand: Lightweight alternative
- Jotai: Atomic state management
- Recoil: Facebook's solution
When to Use Each:
- useState: Local component state
- useReducer: Complex state logic
- Context: Global state (theme, auth)
- Redux/Zustand: Large applications with shared state
46.What is the spread operator (...) and how is it used in React?
The spread operator expands arrays or objects into individual elements.
Spread with Objects:
const user = { name: 'John', age: 25 };
const extended = { ...user, city: 'NYC' };
// { name: 'John', age: 25, city: 'NYC' }
In React Props:
const props = {
name: 'John',
age: 25,
email: 'john@example.com'
};
// Instead of
<User name={props.name} age={props.age} email={props.email} />
// Use spread
<User {...props} />
Merging Props:
function Button(props) {
return <button {...props} className="btn">Click me</button>;
}
// Allows passing any props
<Button onClick={handleClick} disabled={true} />
Spread with Arrays:
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5]; // [1, 2, 3, 4, 5]
Immutable State Updates:
const [user, setUser] = useState({ name: 'John', age: 25 });
// Update one property
setUser({ ...user, age: 26 });
// { name: 'John', age: 26 }
Combining Objects:
const defaults = { theme: 'light', language: 'en' };
const userPrefs = { theme: 'dark' };
const settings = { ...defaults, ...userPrefs };
// { theme: 'dark', language: 'en' }
Common Use in React:
// Passing all props to child
function Component(props) {
return <Child {...props} extraProp="value" />;
}
// State updates
setState(prevState => ({ ...prevState, key: newValue }));
47.How do you handle keyboard events in React?
Handling keyboard input and key presses in React.
onKeyDown Event:
function Input() {
const handleKeyDown = (e) => {
if (e.key === 'Enter') {
console.log('Enter pressed');
}
if (e.key === 'Escape') {
console.log('Escape pressed');
}
};
return <input onKeyDown={handleKeyDown} />;
}
onKeyUp Event:
function Input() {
const [value, setValue] = useState('');
const handleKeyUp = (e) => {
if (e.key === 'Enter') {
submitForm(value);
}
};
return (
<input
value={value}
onChange={(e) => setValue(e.target.value)}
onKeyUp={handleKeyUp}
/>
);
}
Common Key Codes:
const handleKeyDown = (e) => {
if (e.key === 'Enter') { /* Enter */ }
if (e.key === 'Escape') { /* Esc */ }
if (e.key === ' ') { /* Space */ }
if (e.key === 'ArrowUp') { /* Up arrow */ }
if (e.key === 'ArrowDown') { /* Down arrow */ }
if (e.code === 'KeyA') { /* A key */ }
};
Modifier Keys:
const handleKeyDown = (e) => {
if (e.ctrlKey && e.key === 's') {
e.preventDefault();
console.log('Ctrl+S pressed');
}
if (e.shiftKey && e.key === 'Enter') {
console.log('Shift+Enter pressed');
}
if (e.altKey && e.key === 'ArrowUp') {
console.log('Alt+Up pressed');
}
};
Preventing Default:
const handleKeyDown = (e) => {
// Prevent typing in a read-only input
if (isReadOnly) {
e.preventDefault();
}
};
48.What is defaultProps and when to use it?
defaultProps sets default values for component props.
Function Component:
function Greeting({ name = 'Guest', age = 0 }) {
return <p>{name} is {age} years old</p>;
}
// Modern approach (recommended)
Using defaultProps (Legacy):
function Greeting({ name, age }) {
return <p>{name} is {age} years old</p>;
}
Greeting.defaultProps = {
name: 'Guest',
age: 0
};
Class Component:
class Greeting extends React.Component {
static defaultProps = {
name: 'Guest',
age: 0
};
render() {
return <p>{this.props.name} is {this.props.age}</p>;
}
}
Comparison: Modern vs Legacy
Modern (Preferred):
function MyComponent({ name = 'Default' }) {
return <div>{name}</div>;
}
Legacy:
function MyComponent({ name }) {
return <div>{name}</div>;
}
MyComponent.defaultProps = {
name: 'Default'
};
When to Use Modern Approach:
- Cleaner syntax
- Better IDE support
- Easier to understand
- No need for separate defaultProps
Modern Best Practice:
function Button({
label = 'Click me',
type = 'button',
disabled = false,
onClick
}) {
return (
<button type={type} disabled={disabled} onClick={onClick}>
{label}
</button>
);
}
49.How do you create a modal in React?
Creating modal dialogs in React using Portals.
Basic Modal Component:
import ReactDOM from 'react-dom';
function Modal({ isOpen, onClose, children }) {
if (!isOpen) return null;
return ReactDOM.createPortal(
<div className="modal-overlay" onClick={onClose}>
<div className="modal-content" onClick={(e) => e.stopPropagation()}>
<button className="close" onClick={onClose}>×</button>
{children}
</div>
</div>,
document.getElementById('modal-root')
);
}
Usage:
function App() {
const [isOpen, setIsOpen] = useState(false);
return (
<>
<button onClick={() => setIsOpen(true)}>Open Modal</button>
<Modal isOpen={isOpen} onClose={() => setIsOpen(false)}>
<h2>Modal Title</h2>
<p>Modal content goes here</p>
<button onClick={() => setIsOpen(false)}>Close</button>
</Modal>
</>
);
}
HTML Setup:
<div id="root"></div>
<div id="modal-root"></div>
CSS:
.modal-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
}
.modal-content {
background: white;
padding: 20px;
border-radius: 8px;
max-width: 500px;
width: 90%;
}
Advanced: Prevent Body Scroll
function Modal({ isOpen, onClose, children }) {
useEffect(() => {
if (isOpen) {
document.body.style.overflow = 'hidden';
}
return () => {
document.body.style.overflow = 'unset';
};
}, [isOpen]);
if (!isOpen) return null;
// ...
}
50.What is the useCallback hook and when to use it?
useCallback memoizes a function to prevent unnecessary re-renders of child components.
Problem: Function Created on Every Render
function Parent() {
// This function is recreated on every render
const handleClick = () => {
console.log('clicked');
};
// Child receives new function reference, causing re-render even if props didn't change
return <Child onClick={handleClick} />;
}
const Child = React.memo(({ onClick }) => {
return <button onClick={onClick}>Click</button>;
});
Solution: useCallback
function Parent() {
// Function reference stays the same if dependencies haven't changed
const handleClick = useCallback(() => {
console.log('clicked');
}, []); // Empty dependency = never change
return <Child onClick={handleClick} />;
}
With Dependencies:
function Parent() {
const [count, setCount] = useState(0);
// Function changes only when count changes
const handleClick = useCallback(() => {
console.log('Count:', count);
}, [count]); // Dependency: count
return <Child onClick={handleClick} />;
}
Practical Example:
function SearchList({ items }) {
const [query, setQuery] = useState('');
// This function changes only when query changes
const handleSearch = useCallback((searchTerm) => {
return items.filter(item => item.name.includes(searchTerm));
}, [items]);
return (
<>
<Input onSearch={(q) => handleSearch(q)} />
<Results items={handleSearch(query)} />
</>
);
}
When to Use:
- Passing callbacks to memoized children
- Event handlers used by memoized components
- Dependency of useEffect
- Don't overuse (adds complexity)
Rule of Thumb: Use when child is memoized (React.memo) and receives callback as prop.