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 the items state.

  • We use useMemo to memoize the items array, so that it's only recomputed when the items state changes.

  • The memoizedItems variable holds the memoized value of items, 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 the useCallback 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 the onClick 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:

  1. Synchronous State Update: When you call useState to update a state variable, React immediately updates the state variable and re-renders the component synchronously.

  2. 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 of setCount, which receives the previous state value as an argument (prevCount).

  • Inside the setCount function, we compute the updated count (updatedCount) by incrementing the prevCount 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:

  1. 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>;
          }
        }
      
  2. 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>;
          }
        }
      
  3. 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>;
          }
        }
      
  4. 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>;
          }
        }
      
  5. 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:

  1. constructor() and componentDidMount():

    • In functional components, you can initialize state using the useState hook and perform side effects (such as data fetching) using the useEffect 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>;
        }
      
  2. componentDidUpdate():

    • In functional components, you can achieve similar behavior to componentDidUpdate() by using the useEffect 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>;
        }
      
  3. 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>;
        }
      
  4. shouldComponentUpdate():

    • In functional components, you can use the React.memo() higher-order component or the useMemo() 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 a text 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 the text prop to uppercase.

  • We enhance MyComponent with the withUpperCase HOC by wrapping it with withUpperCase(MyComponent), resulting in a new component called MyEnhancedComponent.

  • Finally, we use MyEnhancedComponent in the App component, passing the text 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:

  1. Definition ofMyComponent:

    • MyComponent is a simple functional component that takes a text prop and renders it inside a <div> element.
  2. Definition ofwithUpperCase 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.

  3. Enhancement ofMyComponent with withUpperCase HOC:

    • MyEnhancedComponent is created by enhancing MyComponent with the withUpperCase HOC. This means MyEnhancedComponent will receive props, pass them through withUpperCase to modify them (in this case, converting text prop to uppercase), and then render MyComponent with the modified props.
  4. Usage ofMyEnhancedComponent in App component:

    • The App component renders MyEnhancedComponent, passing the text prop "Hello, World!".

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 the new 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 the async keyword. Inside this function, we use await 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 use await to wait for the promise to settle, and then handle the resolved value or catch any errors directly inside the try 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:

  1. 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
    }
  1. this Binding:

    • Arrow functions do not bind their own this value. They lexically inherit this 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
      }
    };
  1. 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);
  1. 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:

  1. 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.

  1. 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 variable outerVar declared.

  • Inside innerFunction, we can access the outerVar variable from its enclosing outerFunction. This ability to access variables from outer functions is called lexical scoping.

  • Both innerFunction and outerFunction have access to the global variable globalVar.

  • However, variables declared inside innerFunction or outerFunction 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 parameter outerValue.

  • Inside outerFunction, another function innerFunction is defined.

  • innerFunction has access to the outerValue parameter of its enclosing outerFunction. This access to variables from the outer scope, even after the outer function has finished executing, is known as a closure.

  • outerFunction returns innerFunction, creating a closure.

  • We then call outerFunction with an argument of 10, which sets outerValue to 10. This creates a closure where innerFunction has access to outerValue (which is 10).

  • We store the returned innerFunction in a variable called closure.

  • Later, we can call closure with an argument of 5. This adds 5 to the outerValue (which is 10), resulting in 15.

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 method fullName that accepts two additional arguments, city and country.

  • We have two other objects john and jane representing different persons.

  • We demonstrate the use of call to invoke the fullName method of person with john and jane objects and pass the city and country arguments.

  • We use apply similarly to call, but we pass arguments as an array.

  • We use bind to create new functions (johnFullName and janeFullName) with pre-defined city and country arguments. When these new functions are invoked later, they only require the remaining arguments (firstName and lastName) 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".

  1. 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)
  1. 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, and inner.

  • 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 to true). 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:

    1. Capturing Phase: Event listeners attached with useCapture set to true will fire in the reverse order of their attachment, starting from the document root down to the target element.

    2. Target Phase: The event reaches the target element (inner), triggering event listeners attached directly to it.

    3. Bubbling Phase: Event listeners attached with useCapture set to false (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:

  1. Capturing Phase (Reverse Order):

    • Outer clicked (capturing)

    • Middle clicked (capturing)

    • Inner clicked (capturing)

  2. Target Phase:

    • Inner clicked (bubbling)
  3. 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:

  1. 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;
  1. 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;
  1. 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 and sessionStorage 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 using document.cookie. We also use encodeURIComponent and decodeURIComponent 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.

  1. 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;
    
  2. 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;
    
  3. 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:

  1. Setup Redux Store:

     // store.js
     import { configureStore } from '@reduxjs/toolkit';
     import userReducer from './userSlice';
    
     export default configureStore({
       reducer: {
         user: userReducer,
       },
     });
    
  2. 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;
    
  3. 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 };
    
  4. 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:

  1. 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;
    
  2. 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 -&gt;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')
    );
  1. 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:

  1. Install React Hook Form and Zod:
npm install react-hook-form zod
  1. 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';
  1. 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(),
});
  1. 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"}