React interview guide
React Concepts Guide
This guide covers fundamental and advanced React concepts, providing explanations and examples for each topic. Use this as a reference or learning resource for React development.
Table of Contents
- Basic React Concepts
- State and Props
- React Lifecycle
- React Hooks
- Advanced React Concepts
- State Management
- Performance Optimization
- React Router
- Testing React Applications
- Miscellaneous Concepts
- Practical Scenarios
Basic React Concepts
What is React?
React is a JavaScript library for building user interfaces. It was developed by Facebook and is widely used for creating interactive, fast, and scalable web applications.
Core Features and Benefits:
- Component-Based Architecture: React allows you to build encapsulated components that manage their own state.
- Virtual DOM: React uses a virtual representation of the DOM for efficient updates.
- JSX: A syntax extension for JavaScript that allows you to write HTML-like code in your JavaScript files.
- Unidirectional Data Flow: Data in React flows in one direction, from parent to child components.
- Large Ecosystem: React has a vast ecosystem of libraries and tools.
Key Features of React
Virtual DOM
The Virtual DOM is a lightweight copy of the actual DOM. React uses it to improve performance by minimizing direct manipulation of the DOM.
Example of how React updates the DOM:
function Counter() {
const [count, setCount] = useState(0); return (
<div>
<p>{count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}In this example, when the button is clicked, React updates the Virtual DOM first, then efficiently updates only the changed parts in the real DOM.
JSX
JSX is a syntax extension for JavaScript that looks similar to XML or HTML. It allows you to write HTML structures in the same file as your JavaScript code.
Example:
const element = <h1>Hello, world!</h1>;Components
Components are the building blocks of React applications. They can be either function components or class components.
Example of a function component:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}Example of a class component:
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}Unidirectional Data Flow
Data in React flows in one direction, from parent to child components. This makes the application more predictable and easier to understand.
Example:
function ParentComponent() {
const [data, setData] = useState("Hello");return <ChildComponent message={data} />;
}function ChildComponent({ message }) {
return <p>{message}</p>;
}
Functional vs Class Components
Functional Components
- Simpler syntax
- Use hooks for state and lifecycle features
- Easier to test and debug
Example:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}Class Components
- Can use lifecycle methods
- Can have local state
- More verbose syntax
Example:
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}Lifecycle Methods and Hooks
Class components use lifecycle methods like componentDidMount, componentDidUpdate, and componentWillUnmount. Functional components use hooks like useEffect to achieve similar functionality.
Example with lifecycle methods:
class Example extends React.Component {
componentDidMount() {
console.log("Component mounted");
}componentWillUnmount() {
console.log("Component will unmount");
} render() {
return <div>Example Component</div>;
}
}
Equivalent functional component with hooks:
function Example() {
useEffect(() => {
console.log("Component mounted");
return () => console.log("Component will unmount");
}, []); return <div>Example Component</div>;
}What is JSX?
JSX is a syntax extension for JavaScript that allows you to write HTML-like code in your JavaScript files. It makes it easier to describe what the UI should look like.
Example:
const element = (
<div>
<h1>Hello!</h1>
<p>Welcome to React</p>
</div>
);JSX is transformed into regular JavaScript function calls and objects before it’s run in the browser.
Virtual DOM vs Real DOM
The Virtual DOM is a lightweight copy of the actual DOM. When state changes occur, React creates a new Virtual DOM tree and compares it with the previous one. It then updates only the changed parts in the real DOM, which is more efficient than updating the entire DOM tree.
Benefits of Virtual DOM:
- Faster updates
- Improved performance
- More efficient than direct DOM manipulation
State and Props
State vs Props
State
- Managed within the component
- Can be changed over time
- When state changes, the component re-renders
Example:
function Counter() {
const [count, setCount] = useState(0); return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}Props
- Passed from parent to child components
- Read-only within the component
- Changes in props trigger re-renders
Example:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}function App() {
return <Welcome name="Alice" />;
}Passing Data Between Components
Data is typically passed from parent to child components through props. For child-to-parent communication, you can pass functions as props.
Get Dileep Raloti’s stories in your inbox
Join Medium for free to get updates from this writer.
Example:
function Parent() {
const [message, setMessage] = useState("");const handleChildMessage = (childMessage) => {
setMessage(childMessage);
}; return (
<div>
<p>Message from child: {message}</p>
<Child onMessageSend={handleChildMessage} />
</div>
);
}function Child({ onMessageSend }) {
return (
<button onClick={() => onMessageSend("Hello from child!")}>
Send Message to Parent
</button>
);
}
Modifying Props in Child Components
Props should not be modified directly in child components. They are considered read-only. If you need to modify data passed as props, you should lift the state up to a common ancestor.
Default Props
Default props provide fallback values for props that aren’t specified when a component is used.
Example:
function Greeting({ name = "Guest" }) {
return <h1>Hello, {name}!</h1>;
}// Or for class components
Greeting.defaultProps = {
name: "Guest",
};React Lifecycle
Class Component Lifecycle Methods
- Mounting:
constructor()render()componentDidMount()
- Updating:
render()componentDidUpdate()
- Unmounting:
componentWillUnmount()
Example:
class LifecycleExample extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}componentDidMount() {
console.log("Component mounted");
} componentDidUpdate(prevProps, prevState) {
if (this.state.count !== prevState.count) {
console.log("Count updated");
}
} componentWillUnmount() {
console.log("Component will unmount");
} render() {
return (
<div>
<p>Count: {this.state.count}</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Increment
</button>
</div>
);
}
}
Lifecycle Methods in Functional Components
Functional components use the useEffect hook to handle side effects and simulate lifecycle methods.
Example:
function LifecycleExample() {
const [count, setCount] = useState(0);useEffect(() => {
console.log("Component mounted");
return () => console.log("Component will unmount");
}, []); // Empty dependency array means this effect runs once on mount and cleanup on unmount useEffect(() => {
console.log("Count updated");
}, [count]); // This effect runs when count changes return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
React Hooks
React Hooks were introduced in React 16.8 to allow functional components to use state and other React features without writing a class.
Common Hooks
- useState: Adds state to functional components
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}- useEffect: Performs side effects in functional components
function DataFetcher() {
const [data, setData] = useState(null);useEffect(() => {
fetch("https://api.example.com/data")
.then((response) => response.json())
.then((data) => setData(data));
}, []); // Empty dependency array means this effect runs once on mount return <div>{data ? <p>{data}</p> : <p>Loading...</p>}</div>;
}
- useContext: Consumes a React context
const ThemeContext = React.createContext("light");function ThemedButton() {
const theme = useContext(ThemeContext);
return <button className={theme}>Themed Button</button>;
}- useReducer: Manages complex state logic
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, { count: 0 });
return (
<div>
Count: {state.count}
<button onClick={() => dispatch({ type: "increment" })}>+</button>
<button onClick={() => dispatch({ type: "decrement" })}>-</button>
</div>
);
}useEffect vs useLayoutEffect
useEffectruns asynchronously and after a render is painted to the screen.useLayoutEffectruns synchronously after a render but before the screen is updated.
Use useLayoutEffect when you need to make DOM measurements or updates that should be synchronized with the browser's painting.
Custom Hooks
Custom hooks allow you to extract component logic into reusable functions.
Example:
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 ResponsiveComponent() {
const width = useWindowWidth();
return <div>Window width is {width}</div>;
}
Advanced React Concepts
React Context
React Context provides a way to pass data through the component tree without having to pass props down manually at every level.
Example:
const ThemeContext = React.createContext("light");function App() {
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}function Toolbar() {
return <ThemedButton />;
}function ThemedButton() {
const theme = useContext(ThemeContext);
return <button className={theme}>Themed Button</button>;
}
Higher-Order Components (HOCs)
HOCs are functions that take a component and return a new component with some additional functionality.
Example:
function withLogging(WrappedComponent) {
return class extends React.Component {
componentDidMount() {
console.log(`Component ${WrappedComponent.name} mounted`);
}
render() {
return <WrappedComponent {...this.props} />;
}
};
}const EnhancedComponent = withLogging(MyComponent);React Portals
Portals provide a way to render children into a DOM node that exists outside the DOM hierarchy of the parent component.
Example:
function Modal({ children }) {
return ReactDOM.createPortal(children, document.getElementById("modal-root"));
}Code Splitting
Code splitting allows you to split your code into small chunks which you can then load on demand.
Example using dynamic import:
const OtherComponent = React.lazy(() => import("./OtherComponent"));function MyComponent() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<OtherComponent />
</Suspense>
</div>
);
}React’s Reconciliation Process
Reconciliation is the process React uses to update the DOM. When a component’s state or props change, React creates a new virtual DOM tree and compares it with the previous one. It then updates the real DOM with the minimum number of changes necessary.
Prop Drilling
Prop drilling occurs when you pass props through multiple levels of components. It can be avoided by using React Context or state management libraries like Redux.
State Management
Redux
Redux is a predictable state container for JavaScript apps. It helps you write applications that behave consistently and are easy to test.
Core concepts of Redux:
- Store: Holds the state of your application
- Actions: Plain JavaScript objects that represent an intention to change the state
- Reducers: Pure functions that take the current state and an action, and return a new state
Example of a simple Redux setup:
// Action
const increment = () => ({ type: "INCREMENT" });// Reducer
function counterReducer(state = 0, action) {
switch (action.type) {
case "INCREMENT":
return state + 1;
default:
return state;
}
}// Store
const store = createStore(counterReducer);// Usage
store.dispatch(increment());







