code examples
Experienced DevOps Engineer with expertise in CI/CD automation, cloud infrastructure, Kubernetes, and GitOps. Provisioned a Jenkins server on AWS EC2 for automated deployments, integrating Terraform to provision VPCs and EKS clusters. Configured a Jump Server for secure Kubernetes access and implemented ArgoCD for GitOps-driven deployments. Integrated SonarQube for static code analysis and enforced quality gates in Jenkins pipelines. Built AWS ECR repositories and automated Docker image management. Ensured security by managing secrets in Jenkins Credentials Manager and implementing IAM policies for AWS resources. Configured Kubernetes Ingress via ArgoCD and deployed MongoDB with persistence strategies. Designed multi-branch Jenkins pipelines for different environments. Installed Prometheus and Grafana for monitoring with automated alerts. Optimized costs using AWS CloudWatch and Lambda for unused resource cleanup. Ensured end-to-end automation, security, and observability.
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
useEffecthook, and store them in theitemsstate.We use
useMemoto memoize theitemsarray, so that it's only recomputed when theitemsstate changes.The
memoizedItemsvariable 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
handleClickfunction inside theuseCallbackhook.The
handleClickfunction is only recreated if its dependencies change. In this case, it has no dependencies, so it's only created once.We pass the
handleClickfunction as theonClickhandler 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
useStateto 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
handleClickfunction to use the functional form ofsetCount, which receives the previous state value as an argument (prevCount).Inside the
setCountfunction, we compute the updated count (updatedCount) by incrementing theprevCountby 1.We then log the
updatedCountto the console immediately after setting the state. This will log the correct updated count value.Additionally, we've kept the
useEffecthook 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
useStatehook and perform side effects (such as data fetching) using theuseEffecthook 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 theuseEffecthook 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
useEffecthook.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
MyComponentthat takes atextprop 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 thetextprop to uppercase.We enhance
MyComponentwith thewithUpperCaseHOC by wrapping it withwithUpperCase(MyComponent), resulting in a new component calledMyEnhancedComponent.Finally, we use
MyEnhancedComponentin theAppcomponent, passing thetextprop "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:MyComponentis a simple functional component that takes atextprop and renders it inside a<div>element.
Definition of
withUpperCaseHOC:withUpperCaseis 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
textprop of the input props to be in uppercase.Renders the
WrappedComponentwith the modified props.
Enhancement of
MyComponentwithwithUpperCaseHOC:MyEnhancedComponentis created by enhancingMyComponentwith thewithUpperCaseHOC. This meansMyEnhancedComponentwill receive props, pass them throughwithUpperCaseto modify them (in this case, convertingtextprop to uppercase), and then renderMyComponentwith the modified props.
Usage of
MyEnhancedComponentinAppcomponent:- The
Appcomponent rendersMyEnhancedComponent, passing thetextprop "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
myPromisewith 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
fetchDatausing theasynckeyword. Inside this function, we useawaitto 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 useawaitto wait for the promise to settle, and then handle the resolved value or catch any errors directly inside thetryblock.We call the
fetchDatafunction 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
functionkeyword.
// Arrow function syntax
const arrowFunction = () => {
// Function body
};
// Normal function syntax
function normalFunction() {
// Function body
}
thisBinding:Arrow functions do not bind their own
thisvalue. They lexically inheritthisfrom the surrounding code.Normal functions bind their own
thisvalue, 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
argumentsobject.Normal functions have their own
argumentsobject, 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
thiscontext.Normal functions are more flexible and are used in various scenarios, including object methods, constructors, and when you need access to the
argumentsobject.
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
globalVardeclared outside any function.Inside
outerFunction, we have another variableouterVardeclared.Inside
innerFunction, we can access theouterVarvariable from its enclosingouterFunction. This ability to access variables from outer functions is called lexical scoping.Both
innerFunctionandouterFunctionhave access to the global variableglobalVar.However, variables declared inside
innerFunctionorouterFunctionare 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,
outerFunctionis defined with a parameterouterValue.Inside
outerFunction, another functioninnerFunctionis defined.innerFunctionhas access to theouterValueparameter of its enclosingouterFunction. This access to variables from the outer scope, even after the outer function has finished executing, is known as a closure.outerFunctionreturnsinnerFunction, creating a closure.We then call
outerFunctionwith an argument of10, which setsouterValueto10. This creates a closure whereinnerFunctionhas access toouterValue(which is10).We store the returned
innerFunctionin a variable calledclosure.Later, we can call
closurewith an argument of5. This adds5to 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
personwith a methodfullNamethat accepts two additional arguments,cityandcountry.We have two other objects
johnandjanerepresenting different persons.We demonstrate the use of
callto invoke thefullNamemethod ofpersonwithjohnandjaneobjects and pass thecityandcountryarguments.We use
applysimilarly tocall, but we pass arguments as an array.We use
bindto create new functions (johnFullNameandjaneFullName) with pre-definedcityandcountryarguments. When these new functions are invoked later, they only require the remaining arguments (firstNameandlastName) 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 (
useCaptureset 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
useCaptureset totruewill 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
useCaptureset 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
useStateto manage the state of the data (username, theme, message).useEffectis used to retrieve stored data when the component mounts.For local storage and session storage, we use
localStorageandsessionStoragerespectively to store and retrieve data.For cookies, we use
document.cookieto manage cookie data. We split the cookie string, find the desired cookie, and set it usingdocument.cookie. We also useencodeURIComponentanddecodeURIComponentto 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.jsfile: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
UserComponentrenders 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
UserComponentcomponent 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
useFormhook from React Hook Form and passed the Zod resolver to handle form validation.In the form, we registered each input field using the
registerfunction 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
errorsobject 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"}