ReactJs Interview Questions
- Get link
- X
- Other Apps
ReactJS interview Questions
1. What is React?
Explanation:
React is a JavaScript library developed by Facebook for building user interfaces, especially for single-page applications (SPAs). It allows developers to create large web applications that can change data without reloading the page. React focuses on building UI components that are reusable, modular, and maintainable.
Example:
You can create a simple button component that can be reused across your application:
import React from 'react';
function Button() {
return <button>Click Me</button>;
}
2. What are components in React?
Explanation:
Components are the fundamental building blocks of a React application. They are reusable pieces of UI that encapsulate their behavior and appearance. Components can be class-based (using ES6 classes) or functional (using functions). Each component can have its own state and props, making it easier to manage complex UIs.
Example:
A simple functional component can be created as follows:
function Greeting(props) { return <h1>Hello, {props.name}!</h1>;
}
3. What are props in React?
Explanation:
Props (short for properties) are used to pass data from a parent component to a child component. They are read-only, meaning that a child component cannot modify the props it receives. Props help in creating dynamic components and enhance reusability by allowing components to receive different data inputs.
Example:
Using the Greeting
component with props:
function App() { return <Greeting name="Anjali" />;
}
4. What is state in React?
Explanation:
State is an object that holds data specific to a component. Unlike props, a component can modify its own state. When the state changes, React re-renders the component to reflect the updated state. Managing state is crucial for building interactive applications.
Example:
Using the useState
hook to manage state in a functional component:
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increase</button>
</div>
);
}
5. What is the difference between controlled and uncontrolled components?
Explanation:
- Controlled Components: The form data is controlled by React state. This means that the input value is derived from the component state, and changes are handled through state updates.
- Uncontrolled Components: The form data is managed by the DOM itself. You can access the input value using a reference, but the component does not control the input’s state.
Example of a Controlled Component:
function ControlledInput() { const [value, setValue] = useState('');
return (
<input
type="text"
value={value}
onChange={(e) => setValue(e.target.value)}
/>
);
}
Example of an Uncontrolled Component:
import React, { useRef } from 'react';
function UncontrolledInput() {
const inputRef = useRef(null);
const handleSubmit = () => {
alert(`Input value: ${inputRef.current.value}`);
};
return (
<div>
<input type="text" ref={inputRef} />
<button onClick={handleSubmit}>Submit</button>
</div>
);
}
6. What is the purpose of the useEffect
hook?
Explanation:
The useEffect
hook allows you to perform side effects in functional components. Side effects can include data fetching, subscriptions, or manual DOM manipulations. The useEffect
hook accepts two arguments: a function that contains the side effect code, and an optional dependency array that determines when the effect should run.
Example:
import React, { useEffect } from 'react';
function DataFetcher() {
useEffect(() => {
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => console.log(data));
}, []); // The empty array means this effect runs only once after the initial render.
return <div>Data is being fetched...</div>;
}
7. What are React hooks?
Explanation:
Hooks are functions that let you use state and other React features in functional components. They allow you to use state and lifecycle methods without needing to convert functional components into class components. The two most commonly used hooks are useState
for state management and useEffect
for side effects.
Example:
import React, { useState } from 'react';
function HookExample() {
const [count, setCount] = useState(0); // Declare a state variable
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}
8. What is JSX?
Explanation:
JSX (JavaScript XML) is a syntax extension for JavaScript that resembles HTML. It allows developers to write HTML-like code within JavaScript, making it easier to create React elements. JSX gets compiled to JavaScript, which React then processes to create the virtual DOM.
Example:
const element = <h1>Hello, World!</h1>; // JSX syntax
9. What is the DOM, virtual DOM, Real Dom?
Explanation:
What is DOM?
The DOM (Document Object Model) is a structured representation of a webpage that allows programming languages, like JavaScript, to interact with its content and structure. You can think of it as a tree where each element on a webpage (like headings, buttons, images, etc.) is a node in that tree.
Simple Definition:
- The DOM is like a tree of elements representing all the content on a webpage.
- When the browser loads a webpage, it creates this tree structure.
Example:
Consider this HTML code:
<html> <body>
<h1>Hello, World!</h1>
<button>Click me</button>
</body>
</html>
In the DOM, this structure looks like this:
<html>
(root)<body>
<h1>Hello, World!</h1>
<button>Click me</button>
Real DOM
The Real DOM is the actual structure that the browser uses to render a webpage. When changes are made to the Real DOM (like updating text or adding elements), the entire DOM is updated. This can be slow because the browser has to repaint and reflow the whole page.
Key Points:
- The Real DOM is slow to update because any change triggers a complete re-render of the entire page.
Virtual DOM
The Virtual DOM is a lightweight, in-memory representation of the Real DOM used by React. It helps optimize updates by minimizing the number of changes made to the Real DOM.
Key Points:
- When a component's state or props change, React creates a new Virtual DOM.
- React compares the new Virtual DOM with the previous version (this process is called diffing) to identify what has changed.
When the state of a component changes, React updates the virtual DOM first. It then compares the virtual DOM with the actual DOM to determine what has changed, allowing it to update only the necessary parts of the UI. This process is known as reconciliation and significantly improves performance.
How They Work Together
Here’s a step-by-step breakdown using a simple example of a webpage with a button that changes its text when clicked.
Example Scenario:
Initial Load:
- When the webpage is loaded, the browser creates the Real DOM from the HTML:
<h1>Hello, World!</h1><button>Click me</button>
User Interaction:
- The user clicks the button, intending to change the text from "Click me" to "Clicked".
Virtual DOM Creation:
- React creates a new Virtual DOM that reflects the change:
<h1>Hello, World!</h1><button>Clicked</button>
Diffing Process:
- React compares the new Virtual DOM with the old one to identify what has changed (in this case, the button text).
Efficient Updates:
- React determines that only the button text needs to be updated and calculates the minimal set of changes.
Update Real DOM:
- Instead of updating the entire Real DOM, React only updates the specific part that changed (the button's text).
Final Rendering:
- The browser re-renders the updated UI, displaying "Clicked" on the button.
Summary of Differences
Feature | Virtual DOM | Real DOM |
---|---|---|
Nature | In-memory representation of DOM | Actual browser DOM |
Efficiency | Very fast (minimal updates) | Slower (entire DOM is updated) |
Updating Process | React performs efficient diffs | Direct updates to the entire DOM |
Re-rendering | Only updates the necessary parts | Renders the whole UI (even small changes) |
Usage in React | Used to optimize and improve performance | The final output displayed in the browser |
Conclusion
This efficient approach—using the Virtual DOM to handle updates and only modifying the Real DOM where necessary—allows React applications to be fast and responsive, even as they manage complex user interactions.
10. What are keys in React?
Explanation:
Keys are unique identifiers for elements in a list. They help React identify which items have changed, are added, or are removed. Using keys enhances performance by allowing React to optimize rendering and avoid unnecessary re-renders. Keys should be unique among siblings, but they don’t have to be globally unique.
Example:
function TodoList({ todos }) { return (
<ul>
{todos.map(todo => (
<li key={todo.id}>{todo.text}</li> // Each todo has a unique key
))}
</ul>
);
}
11. What is conditional rendering in React?
Explanation:
Conditional rendering is the ability to render different UI elements based on certain conditions. In React, you can use JavaScript operators like if
, else
, or the conditional (?
) operator to control what gets rendered.
Example:
function Greeting({ isLoggedIn }) { return (
<div>
{isLoggedIn ? <h1>Welcome back!</h1> : <h1>Please log in.</h1>}
</div>
);
}
12. What is the context API in React?
Explanation:
The Context API provides a way to pass data through the component tree without having to pass props down manually at every level. This is useful for global data such as themes, user authentication, and settings.
Example:
import React, { createContext, useContext } from 'react';
// Create a Context
const UserContext = createContext();
function App() {
return (
<UserContext.Provider value={{ name: 'Anjali' }}>
<User />
</UserContext.Provider>
);
}
function User() {
const user = useContext(UserContext);
return <h1>User: {user.name}</h1>;
}
Controlled Components
In a controlled component, the form data is handled by the React component's state. The value of the input field is always controlled by the React state, and any changes to the input update the state.
Example of a Controlled Component
import React, { useState } from 'react';
function ControlledInput() {
const [value, setValue] = useState('');
const handleChange = (event) => {
setValue(event.target.value); // Update state on input change
};
const handleSubmit = (event) => {
event.preventDefault(); // Prevent default form submission
alert(`Submitted: ${value}`);
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
value={value} // Set input value to state
onChange={handleChange} // Update state on change
/>
<button type="submit">Submit</button>
</form>
);
}
export default ControlledInput;
Explanation
- The
value
of the input field is controlled by the state variable value
. - The
onChange
event updates the state using setValue
, which re-renders the component with the new value. - The form submission alerts the current value in the input.
Uncontrolled Components
In an uncontrolled component, form data is handled by the DOM itself rather than the React component. You can use the ref
attribute to access the input value when needed.
Example of an Uncontrolled Component
import React, { useRef } from 'react';
function UncontrolledInput() {
const inputRef = useRef(); // Create a ref to access the input element
const handleSubmit = (event) => {
event.preventDefault(); // Prevent default form submission
alert(`Submitted: ${inputRef.current.value}`); // Access value using ref
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
ref={inputRef} // Attach ref to input
/>
<button type="submit">Submit</button>
</form>
);
}
export default UncontrolledInput;
Explanation
- The
inputRef
is created using useRef
, which allows direct access to the DOM element. - When the form is submitted, the input value is accessed using
inputRef.current.value
, without needing to store it in state.
Summary
- Controlled Components: Manage form data through React state. Every keystroke updates the state, making it easier to manipulate and validate.
- Uncontrolled Components: Use the DOM for form data management. The input's state is not tied to React's state, making it simpler for quick forms but harder to validate and manipulate.
This distinction helps you choose the right approach based on your application's needs!
The useRef
hook in React is a powerful tool that allows you to create mutable references to DOM elements or to store any mutable value that you want to persist across renders without causing re-renders. Here’s a detailed explanation of how useRef
works, its use cases, and examples.
What is useRef
?
Creating a Mutable Reference: useRef
creates a mutable object whose .current
property can hold any value. Unlike state, changing the .current
value does not trigger a re-render of the component.
Persisting Values Across Renders: You can use useRef
to store values that need to persist across renders but do not need to cause a re-render when changed. This is useful for tracking previous values or storing timers and intervals.
Accessing DOM Elements: useRef
is commonly used to access and interact with DOM elements directly, especially when you need to focus an input, measure its size, or call methods on it.
Syntax
The useRef
hook is used like this:
const myRef = useRef(initialValue);
initialValue
: This is the initial value you want the ref
to have. It can be any value, including an object or a DOM element.
Example 1: Accessing DOM Elements
Here’s a simple example where we use useRef
to focus an input element when a button is clicked:
import React, { useRef } from 'react';
function FocusInput() {
const inputRef = useRef(null); // Create a ref with initial value null
const handleFocus = () => {
inputRef.current.focus(); // Access the input DOM element and call focus()
};
return (
<div>
<input type="text" ref={inputRef} placeholder="Focus me!" />
<button onClick={handleFocus}>Focus Input</button>
</div>
);
}
export default FocusInput;
Explanation
- Creating a Ref: We create a ref using
useRef(null)
and assign it to inputRef
. - Accessing the Input: When the button is clicked, we access the input element via
inputRef.current
and call its focus()
method, making the input field active.
Example 2: Storing Mutable Values
You can also use useRef
to store mutable values that do not need to trigger re-renders, such as timers or counters.
import React, { useRef, useEffect } from 'react';
function Timer() {
const timerRef = useRef(0); // Initialize the ref with a value of 0
useEffect(() => {
const interval = setInterval(() => {
timerRef.current += 1; // Increment the current value
console.log(`Timer: ${timerRef.current}`); // Log the current timer value
}, 1000);
return () => clearInterval(interval); // Clean up the interval on unmount
}, []);
return <h1>Open the console to see the timer!</h1>;
}
export default Timer;
Explanation
- Storing a Timer: We use
useRef
to store a mutable timer value, timerRef
. - Updating the Value: Inside the
setInterval
, we increment timerRef.current
every second. This does not cause a re-render. - Logging: The timer value is logged to the console without affecting the component's render cycle.
When to Use useRef
- Accessing DOM Elements: When you need to directly manipulate or access a DOM element, such as focusing an input or scrolling.
- Storing Previous Values: To store previous state or prop values without causing a re-render.
- Timers and Intervals: When you need to keep track of timers or intervals without triggering renders.
- Avoiding Re-renders: For values that are needed in a component but do not require the component to re-render when they change.
Important Points
- Initial Value: The initial value passed to
useRef
only sets the .current
property when the component mounts. It does not reset on re-renders. - Mutable: The object returned by
useRef
is mutable, meaning you can change .current
without causing a re-render. - Not for Rendering Logic: Do not use
useRef
to store values that will determine what to render. Use state for that purpose.
What is the DOM?
The DOM (Document Object Model) is like a map or blueprint of a webpage. It is a way for the browser to understand and interact with the content of a webpage.
When a webpage is loaded in the browser, the browser creates a DOM of the page. The DOM represents all the HTML elements (like text, images, buttons, etc.) as objects in a tree structure. This allows you to use JavaScript to access and change things on the page.
Key Differences
Feature Callback Promise Definition A function passed as an argument to another function and executed later. An object representing a future value or error. Syntax Simple, but can lead to "callback hell" with deeply nested functions. More structured and readable syntax, especially when using .then()
and .catch()
. Error Handling Errors are handled manually within the callback. Errors can be easily caught using .catch()
, making it easier to manage. Chaining Can be difficult to manage and read when callbacks are deeply nested (callback hell). Promises make chaining easier with .then()
for sequential operations. Return Value Callbacks do not return values; instead, the result is passed to the callback function. Promises return another promise, making it easy to chain multiple operations. Built-in Support Basic function that doesn't have advanced features. Promises have built-in methods like .then()
, .catch()
, and finally()
.
What is Callback Hell?
Callback Hell refers to a situation in JavaScript where multiple asynchronous operations are handled using callbacks, resulting in deeply nested callback functions. This makes the code difficult to read, understand, and maintain. It’s often visualized as a pyramid of doom due to its arrow-like indentation that keeps increasing with each level of nesting.
Why Does Callback Hell Happen?
When dealing with asynchronous tasks like making API calls, reading files, or setting timers, we often pass a callback function to handle the response after the task is completed. If there are multiple asynchronous operations that depend on each other, these callbacks get nested inside one another.
As the number of nested callbacks grows, the code becomes hard to read, harder to debug, and more prone to errors. This is referred to as callback hell.
Example of Callback Hell
Let's say you want to perform three asynchronous tasks sequentially. Using callbacks, the code might look like this:
doTask1(function(result1) { console.log(result1);
doTask2(function(result2) {
console.log(result2);
doTask3(function(result3) {
console.log(result3);
// More nested callbacks if needed...
}, function(error) {
console.error("Error in Task 3:", error);
});
}, function(error) {
console.error("Error in Task 2:", error);
});
}, function(error) {
console.error("Error in Task 1:", error);
});
As you can see, this creates a deeply nested structure, which:
- Makes it hard to read.
- Increases the chances of errors.
- Becomes difficult to debug and maintain.
This is called callback hell because the indentation keeps increasing, making the code look messy and unmanageable.
Problems with Callback Hell:
- Readability: Deep nesting of functions makes the code harder to read.
- Maintainability: Adding more logic or modifying the existing logic becomes difficult, as everything is tightly coupled.
- Error Handling: Managing errors in deeply nested callbacks can become complex and error-prone.
- Scalability: As more async operations are added, the nesting increases, making the code even harder to scale and manage.
How to Avoid Callback Hell
Using Promises:
Promises help flatten the nested structure and make the code more readable. Instead of nesting callbacks, promises use .then()
and .catch()
for sequential and error handling.
doTask1() .then(result1 => {
console.log(result1);
return doTask2();
})
.then(result2 => {
console.log(result2);
return doTask3();
})
.then(result3 => {
console.log(result3);
})
.catch(error => {
console.error("Error:", error);
});
This structure is much cleaner, easier to read, and manage compared to nested callbacks.
Using async
and await
:
The async
and await
syntax makes asynchronous code look like synchronous code, which is even more readable and less prone to callback hell.
async function executeTasks() { try {
const result1 = await doTask1();
console.log(result1);
const result2 = await doTask2();
console.log(result2);
const result3 = await doTask3();
console.log(result3);
} catch (error) {
console.error("Error:", error);
}
}
executeTasks();
Here’s a simple explanation and example of each concept: map
, reduce
, call
, bind
, and apply
in JavaScript.
1. map
:
- What it does: The
map
method creates a new array by applying a function to each element of an existing array. - When to use: Use
map
when you want to transform every element of an array in some way.
Example:
const numbers = [1, 2, 3, 4];const doubled = numbers.map(num => num * 2);
console.log(doubled); // [2, 4, 6, 8]
- Explanation:
- Each number in the
numbers
array is doubled using num * 2
. - The result is a new array
[2, 4, 6, 8]
.
2. reduce
:
- What it does: The
reduce
method reduces an array to a single value by applying a function to each element and accumulating the result. - When to use: Use
reduce
when you need to calculate a sum, product, or aggregate value from an array.
Example:
const numbers = [1, 2, 3, 4];const sum = numbers.reduce((accumulator, current) => accumulator + current, 0);
console.log(sum); // 10
- Explanation:
- The function takes two arguments: the
accumulator
(the running total) and the current
value from the array. - It adds each number to the accumulator, starting with
0
, to get the sum 10
.
3. call
:
- What it does: The
call
method invokes a function and allows you to set the this
value explicitly. - When to use: Use
call
when you want to call a function and specify the context (this
) for it.
Example:
const person = { name: 'Anjali',
greet: function() {
console.log('Hello, ' + this.name);
}
};
const anotherPerson = { name: 'Kadam' };
person.greet.call(anotherPerson); // Hello, Kadam
- Explanation:
- Normally,
this
refers to person
inside greet
. - By using
call
, you set this
to anotherPerson
, so it prints "Hello, Kadam".
4. bind
:
- What it does: The
bind
method creates a new function that, when called, has this
set to the value you provide. - When to use: Use
bind
when you want to create a new function with a fixed this
value.
Example:
const person = { name: 'Anjali',
greet: function() {
console.log('Hello, ' + this.name);
}
};
const greetAnjali = person.greet.bind(person);
greetAnjali(); // Hello, Anjali
- Explanation:
bind
creates a new function greetAnjali
, where this
is always bound to person
.- Even if
greetAnjali
is called in different contexts, it will always refer to person
.
5. apply
:
- What it does: The
apply
method works like call
, but it takes arguments as an array instead of individually. - When to use: Use
apply
when you want to call a function and pass arguments as an array.
Example:
function introduce(name, age) { console.log(`My name is ${name} and I am ${age} years old.`);
}
const info = ['Anjali', 25];
introduce.apply(null, info); // My name is Anjali and I am 25 years old.
- Explanation:
- The
introduce
function takes two arguments: name
and age
. - Using
apply
, we pass them as an array info
.
Summary of Differences:
call
: Invokes a function with arguments passed individually and sets the this
context.apply
: Invokes a function with arguments passed as an array and sets the this
context.bind
: Creates a new function with a fixed this
context, to be invoked later.map
: Transforms every element of an array and returns a new array.reduce
: Aggregates array elements into a single value.
In JavaScript, for...in
and for...of
are both used to loop over elements, but they behave differently based on the type of data structure you're working with.
1. for...in
loop
- Purpose: It is used to iterate over the keys (properties) of an object or the indexes of an array.
- Usage: It iterates over the enumerable properties of an object or array.
Example 1: for...in
with an Object
const person = { name: 'John', age: 30, city: 'New York' };
for (let key in person) {
console.log(key); // Output: name, age, city
console.log(person[key]); // Output: John, 30, New York
}
Here, for...in
iterates over the keys (name
, age
, city
) of the object person
.
Example 2: for...in
with an Array
const arr = [10, 20, 30];
for (let index in arr) {
console.log(index); // Output: 0, 1, 2 (the array indices)
console.log(arr[index]); // Output: 10, 20, 30
}
With arrays, for...in
loops through the indexes of the array (0, 1, 2
).
2. for...of
loop
- Purpose: It is used to iterate over the values of an iterable object, such as an array, string, or any iterable object.
- Usage: It iterates over the actual values of an iterable, like array elements, string characters, or other iterable values.
Example 1: for...of
with an Array
javascriptconst arr = [10, 20, 30];
for (let value of arr) {
console.log(value); // Output: 10, 20, 30
}
Here, for...of
iterates over the values (10, 20, 30
) of the array arr
.
Example 2: for...of
with a String
javascriptconst str = 'Hello';
for (let char of str) {
console.log(char); // Output: H, e, l, l, o
}
With strings, for...of
loops through the characters of the string (H, e, l, l, o
).
Key Differences
Feature for...in
for...of
Iterates Over Keys (object properties) or array indexes Values of arrays, strings, or iterables Suitable For Objects (enumerating properties) Arrays, strings, or iterable objects Example with Array Iterates over indexes (0, 1, 2
) Iterates over values (10, 20, 30
)
Summary:
for...in
: Loops through keys or indexes (best used for objects).for...of
: Loops through values (best used for arrays, strings, and other iterables).
Difference between ES5 and ES6
Here is the comparison between ES5 and ES6 in table format:
Feature ES5 ES6 Variable Declarations var
(function-scoped, can be redeclared)let
, const
(block-scoped, no redeclaration)Function Syntax Regular functions, dynamic this
binding Arrow functions, lexically bound this
String Interpolation Manual concatenation using +
Template literals with ${}
and backticks Destructuring Manual extraction of array/object properties Array/Object destructuring Classes Constructor functions and prototypes class
syntax with constructor
, extends
for inheritanceModules No native support (used external libraries) Native support with import
/export
Default Parameters Manually set defaults inside the function Native support for default parameters Rest/Spread Operators Use apply
and concat
...rest
to collect arguments, ...spread
to spread arrays/objectsPromises Callback-based asynchronous code Native support with Promise
, then
/catch
for async handling Iterators and Generators No native support Generator functions using function*
and yield
Diff between regular and arrow function
Feature Regular Functions Arrow Functions Syntax Declared using the function
keyword. More concise syntax, using the =>
arrow operator. this
BindingHas its own this
context based on how the function is called (dynamic). Lexically binds this
(inherits this
from the surrounding scope). Constructors Can be used as constructors with new
. Cannot be used as constructors (no new
keyword usage). Arguments Object Has access to the arguments
object. Does not have its own arguments
object (you would need to use rest parameters ...args
instead). Return Statements Requires an explicit return
statement unless using single-line implicit return. Single-line functions have implicit return
, but multi-line requires return
explicitly. Hoisting Function declarations are hoisted to the top of their scope. Arrow functions defined as variables are not hoisted. Usage as Methods Commonly used for methods in objects, but this
must be managed. Not ideal for methods that need dynamic this
, as it inherits this
from its surrounding context. Prototype Regular functions have a prototype
property. Arrow functions do not have a prototype
property. Use Cases Good for most function declarations, especially where dynamic this
or hoisting is needed. Best for concise functions and callbacks where lexical this
is desired.
Lifecycle method of class and functional component :
command to remove project directory in vs
// Remove-Item -Recurse -Force "whatsapp-web-clone"
- Get link
- X
- Other Apps
Comments
Post a Comment