code examples
https://roadsidecoder.hashnode.dev/?source=top_nav_blog_home
https://alok722.github.io/namaste-javascript-notes/dist/lectures.html
https://github.com/mukeshphulwani66/javascript-interview-questions
useState
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
useEffect
import React, { useState, useEffect } from 'react';
function DataFetcher() {
const [data, setData] = useState(null);
useEffect(() => {
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => setData(data))
.catch(error => console.error(error));
}, []);
return (
<div>
{data ? (
<ul>
{data.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
) : (
<p>Loading...</p>
)}
</div>
);
}
import React, { useState, useEffect } from 'react';
function DataFetcher() {
const [data, setData] = useState(null);
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch('https://api.example.com/data');
const jsonData = await response.json();
setData(jsonData);
} catch (error) {
console.error(error);
}
};
fetchData();
}, []);
return (
<div>
{data ? (
<ul>
{data.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
) : (
<p>Loading...</p>
)}
</div>
);
}
export default DataFetcher;
//map
//{} --> return
//() --> no return
useRef
import React, { useRef } from 'react';
function FocusInput() {
// Create a ref using the useRef hook
const inputRef = useRef(null);
// Function to focus on the input element
const focusInput = () => {
inputRef.current.focus();
};
return (
<div>
{/* Attach the ref to the input element */}
<input type="text" ref={inputRef} />
{/* Button to focus on the input element */}
<button onClick={focusInput}>Focus Input</button>
</div>
);
}
export default FocusInput;
useContext
import React, { useContext } from 'react';
const ThemeContext = React.createContext('light');
function ThemedComponent() {
const theme = useContext(ThemeContext);
return <p>Current theme: {theme}</p>;
}
useReducer
import React, { useReducer } from 'react';
const initialState = { count: 0 };
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
<button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>
</div>
);
}
useMemo and useCallback
Sure! Let's see real-world examples of useMemo
and useCallback
hooks in a React application.
1. Real-world example ofuseMemo
:
Suppose you have a component that renders a list of items, and the list is fetched from an API. You want to memoize the list so that it's only fetched once and reused when the component re-renders. Here's how you can use useMemo
for this:
import React, { useState, useEffect, useMemo } from 'react';
import axios from 'axios';
function ItemList() {
const [items, setItems] = useState([]);
useEffect(() => {
axios.get('https://api.example.com/items')
.then(response => setItems(response.data))
.catch(error => console.error(error));
}, []);
const memoizedItems = useMemo(() => items, [items]);
return (
<div>
<h1>Item List</h1>
<ul>
{memoizedItems.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
</div>
);
}
export default ItemList;
In this example:
We fetch the list of items using Axios in the
useEffect
hook, and store them in theitems
state.We use
useMemo
to memoize theitems
array, so that it's only recomputed when theitems
state changes.The
memoizedItems
variable holds the memoized value ofitems
, which is then used in the rendering.
2. Real-world example ofuseCallback
:
Suppose you have a component that renders a list of buttons, and each button performs some action when clicked. You want to avoid recreating the action function every time the component re-renders. Here's how you can use useCallback
for this:
import React, { useCallback } from 'react';
function ButtonList() {
const handleClick = useCallback((id) => {
console.log(`Button ${id} clicked`);
// Do something with the clicked button
}, []);
return (
<div>
<h1>Button List</h1>
<button onClick={() => handleClick(1)}>Button 1</button>
<button onClick={() => handleClick(2)}>Button 2</button>
<button onClick={() => handleClick(3)}>Button 3</button>
</div>
);
}
export default ButtonList;
In this example:
We define the
handleClick
function inside theuseCallback
hook.The
handleClick
function is only recreated if its dependencies change. In this case, it has no dependencies, so it's only created once.We pass the
handleClick
function as theonClick
handler for each button.
In React, the useState
hook is not asynchronous in itself. When you call useState
to update a state variable, the update to the state is actually synchronous. However, the re-rendering of the component that occurs as a result of the state update is asynchronous.
useState is async ? why?
Here's how it works:
Synchronous State Update: When you call
useState
to update a state variable, React immediately updates the state variable and re-renders the component synchronously.Asynchronous Re-rendering: React batches multiple state updates and performs them in a single render cycle to optimize performance. This batching mechanism allows React to schedule state updates and perform them in a more efficient manner. As a result, the actual re-rendering of the component may occur asynchronously, after the state updates have been applied.
Because of this batching mechanism, you can't rely on the updated state value immediately after calling useState
. If you need to perform an action after the state has been updated, you can use the useEffect
hook with the state variable as a dependency.
Here's an example to illustrate this behavior:
import React, { useState, useEffect } from 'react';
function ExampleComponent() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log('Component re-rendered with count:', count);
}, [count]);
const handleClick = () => {
setCount(count + 1);
console.log('Count after setCount:', count); // This may not reflect the updated count
};
return (
<div>
<p>Count: {count}</p>
<button onClick={handleClick}>Increment</button>
</div>
);
}
export default ExampleComponent;
In this example, even though setCount
updates the count
state synchronously, the console.log
statement immediately after setCount
may not reflect the updated value of count
because the re-rendering of the component may occur asynchronously. Instead, the updated value of count
will be reflected in the useEffect
hook, which runs after the component has been re-rendered.
To get the updated data in the console.log
statement after calling setCount
, you can utilize the fact that setState
functions in React are asynchronous. You can use the useEffect
hook to log the updated count value after the component re-renders due to the state update. Here's how you can modify the code to achieve this:
import React, { useState, useEffect } from 'react';
function ExampleComponent() {
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(prevCount => {
const updatedCount = prevCount + 1;
console.log('Count after setCount:', updatedCount);
return updatedCount;
});
};
useEffect(() => {
console.log('Component re-rendered with count:', count);
}, [count]);
return (
<div>
<p>Count: {count}</p>
<button onClick={handleClick}>Increment</button>
</div>
);
}
export default ExampleComponent;
In this modified code:
We've updated the
handleClick
function to use the functional form ofsetCount
, which receives the previous state value as an argument (prevCount
).Inside the
setCount
function, we compute the updated count (updatedCount
) by incrementing theprevCount
by 1.We then log the
updatedCount
to the console immediately after setting the state. This will log the correct updated count value.Additionally, we've kept the
useEffect
hook to log the updated count after the component re-renders, which serves as an additional check.
Controlled and Uncontrolled component
Certainly! Here's a simple example demonstrating the difference between controlled and uncontrolled components in React:
Controlled Component:
import React, { useState } from 'react';
function ControlledComponent() {
const [value, setValue] = useState('');
const handleChange = (event) => {
setValue(event.target.value);
};
return (
<div>
<input type="text" value={value} onChange={handleChange} />
<p>Value: {value}</p>
</div>
);
}
export default ControlledComponent;
In this example, the input field is a controlled component because its value is controlled by the state (value
variable). Whenever the input value changes (onChange
event), the handleChange
function updates the state using setValue
. This ensures that React has full control over the input value.
Uncontrolled Component:
import React, { useRef } from 'react';
function UncontrolledComponent() {
const inputRef = useRef(null);
const handleClick = () => {
console.log('Input value:', inputRef.current.value);
};
return (
<div>
<input type="text" ref={inputRef} />
<button onClick={handleClick}>Get Value</button>
</div>
);
}
export default UncontrolledComponent;
In this example, the input field is an uncontrolled component because its value is not controlled by React state. Instead, we use a ref (inputRef
) to access the DOM node directly. When the button is clicked, we access the input value using inputRef.current.value
. Since React doesn't manage the input value, it's considered an uncontrolled component.
Both controlled and uncontrolled components have their use cases, and the choice between them depends on the specific requirements of your application. Controlled components are typically preferred in most cases as they provide a more predictable and controlled way of managing form data. Uncontrolled components can be useful when integrating with non-React libraries or when you need direct access to the DOM.
Lifecycle methods in react class component?
In React class components, lifecycle methods are special methods that are automatically invoked by React at specific points during the component's lifecycle. Here are some commonly used lifecycle methods along with simple code examples:
constructor()
:The constructor method is called when the component is initialized.
Example:
import React, { Component } from 'react'; class MyComponent extends Component { constructor(props) { super(props); this.state = { count: 0 }; } render() { return <div>{this.state.count}</div>; } }
componentDidMount()
:Called after the component is mounted (i.e., added to the DOM).
Example:
import React, { Component } from 'react'; class MyComponent extends Component { componentDidMount() { console.log('Component mounted'); } render() { return <div>Hello, World!</div>; } }
componentDidUpdate()
:Called after the component's state or props change and the component re-renders.
Example:
import React, { Component } from 'react'; class MyComponent extends Component { componentDidUpdate(prevProps, prevState) { console.log('Component updated'); } render() { return <div>{this.props.message}</div>; } }
componentWillUnmount()
:Called before the component is unmounted (i.e., removed from the DOM).
Example:
import React, { Component } from 'react'; class MyComponent extends Component { componentWillUnmount() { console.log('Component will unmount'); } render() { return <div>Hello, World!</div>; } }
shouldComponentUpdate()
:Called before the component re-renders, allowing you to control whether the component should update or not.
Example:
import React, { Component } from 'react'; class MyComponent extends Component { shouldComponentUpdate(nextProps, nextState) { return this.props.value !== nextProps.value; } render() { return <div>{this.props.value}</div>; } }
These are some of the most commonly used lifecycle methods in React class components. They provide hooks for performing actions at different stages of a component's lifecycle, such as initialization, mounting, updating, and unmounting. However, it's worth noting that with the introduction of React hooks in functional components, many of these lifecycle methods have equivalent or alternative implementations using hooks.
In React functional components, you can achieve similar functionality to class component lifecycle methods using React hooks. Here's how you can translate the class component lifecycle methods to equivalent hooks:
constructor()
andcomponentDidMount()
:In functional components, you can initialize state using the
useState
hook and perform side effects (such as data fetching) using theuseEffect
hook with an empty dependency array.Example:
import React, { useState, useEffect } from 'react'; function MyComponent() { const [count, setCount] = useState(0); useEffect(() => { console.log('Component mounted'); }, []); // Empty dependency array means this effect only runs once after the initial render return <div>{count}</div>; }
componentDidUpdate()
:In functional components, you can achieve similar behavior to
componentDidUpdate()
by using theuseEffect
hook with dependencies.Example:
import React, { useState, useEffect } from 'react'; function MyComponent({ message }) { useEffect(() => { console.log('Component updated'); }, [message]); // Only re-run the effect if message prop changes return <div>{message}</div>; }
componentWillUnmount()
:In functional components, you can perform cleanup tasks by returning a function from the
useEffect
hook.Example:
import React, { useState, useEffect } from 'react'; function MyComponent() { useEffect(() => { console.log('Component mounted'); return () => { console.log('Component will unmount'); }; }, []); // Empty dependency array means this effect only runs once after the initial render return <div>Hello, World!</div>; }
shouldComponentUpdate()
:In functional components, you can use the
React.memo()
higher-order component or theuseMemo()
hook to memoize the component and control whether it should re-render.Example with
React.memo()
:import React, { memo } from 'react'; const MyComponent = memo(({ value }) => { console.log('Rendering MyComponent'); return <div>{value}</div>; }); export default MyComponent;
Example with
useMemo()
:import React, { useMemo } from 'react'; function MyComponent({ value }) { const memoizedValue = useMemo(() => value, [value]); console.log('Rendering MyComponent'); return <div>{memoizedValue}</div>; } export default MyComponent;
These examples demonstrate how to achieve similar functionality to class component lifecycle methods using React hooks in functional components. Hooks provide a more concise and flexible way to manage component lifecycle and state in functional components.
Hoc
Sure, here's a very simple Higher-Order Component (HOC) example in a functional component:
import React from 'react';
// Define a higher-order component
const withUpperCase = (WrappedComponent) => {
// Return a functional component
return (props) => {
// Transform the props if needed
const modifiedProps = {
...props,
text: props.text.toUpperCase() // Example transformation: converting text to uppercase
};
// Render the wrapped component with modified props
return <WrappedComponent {...modifiedProps} />;
};
};
// Example functional component
const MyComponent = ({ text }) => {
return <div>{text}</div>;
};
// Enhance MyComponent with the withUpperCase HOC
const MyEnhancedComponent = withUpperCase(MyComponent);
// Usage of the enhanced component
const App = () => {
return <MyEnhancedComponent text="Hello, World!" />;
};
export default App;
In this example:
We define a simple functional component
MyComponent
that takes atext
prop and renders it.We define a Higher-Order Component
withUpperCase
, which takes a component as an argument and returns a modified version of that component. In this case, it transforms thetext
prop to uppercase.We enhance
MyComponent
with thewithUpperCase
HOC by wrapping it withwithUpperCase(MyComponent)
, resulting in a new component calledMyEnhancedComponent
.Finally, we use
MyEnhancedComponent
in theApp
component, passing thetext
prop "Hello, World!".
This example demonstrates a simple use case of a Higher-Order Component in a functional component, where the HOC modifies the props of the wrapped component before rendering it.
The output of the provided code will be a rendered <div>
element containing the text "HELLO, WORLD!".
Here's a breakdown of how the code works:
Definition of
MyComponent
:MyComponent
is a simple functional component that takes atext
prop and renders it inside a<div>
element.
Definition of
withUpperCase
HOC:withUpperCase
is a Higher-Order Component (HOC) that takes a component (WrappedComponent
) as an argument.It returns a new functional component that:
Receives props (
props
) as input.Modifies the
text
prop of the input props to be in uppercase.Renders the
WrappedComponent
with the modified props.
Enhancement of
MyComponent
withwithUpperCase
HOC:MyEnhancedComponent
is created by enhancingMyComponent
with thewithUpperCase
HOC. This meansMyEnhancedComponent
will receive props, pass them throughwithUpperCase
to modify them (in this case, convertingtext
prop to uppercase), and then renderMyComponent
with the modified props.
Usage of
MyEnhancedComponent
inApp
component:- The
App
component rendersMyEnhancedComponent
, passing thetext
prop "Hello, World!".
- The
Since MyEnhancedComponent
modifies the text
prop to be in uppercase before rendering MyComponent
, the rendered output will be a <div>
element containing the text "HELLO, WORLD!".
Promise Example
Sure, here's a simple example of a promise in JavaScript:
// Create a promise
const myPromise = new Promise((resolve, reject) => {
// Simulate an asynchronous operation (e.g., fetching data)
setTimeout(() => {
// Resolve the promise with a value (success)
resolve('Data fetched successfully');
// Reject the promise with an error (failure)
// reject('Error fetching data');
}, 2000);
});
// Consuming the promise
myPromise.then((data) => {
console.log(data); // Output: "Data fetched successfully"
}).catch((error) => {
console.error(error); // Output: "Error fetching data"
});
In this example:
We create a new promise
myPromise
with thenew Promise()
constructor.Inside the promise executor function, we simulate an asynchronous operation using
setTimeout()
to resolve or reject the promise after a delay of 2000 milliseconds.If the asynchronous operation is successful, we call
resolve()
with a value ('Data fetched successfully').If there's an error during the operation, we call
reject()
with an error message ('Error fetching data').We consume the promise using the
then()
method, which takes two callback functions as arguments: one for handling the resolved value (data
) and one for handling any errors (error
). If the promise is resolved successfully, the first callback is invoked, and if it's rejected, the second callback is invoked.We use the
catch()
method to handle any errors that occur during the asynchronous operation.
This is a basic example of how promises work in JavaScript to handle asynchronous operations and manage their outcomes.
converted above code to Async/await
Here's the provided code converted to use async/await syntax:
// Create an async function to perform asynchronous operation
const fetchData = async () => {
// Wrap the asynchronous operation in a try-catch block
try {
// Simulate an asynchronous operation (e.g., fetching data) using setTimeout
const data = await new Promise((resolve, reject) => {
setTimeout(() => {
// Resolve the promise with a value (success)
resolve('Data fetched successfully');
// Reject the promise with an error (failure)
// reject('Error fetching data');
}, 2000);
});
// Log the fetched data
console.log(data); // Output: "Data fetched successfully"
} catch (error) {
// Log any errors that occur during the asynchronous operation
console.error(error); // Output: "Error fetching data"
}
};
// Call the async function to consume the promise
fetchData();
In this code:
We define an asynchronous function
fetchData
using theasync
keyword. Inside this function, we useawait
to pause the execution until the promise resolves or rejects.We wrap the asynchronous operation (simulated with
setTimeout
) inside a try-catch block to handle any errors that may occur during the operation.Instead of using
.then()
and.catch()
to handle promise resolution and rejection, we useawait
to wait for the promise to settle, and then handle the resolved value or catch any errors directly inside thetry
block.We call the
fetchData
function to initiate the asynchronous operation.
Callback hell---> overcome it using promises ---> refactored chaining using asyn await
Callback hell occurs when you have multiple nested callbacks, often in asynchronous operations, making the code hard to read and maintain. One way to overcome callback hell is by using named functions or by modularizing the code. Here's a simple example illustrating how to overcome callback hell using named functions:
// Simulated asynchronous functions
function asyncFunction1(callback) {
setTimeout(() => {
console.log('Async function 1');
callback();
}, 1000);
}
function asyncFunction2(callback) {
setTimeout(() => {
console.log('Async function 2');
callback();
}, 3000);
}
function asyncFunction3(callback) {
setTimeout(() => {
console.log('Async function 3');
callback();
}, 5000);
}
// Usage: Avoiding callback hell with named functions
asyncFunction1(() => {
asyncFunction2(() => {
asyncFunction3(() => {
console.log('All async functions completed');
});
});
});
// Usage: Using Promises to avoid callback hell
asyncFunction1()
.then(() => asyncFunction2())
.then(() => asyncFunction3())
.then(() => {
console.log('All async functions completed');
});
// Usage: Using async/await to avoid nested Promises
async function runAsyncFunctions() {
await asyncFunction1();
await asyncFunction2();
await asyncFunction3();
console.log('All async functions completed');
}
// Call the async function
runAsyncFunctions();
In this code:
We define three simulated asynchronous functions (
asyncFunction1
,asyncFunction2
,asyncFunction3
) that take a callback function as an argument.Each asynchronous function executes its task after a timeout and calls the provided callback when done.
Instead of nesting callbacks directly, we use named functions for each callback.
By using named functions, the code becomes more readable and avoids the deep nesting of callbacks, making it easier to understand and maintain.
output:
Async function 1 --> 1sec
Async function 2 --> 3sec
Async function 3 --> 5sec
All async functions completed --> immediately execute
Normal vs Arrow Fn
Arrow functions and normal functions in JavaScript have some differences in their behavior and syntax. Here's a comparison between the two with code examples:
Syntax:
Arrow function syntax is more concise compared to normal function syntax.
Arrow functions use the
=>
syntax.Normal functions are defined using the
function
keyword.
// Arrow function syntax
const arrowFunction = () => {
// Function body
};
// Normal function syntax
function normalFunction() {
// Function body
}
this
Binding:Arrow functions do not bind their own
this
value. They lexically inheritthis
from the surrounding code.Normal functions bind their own
this
value, which can change based on how they are called.
const obj = {
value: 10,
arrowFunction: () => {
console.log(this.value); // undefined
},
normalFunction: function() {
console.log(this.value); // 10
}
};
Arguments Object:
Arrow functions do not have their own
arguments
object.Normal functions have their own
arguments
object, which contains all the arguments passed to the function.
const arrowFunction = (...args) => {
console.log(arguments); // ReferenceError: arguments is not defined
};
const normalFunction = function() {
console.log(arguments); // Arguments [1, 2, 3]
};
arrowFunction(1, 2, 3);
normalFunction(1, 2, 3);
Use Cases:
Arrow functions are commonly used for concise one-liner functions, callback functions, and for maintaining lexical
this
context.Normal functions are more flexible and are used in various scenarios, including object methods, constructors, and when you need access to the
arguments
object.
Overall, both arrow functions and normal functions have their own use cases and advantages. It's important to understand their differences and choose the appropriate type of function based on the specific requirements of your code.
Pure and Impure Fn
Pure functions and impure functions are concepts in functional programming that describe functions based on their behavior and side effects. Here's an explanation of each with code examples:
Pure Functions:
Pure functions are functions that always return the same output for the same input and do not have any side effects.
They do not modify the state of variables outside their scope or have any observable effects on the program's execution other than computing a result.
// Pure function example
function add(a, b) {
return a + b;
}
const result = add(3, 5); // 8
In this example, the add
function always returns the same result (a + b
) for the same inputs a
and b
. It does not modify any external variables or have any side effects.
Impure Functions:
Impure functions are functions that have side effects or produce different results for the same input.
They may modify external state or perform I/O operations, such as reading from or writing to files, making network requests, or updating the DOM.
// Impure function example
let total = 0;
function addToTotal(value) {
total += value;
}
addToTotal(10);
console.log(total); // 10
In this example, the addToTotal
function modifies the external variable total
by adding the value
to it. It has a side effect on the program's state (changing the value of total
) and does not always produce the same result for the same input.
Pure functions are preferred in functional programming because they are predictable, easier to reason about, and facilitate testing and debugging. Impure functions are still necessary in many cases, especially when dealing with I/O operations or managing state in applications. However, it's important to minimize their use and isolate them as much as possible to maintain code clarity and predictability.
Scope, Lexical scope
Sure, here's an example demonstrating lexical scope in JavaScript:
// Global variable
let globalVar = 'I am global';
function outerFunction() {
// Outer function variable
let outerVar = 'I am outer';
function innerFunction() {
// Inner function scope variable
let innerVar = 'I am inner';
console.log(innerVar); // Output: "I am inner"
console.log(outerVar); // Output: "I am outer"
console.log(globalVar); // Output: "I am global"
}
innerFunction();
}
outerFunction();
// console.log(outerVar); // Trying to access outerVar here will result in a ReferenceError
// console.log(innerVar); // Trying to access innerVar here will result in a ReferenceError
console.log(globalVar); // Output: "I am global"
In this example:
We have a global variable
globalVar
declared outside any function.Inside
outerFunction
, we have another variableouterVar
declared.Inside
innerFunction
, we can access theouterVar
variable from its enclosingouterFunction
. This ability to access variables from outer functions is called lexical scoping.Both
innerFunction
andouterFunction
have access to the global variableglobalVar
.However, variables declared inside
innerFunction
orouterFunction
are not accessible outside their respective functions due to lexical scoping rules.Lexical scoping means that the scope of a variable is determined by its location within the source code (i.e., its lexical context) and cannot be influenced by how or where the function is called.
Closure
Sure, here's an example demonstrating closures in JavaScript:
function outerFunction(outerValue) {
// Inner function defined inside outer function
function innerFunction(innerValue) {
// innerFunction has access to both outerValue and innerValue
return outerValue + innerValue;
}
// Returning innerFunction from outerFunction
return innerFunction;
}
// Creating a closure by calling outerFunction and storing the returned innerFunction
const closure = outerFunction(10);
// The returned innerFunction retains access to the outerValue (10) from its enclosing scope
// and can still be called even though outerFunction has already finished executing
const result = closure(5); // Output: 15
console.log(result);
Explanation:
In this example,
outerFunction
is defined with a parameterouterValue
.Inside
outerFunction
, another functioninnerFunction
is defined.innerFunction
has access to theouterValue
parameter of its enclosingouterFunction
. This access to variables from the outer scope, even after the outer function has finished executing, is known as a closure.outerFunction
returnsinnerFunction
, creating a closure.We then call
outerFunction
with an argument of10
, which setsouterValue
to10
. This creates a closure whereinnerFunction
has access toouterValue
(which is10
).We store the returned
innerFunction
in a variable calledclosure
.Later, we can call
closure
with an argument of5
. This adds5
to theouterValue
(which is10
), resulting in15
.
Closures are powerful and useful in scenarios where you need to retain access to variables from an enclosing scope even after the function that defined those variables has finished executing.
Call,Apply and Bind
const person = {
fullName: function(city, country) {
return this.firstName + ' ' + this.lastName + ', ' + city + ', ' + country;
}
};
const john = {
firstName: 'John',
lastName: 'Doe'
};
const jane = {
firstName: 'Jane',
lastName: 'Doe'
};
// Using call
console.log(person.fullName.call(john, 'New York', 'USA')); // Output: "John Doe, New York, USA"
console.log(person.fullName.call(jane, 'Los Angeles', 'USA')); // Output: "Jane Doe, Los Angeles, USA"
// Using apply
const cityAndCountry = ['London', 'UK'];
console.log(person.fullName.apply(john, cityAndCountry)); // Output: "John Doe, London, UK"
console.log(person.fullName.apply(jane, cityAndCountry)); // Output: "Jane Doe, London, UK"
// Using bind
const johnFullName = person.fullName.bind(john, 'Boston', 'USA');
console.log(johnFullName()); // Output: "John Doe, Boston, USA"
const janeFullName = person.fullName.bind(jane, 'Chicago', 'USA');
console.log(janeFullName()); // Output: "Jane Doe, Chicago, USA"
Explanation:
We have an object
person
with a methodfullName
that accepts two additional arguments,city
andcountry
.We have two other objects
john
andjane
representing different persons.We demonstrate the use of
call
to invoke thefullName
method ofperson
withjohn
andjane
objects and pass thecity
andcountry
arguments.We use
apply
similarly tocall
, but we pass arguments as an array.We use
bind
to create new functions (johnFullName
andjaneFullName
) with pre-definedcity
andcountry
arguments. When these new functions are invoked later, they only require the remaining arguments (firstName
andlastName
) to be provided.
Call by value and Call by reference
In JavaScript, understanding "call by value" and "call by reference" is crucial for understanding how data is passed to functions. However, JavaScript uses a mechanism that behaves somewhat differently from traditional "call by value" or "call by reference". Instead, JavaScript uses "pass by value" and "pass by reference".
Pass by Value:
When a variable is passed by value to a function, a copy of the variable's value is passed to the function.
Modifying the parameter inside the function does not affect the original variable outside the function.
let num = 10;
function modifyValue(value) {
value = 20;
}
modifyValue(num);
console.log(num); // Output: 10 (unchanged)
Pass by Reference:
When an object is passed by reference to a function, a reference to the original object is passed to the function.
Modifying properties of the object inside the function will affect the original object outside the function.
let person = { name: 'John' };
function modifyObject(obj) {
obj.name = 'Jane';
}
modifyObject(person);
console.log(person.name); // Output: "Jane" (modified)
In JavaScript:
Primitive data types (like numbers, strings, boolean) are passed by value.
Objects (including arrays and functions) are passed by reference.
So, JavaScript behaves more like "pass by sharing", where the function receives a reference to the original value (for objects) or a copy of the original value (for primitives), but cannot modify the original binding of the variable itself.
In summary, while the terms "pass by value" and "pass by reference" are commonly used, in JavaScript, it's more accurate to say "pass by value" for primitives and "pass by reference" for objects.
Event Propogation (Event capturing,Event Bubbling)
Event bubbling and event capturing are two different mechanisms used by the DOM to handle events propagating through nested elements. Let's demonstrate both with a simple HTML structure and JavaScript code.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Event Bubbling vs Capturing</title>
</head>
<body>
<div id="outer">
<div id="middle">
<div id="inner">Click me!</div>
</div>
</div>
<script>
const outer = document.getElementById('outer');
const middle = document.getElementById('middle');
const inner = document.getElementById('inner');
outer.addEventListener('click', () => {
console.log('Outer clicked (bubbling)');
}, false); // Event bubbling (default)
middle.addEventListener('click', () => {
console.log('Middle clicked (bubbling)');
}, false); // Event bubbling (default)
inner.addEventListener('click', () => {
console.log('Inner clicked (bubbling)');
}, false); // Event bubbling (default)
outer.addEventListener('click', () => {
console.log('Outer clicked (capturing)');
}, true); // Event capturing (reverse order)
middle.addEventListener('click', () => {
console.log('Middle clicked (capturing)');
}, true); // Event capturing (reverse order)
inner.addEventListener('click', () => {
console.log('Inner clicked (capturing)');
}, true); // Event capturing (reverse order)
</script>
</body>
</html>
Explanation:
The HTML contains three nested
<div>
elements:outer
,middle
, andinner
.We attach click event listeners to each element.
By default, event listeners use event bubbling, where the event starts at the target element and then "bubbles" up through its ancestors (outer elements) to the document root.
We also attach event listeners with capturing enabled (
useCapture
set totrue
). Event capturing occurs in the reverse order, starting from the document root down to the target element.When you click on the innermost
div
, you'll see both the bubbling and capturing phases in the console logs. The bubbling phase logs start from the innermost element and propagate up to the outermost element, while the capturing phase logs start from the outermost element and propagate down to the innermost element.
The order of logs in this scenario will depend on the event propagation phase (bubbling or capturing) and the order of the event listeners. Let's analyze it:
For each event (click) on the innermost
div
:Capturing Phase: Event listeners attached with
useCapture
set totrue
will fire in the reverse order of their attachment, starting from the document root down to the target element.Target Phase: The event reaches the target element (
inner
), triggering event listeners attached directly to it.Bubbling Phase: Event listeners attached with
useCapture
set tofalse
(or omitted, as it's the default) will fire in the order of their attachment, starting from the target element up to the document root.
Considering the setup provided in the HTML and JavaScript:
Capturing Phase (Reverse Order):
Outer clicked (capturing)
Middle clicked (capturing)
Inner clicked (capturing)
Target Phase:
Inner clicked (bubbling)
Bubbling Phase (Normal Order):
Outer clicked (bubbling)
Middle clicked (bubbling)
Inner clicked (bubbling)
So, the complete order of logs for a single click event on the innermost div
will be:
Outer clicked (capturing)
Middle clicked (capturing)
Inner clicked (capturing)
Inner clicked (bubbling)
Outer clicked (bubbling)
Middle clicked (bubbling)
Inner clicked (bubbling)
This demonstrates how event propagation occurs in both the capturing and bubbling phases. The capturing phase starts from the outermost ancestor and moves towards the target element, while the bubbling phase starts from the target element and moves towards the outermost ancestor.
local,session and cookies in react.js
Certainly! Below is the modified code for handling local storage, session storage, and cookies in a React application:
- Local Storage:
import React, { useEffect, useState } from 'react';
function LocalStorageExample() {
const [username, setUsername] = useState('');
useEffect(() => {
const storedUsername = localStorage.getItem('username');
if (storedUsername) setUsername(JSON.parse(storedUsername));
}, []);
const handleChange = (event) => {
const { value } = event.target;
setUsername(value);
localStorage.setItem('username', JSON.stringify(value));
};
return (
<div>
<h2>Local Storage Example</h2>
<input type="text" value={username} onChange={handleChange} />
</div>
);
}
export default LocalStorageExample;
- Session Storage:
import React, { useEffect, useState } from 'react';
function SessionStorageExample() {
const [theme, setTheme] = useState('');
useEffect(() => {
const storedTheme = sessionStorage.getItem('theme');
if (storedTheme) setTheme(storedTheme);
}, []);
const handleChange = (event) => {
const { value } = event.target;
setTheme(value);
sessionStorage.setItem('theme', value);
};
return (
<div>
<h2>Session Storage Example</h2>
<input type="text" value={theme} onChange={handleChange} />
</div>
);
}
export default SessionStorageExample;
- Cookies:
import React, { useEffect, useState } from 'react';
function CookiesExample() {
const [message, setMessage] = useState('');
useEffect(() => {
const cookies = document.cookie.split(';');
const storedMessage = cookies.find(cookie => cookie.includes('message'));
if (storedMessage) {
const decodedMessage = decodeURIComponent(storedMessage.split('=')[1]);
setMessage(decodedMessage);
}
}, []);
const handleChange = (event) => {
const { value } = event.target;
setMessage(value);
const encodedMessage = encodeURIComponent(value);
document.cookie = `message=${encodedMessage}; expires=Fri, 31 Dec 2022 23:59:59 GMT; path=/`;
};
return (
<div>
<h2>Cookies Example</h2>
<input type="text" value={message} onChange={handleChange} />
</div>
);
}
export default CookiesExample;
In each example:
We use
useState
to manage the state of the data (username, theme, message).useEffect
is used to retrieve stored data when the component mounts.For local storage and session storage, we use
localStorage
andsessionStorage
respectively to store and retrieve data.For cookies, we use
document.cookie
to manage cookie data. We split the cookie string, find the desired cookie, and set it usingdocument.cookie
. We also useencodeURIComponent
anddecodeURIComponent
to handle special characters in the cookie value.
React Code splitting
Code splitting in React allows you to split your code into smaller chunks that are loaded on demand. This can improve the initial loading time of your application by only loading the necessary code for the current view. Here's a simple real-world example of code splitting in React:
Suppose we have a React application with two pages: HomePage
and AboutPage
. We want to split the code for each page into separate bundles.
HomePage: Create a file named
HomePage.js
:import React from 'react'; function HomePage() { return ( <div> <h1>Home Page</h1> <p>Welcome to the home page!</p> </div> ); } export default HomePage;
AboutPage: Create a file named
AboutPage.js
:import React from 'react'; function AboutPage() { return ( <div> <h1>About Page</h1> <p>Learn more about us!</p> </div> ); } export default AboutPage;
App Component: Create an
App.js
file:import React, { Suspense, lazy } from 'react'; import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'; import NavBar from './NavBar'; const HomePage = lazy(() => import('./HomePage')); const AboutPage = lazy(() => import('./AboutPage')); const UserPage = lazy(() => import('./UserPage')); function App() { return ( <Router> <NavBar /> <Suspense fallback={<div>Loading...</div>}> <Switch> <Route exact path="/" component={HomePage} /> <Route path="/about" component={AboutPage} /> <Route path="/user/:userId" component={UserPage} /> </Switch> </Suspense> </Router> ); } export default App;
UserPage: Create a file named UserPage.js:
import React from 'react'; import { useParams } from 'react-router-dom'; function UserPage() { const { userId } = useParams(); return ( <div> <h1>User Profile</h1> <p>User ID: {userId}</p> </div> ); } export default UserPage;
import React from 'react'; import { Link } from 'react-router-dom'; function NavBar() { return ( <nav> <ul> <li><Link to="/">Home</Link></li> <li><Link to="/about">About</Link></li> </ul> </nav> ); } export default NavBar;
Crud in redux toolkit thunk
To perform CRUD operations with Redux Toolkit using async thunk, we need to create actions and reducers for each operation (Create, Read, Update, Delete) and use async thunk to handle asynchronous API calls. Below is an example implementation of CRUD operations with Redux Toolkit using async thunk:
Setup Redux Store:
// store.js import { configureStore } from '@reduxjs/toolkit'; import userReducer from './userSlice'; export default configureStore({ reducer: { user: userReducer, }, });
Create User Slice:
// userSlice.js import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'; import userService from '../services/userService'; // Async thunk for fetching users export const fetchUsers = createAsyncThunk('user/fetchUsers', async () => { const response = await userService.getUsers(); return response.data; }); // Async thunk for creating user export const createUser = createAsyncThunk('user/createUser', async (userData) => { const response = await userService.createUser(userData); return response.data; }); // Async thunk for updating user export const updateUser = createAsyncThunk('user/updateUser', async (userData) => { const response = await userService.updateUser(userData); return response.data; }); // Async thunk for deleting user export const deleteUser = createAsyncThunk('user/deleteUser', async (userId) => { await userService.deleteUser(userId); return userId; }); const userSlice = createSlice({ name: 'user', initialState: { users: [], status: 'idle', error: null, }, reducers: {}, extraReducers: (builder) => { builder .addCase(fetchUsers.pending, (state) => { state.status = 'loading'; }) .addCase(fetchUsers.fulfilled, (state, action) => { state.status = 'succeeded'; state.users = action.payload; }) .addCase(fetchUsers.rejected, (state, action) => { state.status = 'failed'; state.error = action.error.message; }) // Reducers for createUser, updateUser, deleteUser .addCase(createUser.fulfilled, (state, action) => { state.users.push(action.payload); }) .addCase(updateUser.fulfilled, (state, action) => { const updatedUser = action.payload; const existingUserIndex = state.users.findIndex(user => user.id === updatedUser.id); if (existingUserIndex !== -1) { state.users[existingUserIndex] = updatedUser; } }) .addCase(deleteUser.fulfilled, (state, action) => { const userId = action.payload; state.users = state.users.filter(user => user.id !== userId); }); }, }); export default userSlice.reducer;
Service Layer:
// userService.js import axios from 'axios'; const baseUrl = '/api/users'; // Replace with your API endpoint const getUsers = async () => { return await axios.get(baseUrl); }; const createUser = async (userData) => { return await axios.post(baseUrl, userData); }; const updateUser = async (userData) => { return await axios.put(`${baseUrl}/${userData.id}`, userData); }; const deleteUser = async (userId) => { return await axios.delete(`${baseUrl}/${userId}`); }; export default { getUsers, createUser, updateUser, deleteUser };
Component Usage:
import React, { useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { fetchUsers, createUser, updateUser, deleteUser } from './userSlice'; function UserComponent() { const dispatch = useDispatch(); const { users,status,error } = useSelector((state) => state.user); //const users = useSelector((state) => state.user.users); //const status = useSelector((state) => state.user.status); //const error = useSelector((state) => state.user.error); useEffect(() => { dispatch(fetchUsers()); }, [dispatch]); const handleCreateUser = () => { dispatch(createUser({ name: 'John Doe' })); }; const handleUpdateUser = (userId) => { dispatch(updateUser({ id: userId, name: 'Updated Name' })); }; const handleDeleteUser = (userId) => { dispatch(deleteUser(userId)); }; return ( <div> {status === 'loading' && <p>Loading...</p>} {status === 'failed' && <p>Error: {error}</p>} <button onClick={handleCreateUser}>Create User</button> <ul> {users.map((user) => ( <li key={user.id}> {user.name} <button onClick={() => handleUpdateUser(user.id)}>Update</button> <button onClick={() => handleDeleteUser(user.id)}>Delete</button> </li> ))} </ul> </div> ); } export default UserComponent;
In this setup:
We define async thunk actions for fetching, creating, updating, and deleting users.
We use a service layer (
userService.js
) to interact with the API.The component (
UserComponent
) dispatches these actions and displays users accordingly.Reducers handle the state updates based on the action outcomes.
The Redux store (
store.js
) is set up to include the user slice reducer.The
UserComponent
renders a list of users and provides functionality to create, update, and delete users.
Crud in redux toolkit Query
To convert the above code to use Redux Toolkit Query, we'll utilize the createApi
function provided by Redux Toolkit Query. This function allows us to define API endpoints and automatically generate Redux slice reducers and hooks for interacting with the API.
Here's how you can refactor the code to use Redux Toolkit Query:
Create API Slice:
// apiSlice.js import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; const baseUrl = '/api/users'; // Replace with your API endpoint const apiSlice = createApi({ reducerPath: 'api', baseQuery: fetchBaseQuery({ baseUrl }), endpoints: (builder) => ({ getUsers: builder.query({ query: () => '', }), createUser: builder.mutation({ query: (userData) => ({ url: '', method: 'POST', body: userData, }), }), updateUser: builder.mutation({ query: ({ id, ...userData }) => ({ url: `${id}`, method: 'PUT', body: userData, }), }), deleteUser: builder.mutation({ query: (userId) => ({ url: `${userId}`, method: 'DELETE', }), }), }), }); export const { useGetUsersQuery, useCreateUserMutation, useUpdateUserMutation, useDeleteUserMutation, } = apiSlice;
Store Configuration: You need to configure your Redux store and include the API slice reducer.
```javascript // store.js import { configureStore } from '@reduxjs/toolkit'; import { apiSlice } from './apiSlice';
export const store = configureStore({ reducer: {
}, middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(apiSlice.middleware), });
// multiple slice example // store.js import { configureStore } from '@reduxjs/toolkit'; import { apiSlice } from './apiSlice'; import { productApiSlice } from './productApiSlice'; // Import the productApiSlice
export const store = configureStore({ reducer: {
[productApiSlice.reducerPath]: productApiSlice.reducer, // Include the productApiSlice reducer }, middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(apiSlice.middleware, productApiSlice.middleware), // Include the productApiSlice middleware });
3. Provider Setup: Provide the Redux store to the component using React's ->Provider
```javascript
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { store } from './store';
import App from './App';
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
Component Usage:
import React, { useEffect } from 'react'; import { useGetUsersQuery, useCreateUserMutation, useUpdateUserMutation, useDeleteUserMutation } from './apiSlice'; function UserComponent() { const { data: users, error, isLoading, isSuccess } = useGetUsersQuery(); const [createUser] = useCreateUserMutation(); const [updateUser] = useUpdateUserMutation(); const [deleteUser] = useDeleteUserMutation(); useEffect(() => { // Refetch users after mutations if (isSuccess) { refetch(); } }, [isSuccess, refetch]); const handleCreateUser = () => { createUser({ name: 'John Doe' }); }; const handleUpdateUser = (userId) => { updateUser({ id: userId, name: 'Updated Name' }); }; const handleDeleteUser = (userId) => { deleteUser(userId); }; if (isLoading) return <p>Loading...</p>; if (error) return <p>Error: {error.message}</p>; return ( <div> <button onClick={handleCreateUser}>Create User</button> <ul> {users.map((user) => ( <li key={user.id}> {user.name} <button onClick={() => handleUpdateUser(user.id)}>Update</button> <button onClick={() => handleDeleteUser(user.id)}>Delete</button> </li> ))} </ul> </div> ); } export default UserComponent;
In this setup:
We define an API slice using
createApi
, specifying the base URL and endpoint definitions.Redux Toolkit Query generates hooks for fetching data (
useGetUsersQuery
) and mutations (useCreateUserMutation
,useUpdateUserMutation
,useDeleteUserMutation
).The
UserComponent
component uses these hooks to interact with the API.We handle loading and error states and refetch users after mutations to ensure the UI stays up to date with the latest data.
crud using react-query
import React from 'react';
import { useQuery, useMutation, queryCache } from 'react-query';
// Function to fetch data
const fetchData = async () => {
const response = await fetch('your_api_endpoint');
return response.json();
};
// Function to create data
const createData = async (newData) => {
const response = await fetch('your_api_endpoint', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(newData),
});
return response.json();
};
// Function to update data
const updateData = async (id, updatedData) => {
const response = await fetch(`your_api_endpoint/${id}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(updatedData),
});
return response.json();
};
// Function to delete data
const deleteData = async (id) => {
const response = await fetch(`your_api_endpoint/${id}`, {
method: 'DELETE',
});
return response.json();
};
const App = () => {
// Fetch data query
const { data, isLoading, isError } = useQuery('data', fetchData);
// Create mutation
const createMutation = useMutation(createData, {
onSuccess: () => {
queryCache.invalidateQueries('data');
},
});
// Update mutation
const updateMutation = useMutation(updateData, {
onSuccess: () => {
queryCache.invalidateQueries('data');
},
});
// Delete mutation
const deleteMutation = useMutation(deleteData, {
onSuccess: () => {
queryCache.invalidateQueries('data');
},
});
if (isLoading) return <div>Loading...</div>;
if (isError) return <div>Error fetching data</div>;
return (
<div>
{/* Display data */}
{data.map(item => (
<div key={item.id}>
<span>{item.name}</span>
<button onClick={() => deleteMutation.mutate(item.id)}>Delete</button>
<button onClick={() => updateMutation.mutate({ id: item.id, newData: { name: 'Updated Name' } })}>Update</button>
</div>
))}
{/* Create new data */}
<button onClick={() => createMutation.mutate({ name: 'New Data' })}>Create</button>
</div>
);
};
export default App;
import React from 'react';
import { QueryClient, QueryClientProvider } from 'react-query';
import App from './App'; // Assuming your App component is in a separate file
const queryClient = new QueryClient();
const WrappedApp = () => (
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>
);
export default WrappedApp;
react hook form
https://github.com/cosdensolutions/code/tree/master/videos/long/react-hook-form-tutorial
https://youtu.be/cc_xmawJ8Kg?si=TVwvHaX3WCyMq7B3
Using React Hook Form with Zod is a great combination for handling form validations in React applications. React Hook Form is a library for managing form state and validation in React using hooks, while Zod is a schema validation library that provides a simple and powerful API for validating data.
Here's how you can use React Hook Form with Zod for form validation:
- Install React Hook Form and Zod:
npm install react-hook-form zod
- Import necessary modules in your component:
import React from 'react';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
- Define your form schema using Zod:
const schema = z.object({
firstName: z.string().min(2).max(20).nonempty(),
lastName: z.string().min(2).max(20).nonempty(),
email: z.string().email(),
});
- Create your React component and use React Hook Form:
const MyForm = () => {
const { register, handleSubmit, formState: { errors } } = useForm({
resolver: zodResolver(schema)
});
const onSubmit = (data) => {
console.log(data);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input type="text" {...register("firstName")} />
{errors.firstName && <span>{errors.firstName.message}</span>}
<input type="text" {...register("lastName")} />
{errors.lastName && <span>{errors.lastName.message}</span>}
<input type="email" {...register("email")} />
{errors.email && <span>{errors.email.message}</span>}
<button type="submit">Submit</button>
</form>
);
};
export default MyForm;
In this example:
We defined a schema using Zod to validate the form fields.
We used the
useForm
hook from React Hook Form and passed the Zod resolver to handle form validation.In the form, we registered each input field using the
register
function provided by React Hook Form. We spread the register function's result into the input element.We displayed error messages for each field using the
errors
object provided by React Hook Form.
With this setup, React Hook Form will handle form state, validation, and error messages based on the Zod schema you defined.
promise method
https://github.com/mukeshphulwani66/javascript-interview-questions/blob/main
function getSquare(n, delay) {
const promise = new Promise((res, rej) => {
setTimeout(() => {
if (n % 2 == 0) res(n * n)
else rej("cant calculate sqaure for odd numbers")
}, delay)
})
return promise
}
async function getData() {
// 1
// race - will return first promse whether its resolved or rejected
// any - will return first promise only when its resolved
// all - will return all promise when its resolved , if any one fail it will throw error
// allSettled - will return all promise whether its resolved or rejected
try {
const res = await Promise.
any([getSquare(5, 2000), getSquare(3, 1000)])
console.log(res)
} catch (err) {
console.log("ERROR",err)
console.log(err.errors)
}
}
getData()
// js
// JSON.stringify()--> js (array or object) to json string
// JSON.parse()--> json string to js
# python
#json.dumps()--> python (array or object) to json string
#json.load()--> json string to python
import json
data = {"name": "John", "age": 30, "city": "New York"}
json_string = json.dumps(data)
print(json_string) # Output: {"name": "John", "age": 30, "city": "New York"}
with open('data.json', 'r') as file:
data = json.load(file)
print(data) # Output: {"name": "John", "age": 30, "city": "New York"}