1. What is React?
React's key features include its declarative nature (you describe what the UI should look like for a given state), component-based architecture, and unidirectional data flow. It’s widely used because of its performance and scalability.
// Basic React component import React from 'react'; import ReactDOM from 'react-dom'; function App() { return ( <div> <h1>Hello, React!</h1> <p>This is a simple React component.</p> </div> ); } ReactDOM.render(<App />, document.getElementById('root'));
In this example, the `App` component is rendered into a DOM element with the ID `root`. React handles the rendering and updates efficiently using the Virtual DOM.
2. What are components in React?
Functional components are simpler and more modern, while class components were traditionally used for state management and lifecycle methods before hooks were introduced in React 16.8.
// Functional Component const Welcome = ({ name }) => { return <h1>Hello, {name}!</h1>; }; // Class Component class WelcomeClass extends React.Component { constructor(props) { super(props); this.state = { greeting: 'Hello' }; } render() { return <h1>{this.state.greeting}, {this.props.name}!</h1>; } } // Usage function App() { return ( <> <Welcome name="Alice" /> <WelcomeClass name="Bob" /> </> ); }
Here, `Welcome` is a functional component that accepts a `name` prop, while `WelcomeClass` is a class component with internal state. Both achieve similar results but differ in syntax and capabilities.
3. What is JSX?
JSX supports embedding JavaScript expressions using curly braces `` and can include attributes, conditionals, and loops.
// JSX Example const name = "React"; const element = ( <div className="container"> <h1>Hello, {name}!</h1> {true ? <p>JSX is awesome!</p> : <p>Not rendered</p>} </div> ); // Transpiled to: const element = React.createElement( "div", { className: "container" }, React.createElement("h1", null, "Hello, ", name, "!"), true ? React.createElement("p", null, "JSX is awesome!") : React.createElement("p", null, "Not rendered") );
This shows how JSX simplifies UI declaration. The transpiled version demonstrates what happens under the hood, but developers rarely write it manually.
4. What is the Virtual DOM?
This process, called reconciliation, enhances performance, especially in dynamic applications with frequent updates.
import React, { useState } from 'react'; function Counter() { const [count, setCount] = useState(0); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}>Click me</button> </div> ); } // React updates only the <p> content when count changes
In this example, clicking the button updates the count
state. React re-renders the Virtual DOM, detects the change in the <p>
element, and updates only that part in the real DOM.
5. What are props in React?
They enable component reusability by making them configurable from the outside.
// Child component const Greeting = ({ name, greetFn }) => ( <button onClick={() => greetFn(name)}>Hello, {name}!</button> ); // Parent component function App() { const sayHello = (name) => alert(`Hi, ${name}!`); return ( <div> <Greeting name="Alice" greetFn={sayHello} /> <Greeting name="Bob" greetFn={sayHello} /> </div> ); }
Here, `Greeting` receives `name` and `greetFn` as props. The parent `App` passes different names and a shared function, demonstrating how props customize behavior.
6. What is state in React?
State is private to the component and can only be updated using the provided setter function (e.g., `setState` or the updater from `useState`).
import React, { useState } from 'react'; function Toggle() { const [isOn, setIsOn] = useState(false); return ( <div> <p>Status: {isOn ? 'On' : 'Off'}</p> <button onClick={() => setIsOn(!isOn)}> Toggle </button> </div> ); } // Class version class ToggleClass extends React.Component { state = { isOn: false }; toggle = () => this.setState({ isOn: !this.state.isOn }); render() { return ( <div> <p>Status: {this.state.isOn ? 'On' : 'Off'}</p> <button onClick={this.toggle}>Toggle</button> </div> ); } }
Both examples show a toggle switch. The functional version uses `useState`, while the class version uses `setState`. State changes trigger re-renders automatically.
7. What are hooks in React?
Common hooks include `useState` (for state), `useEffect` (for side effects), and `useContext` (for context). Custom hooks can also be created for shared logic.
import React, { useState, useEffect } from 'react'; // Custom hook 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(); const [count, setCount] = useState(0); return ( <div> <p>Window width: {width}px</p> <p>Count: {count}</p> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); }
This example uses `useState` for a counter, `useEffect` in a custom `useWindowWidth` hook to track window size, and demonstrates how hooks simplify stateful logic in functional components.
8. What is the useEffect hook?
It replaces lifecycle methods like `componentDidMount`, `componentDidUpdate`, and `componentWillUnmount` in class components. The cleanup function (returned by `useEffect`) prevents memory leaks.
import React, { useState, useEffect } from 'react'; function DataFetcher({ url }) { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { setLoading(true); const fetchData = async () => { try { const response = await fetch(url); const result = await response.json(); setData(result); } catch (error) { console.error('Fetch error:', error); } finally { setLoading(false); } }; fetchData(); }, [url]); // Runs when url changes return ( <div> {loading ? <p>Loading...</p> : <pre>{JSON.stringify(data, null, 2)}</pre>} </div> ); } function App() { return <DataFetcher url="https://api.example.com/data" />; }
Here, `useEffect` fetches data when the `url` prop changes. The dependency array `[url]` ensures it doesn’t run unnecessarily, and the async operation is handled cleanly.
9. What is the difference between useState and useReducer?
Use `useState` for basic state (e.g., a single counter). Use `useReducer` when state updates depend on previous state or involve multiple actions (e.g., a form with many fields).
import React, { useState, useReducer } from 'react'; // useState example function Counter() { const [count, setCount] = useState(0); return ( <div> <p>Count: {count}</p> <button onClick={() => setCount(count + 1)}>Add</button> </div> ); } // useReducer example const initialState = { count: 0, step: 1 }; function reducer(state, action) { switch (action.type) { case 'increment': return { ...state, count: state.count + state.step }; case 'setStep': return { ...state, step: action.step }; default: return state; } } function AdvancedCounter() { const [state, dispatch] = useReducer(reducer, initialState); return ( <div> <p>Count: {state.count}</p> <p>Step: {state.step}</p> <button onClick={() => dispatch({ type: 'increment' })}>Add</button> <input type="number" value={state.step} onChange={(e) => dispatch({ type: 'setStep', step: Number(e.target.value) })} /> </div> ); }
`useState` is straightforward for a single `count`. `useReducer` manages `count` and `step` together, allowing more complex interactions like adjusting the increment step dynamically.
10. What is React Router?
It provides components like `BrowserRouter`, `Route`, `Link`, and `Switch` (or `Routes` in v6) to define routes and navigate programmatically or via links.
import { BrowserRouter, Route, Routes, Link } from 'react-router-dom'; function Home() { return <h1>Home Page</h1>; } function About() { return <h1>About Page</h1>; } function App() { return ( <BrowserRouter> <nav> <Link to="/">Home</Link> | <Link to="/about">About</Link> </nav> <Routes> <Route path="/" element={<Home />} /> <Route path="/about" element={<About />} /> </Routes> </BrowserRouter> ); }
This example sets up a simple app with two routes. Clicking the `Link` components updates the URL and renders the corresponding component without refreshing the page.
11. What is the purpose of keys in React?
Without keys, React might re-render the entire list or misalign elements, leading to performance issues or bugs. Use stable IDs (e.g., from data) rather than array indices when possible.
import React, { useState } from 'react'; function TodoList() { const [todos, setTodos] = useState([ { id: 1, text: 'Learn React' }, { id: 2, text: 'Build a project' }, ]); const addTodo = () => { setTodos([...todos, { id: Date.now(), text: 'New Todo' }]); }; return ( <div> <button onClick={addTodo}>Add Todo</button> <ul> {todos.map(todo => ( <li key={todo.id}>{todo.text}</li> ))} </ul> </div> ); }
Here, key={todo.id}
ensures React tracks each <li>
by its unique id
. If a todo is added, only the new item is appended, not the entire list re-rendered.
12. What is a controlled component?
This approach is predictable and allows validation or formatting before updating the UI. It’s commonly used for inputs, selects, and textareas.
import React, { useState } from 'react'; function Form() { const [name, setName] = useState(''); const [submitted, setSubmitted] = useState(''); const handleSubmit = (e) => { e.preventDefault(); setSubmitted(name); }; return ( <form onSubmit={handleSubmit}> <label> Name: <input type="text" value={name} onChange={(e) => setName(e.target.value.toUpperCase())} /> </label> <button type="submit">Submit</button> <p>Submitted: {submitted}</p> </form> ); }
The input’s `value` is tied to `name` state, and `onChange` updates it (converting to uppercase as an example). On submit, the state value is displayed, showing full control by React.
13. What is an uncontrolled component?
Unlike controlled components, the state isn’t mirrored in React; you retrieve values when needed (e.g., on submit).
import React, { useRef } from 'react'; function UncontrolledForm() { const inputRef = useRef(null); const [submitted, setSubmitted] = useState(''); const handleSubmit = (e) => { e.preventDefault(); setSubmitted(inputRef.current.value); inputRef.current.value = ''; // Reset manually }; return ( <form onSubmit={handleSubmit}> <label> Name: <input type="text" ref={inputRef} defaultValue="Initial" /> </label> <button type="submit">Submit</button> <p>Submitted: {submitted}</p> </form> ); }
Here, `inputRef` accesses the input’s DOM node. The value isn’t tracked in state during typing; it’s grabbed on submit. `defaultValue` sets an initial value.
14. What is the Context API?
It consists of a `Provider` (to supply the value) and a `Consumer` (or `useContext` hook) to access it. Context should be used sparingly to avoid overcomplicating the app.
import React, { createContext, useContext, useState } from 'react'; const ThemeContext = createContext(); function App() { const [theme, setTheme] = useState('light'); return ( <ThemeContext.Provider value={{ theme, setTheme }}> <Toolbar /> </ThemeContext.Provider> ); } function Toolbar() { return <Button />; } function Button() { const { theme, setTheme } = useContext(ThemeContext); return ( <button style={{ background: theme === 'light' ? '#fff' : '#333', color: theme === 'light' ? '#000' : '#fff' }} onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')} > Toggle Theme: {theme} </button> ); }
The `ThemeContext` provides `theme` and `setTheme` to all descendants. The `Button` component consumes it with `useContext` to toggle between light and dark themes.
15. What is Redux?
Redux is overkill for small apps but shines in large-scale applications with complex state interactions.
import { createStore } from 'redux'; import { Provider, useSelector, useDispatch } from 'react-redux'; // Reducer const counterReducer = (state = { count: 0 }, action) => { switch (action.type) { case 'INCREMENT': return { count: state.count + 1 }; case 'DECREMENT': return { count: state.count - 1 }; default: return state; } }; // Store const store = createStore(counterReducer); // React component function Counter() { const count = useSelector(state => state.count); const dispatch = useDispatch(); return ( <div> <p>Count: {count}</p> <button onClick={() => dispatch({ type: 'INCREMENT' })}>Add</button> <button onClick={() => dispatch({ type: 'DECREMENT' })}>Subtract</button> </div> ); } function App() { return ( <Provider store={store}> <Counter /> </Provider> ); }
The `counterReducer` manages the state. `useSelector` accesses the `count`, and `useDispatch` sends actions to update it. The `Provider` makes the store available to all components.
16. What are React Fragments?
<div>
). This keeps the DOM cleaner and avoids unnecessary wrappers that might affect styling or semantics.You can use the shorthand <>...</>
or the explicit <React.Fragment>
syntax, the latter supporting keys for lists.
import React from 'react'; function List() { const items = ['Apple', 'Banana', 'Orange']; return ( <> <h1>Fruits</h1> <ul> {items.map((item, index) => ( <React.Fragment key={index}> <li>{item}</li> <p>Item #{index + 1}</p> </React.Fragment> ))} </ul> </> ); }
The shorthand <>...</>
wraps the <h1>
and <ul>
, while <React.Fragment>
with a key
groups each <li>
and <p>
in the list, avoiding an extra parent <div>
.
17. What is the useMemo hook?
Use it for calculations that are costly (e.g., filtering large arrays) and depend on specific values.
import React, { useState, useMemo } from 'react'; function ExpensiveComponent() { const [count, setCount] = useState(0); const [other, setOther] = useState(0); const expensiveCalculation = (num) => { console.log('Calculating...'); return Array(num).fill().reduce((acc) => acc + Math.random(), 0); }; const memoizedValue = useMemo(() => expensiveCalculation(count), [count]); return ( <div> <p>Memoized Value: {memoizedValue}</p> <button onClick={() => setCount(count + 1)}>Increment Count</button> <button onClick={() => setOther(other + 1)}>Increment Other: {other}</button> </div> ); }
`expensiveCalculation` only runs when `count` changes, not `other`. Without `useMemo`, it would run on every render, slowing the app unnecessarily.
18. What is the useCallback hook?
It’s often used with `React.memo` to optimize performance in components with event handlers.
import React, { useState, useCallback } from 'react'; const Child = React.memo(({ onClick }) => { console.log('Child rendered'); return <button onClick={onClick}>Click me</button>; }); function Parent() { const [count, setCount] = useState(0); const [other, setOther] = useState(0); const handleClick = useCallback(() => { setCount(count + 1); }, [count]); // Only recreates if count changes return ( <div> <p>Count: {count}</p> <Child onClick={handleClick} /> <button onClick={() => setOther(other + 1)}>Other: {other}</button> </div> ); }
`handleClick` is memoized with `useCallback`. The `Child` (wrapped in `React.memo`) only re-renders if `onClick` changes, not when `other` updates, improving performance.
19. What are React Portals?
<body>
for modals or tooltips. This avoids issues with CSS (e.g., overflow: hidden
) or DOM stacking contexts.Portals still participate in React’s event bubbling and context, despite being outside the parent DOM tree.
import React, { useState } from 'react'; import { createPortal } from 'react-dom'; function Modal({ children }) { return createPortal( <div style={{ position: 'fixed', top: '50%', left: '50%', transform: 'translate(-50%, -50%)', background: '#fff', padding: '20px' }}> {children} </div>, document.getElementById('modal-root') // Assumes <div id="modal-root"></div> in HTML ); } function App() { const [showModal, setShowModal] = useState(false); return ( <div> <button onClick={() => setShowModal(true)}>Show Modal</button> {showModal && ( <Modal> <h2>Modal Title</h2> <button onClick={() => setShowModal(false)}>Close</button> </Modal> )} </div> ); }
The <Modal>
component renders into #modal-root
outside the <App>
DOM tree, ensuring it’s positioned correctly (e.g., over other content) without parent constraints.
20. What is lazy loading in React?
It’s especially useful in large applications to optimize performance by loading only what the user currently needs.
import React, { lazy, Suspense } from 'react'; import { BrowserRouter, Route, Routes, Link } from 'react-router-dom'; // Lazy-loaded component const HeavyComponent = lazy(() => import('./HeavyComponent')); // Assume this is a separate file function App() { return ( <BrowserRouter> <nav> <Link to="/">Home</Link> | <Link to="/heavy">Heavy</Link> </nav> <Suspense fallback={<div>Loading...</div>}> <Routes> <Route path="/" element={<h1>Home</h1>} /> <Route path="/heavy" element={<HeavyComponent />} /> </Routes> </Suspense> </BrowserRouter> ); } // HeavyComponent.js export default function HeavyComponent() { return <h1>This is a heavy component!</h1>; }
`HeavyComponent` is loaded only when the `/heavy` route is accessed. `Suspense` shows a fallback UI during loading, enhancing user experience while splitting the bundle.