diff --git a/src/UseCallback/README.md b/src/UseCallback/README.md new file mode 100644 index 0000000..e06fe3f --- /dev/null +++ b/src/UseCallback/README.md @@ -0,0 +1,129 @@ +# useCallback Tutorial + +## Important concepts + +### useState +A Hook that lets you add React state to function components. +- `const [toggle, setToggle] = useState(false);`: Manages the toggle state for showing/hiding an h1 element. +- `const [data, setData] = useState("Yo, pls sub to the channel!");`: Stores a string message used in the returnComment function. + +### useCallback +A Hook that lets you cache a function definition between re-renders. +- `const returnComment = useCallback((name) => { return data + name; }, [data]);`: Memoizes the returnComment function, preventing unnecessary re-renders of the Child component unless the 'data' dependency changes. +- Memoization is widely used in React for performance optimization + + - React provides built-in hooks like useMemo and useCallback that implement memoization. These hooks are used to optimize expensive calculations and prevent unnecessary re-renders of components. + - Memoization can be used in various contexts beyond simple function caching, and for purposes other than speed gains, such as in simple mutually recursive descent parsing. + - Memoization is specifically about caching function results, unlike other forms of caching that might deal with data storage or retrieval. + - Specific implementation of Memoization in logic programming languages is also known as tabling. + +### useEffect +A Hook that lets you perform side effects in function components. +- `useEffect(() => { console.log("FUNCTION WAS CALLED"); }, [returnComment]);`: Logs a message to the console whenever the returnComment function reference changes, demonstrating when the Child component re-renders. +- A side effect refers to any operation that affects the state outside of the function's scope or interacts with the outside world. This can include: + + - Modifying a global variable or an object passed by reference. + - Performing I/O operations, such as reading from or writing to a file or database. + - Making network requests or API calls. + - Logging information to the console. + + +### Child Component +A component that is nested within another component (the parent component). +- ``: Renders the Child component in CallBackTutorial.js, passing the memoized returnComment function as a prop. +- The entire Child.js file defines a child component that receives and uses the returnComment prop. + +## Operations + +1. CallBackTutorial component starts mounting: + - React processes the import statements, bringing in necessary dependencies (axios, useState, useCallback, and the Child component). + +2. Function component CallBackTutorial is defined and executed: + - `useState(false)` is called to initialize the `toggle` state: + - React creates a state variable `toggle` with initial value `false`. + - React creates a setter function `setToggle`. + - `useState("Yo, pls sub to the channel!")` is called to initialize the `data` state: + - React creates a state variable `data` with the initial string value. + - React creates a setter function `setData`. + +3. `useCallback` is executed: + - React creates a memoized version of the `returnComment` function. + - **Memoization Explanation**: + - useCallback memoizes the function definition itself, not the function's output. + - It stores the function reference, creating a new reference only if the dependencies change. + - This differs from traditional memoization, which caches function results based on input. + - In this case, the entire function `(name) => { return data + name; }` is stored and reused. + - The function is memoized with `data` as a dependency, meaning it will only be recreated if `data` changes. + - The stored function reference will only change if `data` changes. + - This ensures stable function identity across re-renders when `data` remains the same. + +4. The JSX in the return statement of CallBackTutorial is evaluated: + - React processes the JSX, creating a virtual DOM representation. + +5. Child component is encountered in the JSX: + - React sees ``. + - It prepares to render the Child component, passing the memoized `returnComment` function as a prop. + +6. Child component starts rendering: + - The function component Child is executed with `returnComment` prop. + - `useEffect` in Child is encountered: + - React schedules this effect to run after the render is committed to the screen. + - The JSX in Child's return statement is evaluated: + - `returnComment("Pedro")` is called, concatenating "Pedro" to the current value of `data`. + - The result is placed within a `
`. + +7. React completes the initial render of both components: + - The virtual DOM is created for the entire component tree. + - React commits this to the actual DOM, painting the initial UI to the screen. + +8. After the render, React runs the scheduled effects: + - The `useEffect` in Child component is executed. + - "FUNCTION WAS CALLED" is logged to the console. + +9. The application is now in its initial state, waiting for user interaction. + +10. User clicks the "Toggle" button: + - The onClick handler is triggered. + - `setToggle(!toggle)` is called, scheduling a state update. + +11. React processes the state update: + - It marks the CallBackTutorial component for re-rendering. + +12. Re-render of CallBackTutorial begins: + - The function component is executed again. + - `useState` and `useCallback` hooks are called again: + - `toggle` state is updated with its new value. + - `data` state remains unchanged. + - **Memoization in Action**: + - `useCallback` checks its dependencies (`[data]`). + - Since `data` hasn't changed, it returns the same function reference as before. + - This demonstrates how useCallback caches the function definition, not its result. + - `returnComment` function is not recreated as `data` hasn't changed. + +13. JSX in CallBackTutorial is re-evaluated: + - If `toggle` is now `true`, the `

toggle

` element is included in the virtual DOM. + +14. Child component is encountered again: + - React checks if any props have changed. + - **Benefit of Memoization**: + - `returnComment` is the same reference as before, thanks to useCallback. + - React determines that Child's props haven't changed. + - Child component is not re-rendered, preventing unnecessary computation. + - `returnComment` is the same reference as before (thanks to useCallback), so Child is not re-rendered. + +15. React completes the re-render: + - The new virtual DOM is compared with the previous one (diffing process). + - Only the changes (the toggle h1 element) are applied to the actual DOM. + +16. The application is now in its updated state, again waiting for user interaction. + +This cycle of user interaction → state update → re-render continues throughout the lifecycle of the application, with Child only re-rendering if the `data` state in CallBackTutorial changes, causing a new reference of `returnComment` to be created. + +This cycle continues throughout the application's lifecycle. The key point is that useCallback memoizes the function definition itself, providing a stable function reference. This stability prevents unnecessary re-renders of Child, as React can quickly determine that the prop hasn't changed. The actual caching of function results (what `returnComment` returns) doesn't occur here; instead, it's the function's identity that's preserved across renders, which is crucial for optimizing React's reconciliation process. + +## React Dev Reference + +- useState: https://react.dev/reference/react/useState +- useCallback: https://react.dev/reference/react/useCallback +- useEffect: https://react.dev/reference/react/useEffect +- Components and Props: https://react.dev/learn/your-first-component diff --git a/src/UseContext/README.md b/src/UseContext/README.md new file mode 100644 index 0000000..b21f496 --- /dev/null +++ b/src/UseContext/README.md @@ -0,0 +1,75 @@ +# React Context Tutorial + +This project demonstrates the usage of React Context for state management across components without prop drilling. + +## Components + +1. `ContextTutorial`: The main component that provides the context. +2. `Login`: A component with an input field to update the username. +3. `User`: A component that displays the current username. + +### ContextTutorial + +This is the main component that sets up the AppContext and manages the username state. It wraps the child components (Login and User) with the AppContext.Provider. + +### Login + +This component renders an input field where users can enter a username. It uses the useContext hook to access the setUsername function from AppContext. + +### User + +This component displays the current username. It uses the useContext hook to access the username value from AppContext. + +## How it Works + +1. The ContextTutorial component creates a state for the username and provides it to child components via AppContext.Provider. +2. The Login component allows users to input a username, which updates the state in ContextTutorial. +3. The User component displays the current username, which updates automatically when the state changes. + +## Key Concepts + +- [React Context](https://react.dev/reference/react/createContext): For sharing data between components without explicit prop passing. +- [useState Hook](https://react.dev/reference/react/useState): For adding state to functional components. +- [useContext Hook](https://react.dev/reference/react/useContext): For consuming context in child components. + +## Operations + +1. **ContextTutorial Component Mount**: + - Initializes `username` state with an empty string. + - Wraps child components with `AppContext.Provider`, passing down `username` state and `setUsername` function. + +2. **Login Component Mount**: + - Accesses `setUsername` function from AppContext. + - Renders an input field for username entry. + +3. **User Component Mount**: + - Accesses `username` value from AppContext using `useContext`. + - Displays the current username (initially empty). + +4. **User Input in Login Component**: + - `onChange` event triggers when user types in the input field. + - Calls `setUsername` with the new input value. + - Updates `username` state in `ContextTutorial` component. + +5. **State Update in ContextTutorial**: + - `AppContext.Provider` value updates. + - Triggers re-render of Login and User components. + +6. **User Component Re-render**: + - Receives updated `username` value from context. + - Displays updated username value. + +## Usage + +To use this example: + +1. Clone the repository. +2. Install dependencies with `npm install`. +3. Run the app with `npm start`. + +## Further Reading + +- [React Documentation](https://react.dev/learn) +- [Using the Context API in React](https://react.dev/learn/passing-data-deeply-with-context) +- [Hooks API Reference](https://react.dev/reference/react) + diff --git a/src/UseEffect/EffectTutorial.js b/src/UseEffect/EffectTutorial.js index dabb9b1..a94d5fe 100644 --- a/src/UseEffect/EffectTutorial.js +++ b/src/UseEffect/EffectTutorial.js @@ -31,3 +31,98 @@ function EffectTutorial() { } export default EffectTutorial; + +/* + +import React, { useEffect, useState } from "react"; +// React: JavaScript library for building user interfaces +// useEffect: Hook for performing side effects in function components +// useState: Hook for adding state to function components +// Importing necessary React features for this component + +import axios from "axios"; +// axios: Promise-based HTTP client for making requests +// Imported to make API calls + +function EffectTutorial() { +// EffectTutorial: Defines a functional React component +// Creates the main component for this tutorial + + const [data, setData] = useState(""); + // useState: Initializes a state variable with a setter function + // Creates 'data' state to store email, initially an empty string + + const [count, setCount] = useState(0); + // useState: Initializes another state variable with a setter function + // Creates 'count' state to track button clicks, initially 0 + + useEffect(() => { + // useEffect: Performs side effects in functional components + // Sets up an effect to run after component mounts + + axios + .get("https://jsonplaceholder.typicode.com/comments") + // axios.get: Sends a GET request to the specified URL + // Fetches data from the JSONPlaceholder API + + .then((response) => { + // .then: Handles the successful response from the API + // Processes the fetched data + + setData(response.data[0].email); + // setData: Updates the 'data' state + // Sets 'data' to the email from the first comment + + console.log("API WAS CALLED"); + // console.log: Outputs a message to the console + // Logs when the API call is completed + }); + }, []); + // [], empty dependency array: Specifies when the effect should run + // Ensures the effect runs only once, after initial render + + return ( +
+ Hello World +

{data}

+ // {data}: Displays the fetched email data + +

{count}

+ // {count}: Displays the current count state + + + // onClick: Event handler for button clicks + // setCount: Updates the 'count' state + // Increments count by 1 on each button click +
+ ); +} + +export default EffectTutorial; +// export default: Makes EffectTutorial available for import elsewhere + + +Initial trigger and operations: + +1. Initial Trigger: Component Mount + The initial trigger for code execution is the component mounting. + This is evident from the empty dependency array `[]` in the `useEffect` hook. + +2. Operations: + a. When the component mounts, the `useEffect` hook runs. + b. Inside `useEffect`, an axios GET request is made to fetch comments from the API. + c. When the API responds, the email from the first comment is extracted and stored in the `data` state using `setData`. + d. "API WAS CALLED" is logged to the console. + e. The component renders, displaying "Hello World", the fetched email (`data`), and the initial count (0). + f. After initial render, the button becomes interactive. Each click increments the `count` state, triggering a re-render with the updated count value. + +Note that the API call only happens once when the component mounts, while the button can be clicked multiple times to update the count independently. + + +*/ diff --git a/src/UseImperativeHandle/Button.js b/src/UseImperativeHandle/Button.js index 40c630a..f2e8a31 100644 --- a/src/UseImperativeHandle/Button.js +++ b/src/UseImperativeHandle/Button.js @@ -1,9 +1,25 @@ import React, { forwardRef, useImperativeHandle, useState } from "react"; +// These are imports from the React library. forwardRef is used for ref forwarding, +// useImperativeHandle for customizing the instance value exposed to parent components, and +// useState for managing component state. +// These imported functions will be used to create a functional component with ref forwarding and +// state management capabilities. const Button = forwardRef((props, ref) => { + // forwardRef is a higher-order component that allows the component to receive a ref and + // pass it further down to a child component. + // It's used here to create a functional component that can receive a ref as a second argument. + const [toggle, setToggle] = useState(false); - + // useState is a React hook that allows functional components to have state. + // It returns an array with the current state value and a function to update it. + // It's used here to create a 'toggle' state variable initialized to false, and a 'setToggle' function to update it. + useImperativeHandle(ref, () => ({ + // useImperativeHandle customizes the instance value that is exposed to parent components when using ref. + // It's used here to create a method 'alterToggle' that can be called from its parent component, namely, ImperativeHandle + // to change the 'toggle' state. + alterToggle() { setToggle(!toggle); }, @@ -12,8 +28,13 @@ const Button = forwardRef((props, ref) => { <> {toggle && Toggle} + // This is the JSX returned by the component. It uses conditional rendering with the '&&' operator. + // It renders a button and conditionally renders a span element based on the 'toggle' state. ); }); export default Button; +// Button is Child component +// This statement exports the Button component as the default export of this module. +// It allows other files to import this component. diff --git a/src/UseImperativeHandle/ImperativeHandle.js b/src/UseImperativeHandle/ImperativeHandle.js index b4abcb8..b02837a 100644 --- a/src/UseImperativeHandle/ImperativeHandle.js +++ b/src/UseImperativeHandle/ImperativeHandle.js @@ -1,9 +1,22 @@ import React, { useRef } from "react"; import Button from "./Button"; +// These are imports. +// useRef is a hook that provides a way to persist values between renders. +// useRef will be used to create a ref, and the Button component is imported from the previous file. function ImperativeHandle() { + // This declares a functional component named ImperativeHandle. + // This component will use the Button component and demonstrate the use of imperative handle. + const buttonRef = useRef(null); + // useRef creates a mutable ref object whose .current property is initialized to the passed argument (null). + // It's used to create a ref that will be passed to the Button component. + return ( + // This is the JSX returned by the ImperativeHandle component. It includes an event handler and ref passing. + // It renders a button that, when clicked, calls the alterToggle method on the Button component. + // It also renders the Button component, passing the buttonRef to it. +
+ ); +} +``` + +## Lifting State Up + +Used when multiple components need to share state. + +### How it works: +1. Move the state to the closest common ancestor. +2. Pass the state and setter function as props to child components. + +### Example: + +```jsx +// Parent Component +function Parent() { + const [data, setData] = useState(''); + + return ( +
+

Data: {data}

+ +
+ ); +} + +// Child Component +function Child({ setData }) { + return ( + setData(e.target.value)} + /> + ); +} +``` + +## Context API + +Useful for deep component trees to avoid prop drilling. + +### How it works: +1. Create a context using React.createContext(). +2. Wrap parent component with Context.Provider. +3. Use useContext hook in child components to access and update the context value. + +### Example: + +```jsx +// Create context +const DataContext = React.createContext(); + +// Parent Component +function Parent() { + const [data, setData] = useState(''); + + return ( + +
+

Data: {data}

+ +
+
+ ); +} + +// Child Component +function Child() { + const { setData } = useContext(DataContext); + + return ( + setData(e.target.value)} + /> + ); +} +``` + +## Custom Events + +Less common, but useful in certain scenarios, especially with complex component hierarchies. + +### How it works: +1. Create a custom event in the child component. +2. Dispatch the event with data. +3. Listen for the event in the parent component. + +### Example: + +```jsx +// Parent Component +function Parent() { + useEffect(() => { + const handleChildEvent = (e) => { + console.log('Received from child:', e.detail); + }; + + window.addEventListener('CHILD_EVENT', handleChildEvent); + + return () => { + window.removeEventListener('CHILD_EVENT', handleChildEvent); + }; + }, []); + + return ; +} + +// Child Component +function Child() { + const sendDataToParent = () => { + const event = new CustomEvent('CHILD_EVENT', { detail: 'Hello from child!' }); + window.dispatchEvent(event); + }; + + return ; +} +``` + +## Refs with useImperativeHandle + +Allows a parent component to call methods on a child component. + +### How it works: +1. Use forwardRef to create the child component. +2. Use useImperativeHandle in the child to expose methods to the parent. +3. Create a ref in the parent and pass it to the child. + +### Example: + +```jsx +// Child Component +const Child = forwardRef((props, ref) => { + const [data, setData] = useState(''); + + useImperativeHandle(ref, () => ({ + getChildData: () => data + })); + + return setData(e.target.value)} />; +}); + +// Parent Component +function Parent() { + const childRef = useRef(); + + const getDataFromChild = () => { + console.log('Child data:', childRef.current.getChildData()); + }; + + return ( +
+ + +
+ ); +} +``` + +## Conclusion + +Each method has its use cases, advantages, and trade-offs. Choose the appropriate method based on your specific requirements, component structure, and the complexity of your application. + +Remember, while these methods enable child-to-parent communication, it's generally recommended to keep the data flow primarily top-down in React applications for better predictability and easier debugging. diff --git a/src/UseLayoutEffect/LayoutEffectTutorial.js b/src/UseLayoutEffect/LayoutEffectTutorial.js index a8d9e2a..09ea734 100644 --- a/src/UseLayoutEffect/LayoutEffectTutorial.js +++ b/src/UseLayoutEffect/LayoutEffectTutorial.js @@ -19,3 +19,20 @@ function LayoutEffectTutorial() { } export default LayoutEffectTutorial; + +/* + +The component uses useRef to create a reference to the input element. +useLayoutEffect is used to log the initial value of the input synchronously after render. +useEffect is used to change the input's value asynchronously after the browser paint. +The input element is rendered with an initial value of "PEDRO" and styled inline. + +useLayoutEffect runs synchronously immediately after React has performed all DOM mutations. +useEffect runs asynchronously after the browser has painted the updates. +This sequence demonstrates how useLayoutEffect can be used for measurements or updates +that need to happen before the browser paints, preventing potential visual flickers. + +In real-world applications, directly manipulating DOM elements (as done here with inputRef.current.value) +should generally be avoided in favor of React's declarative state management. + +*/ diff --git a/src/UseMemo/README.md b/src/UseMemo/README.md new file mode 100644 index 0000000..ed7ace5 --- /dev/null +++ b/src/UseMemo/README.md @@ -0,0 +1,96 @@ +# React Memo Tutorial + +This project demonstrates the use of React hooks, particularly `useMemo`, for optimizing performance in a React application. + +## Key Elements/Keywords + +1. **React Hooks**: Functions that let you use state and other React features without writing a class. + + - `useState`: A Hook that lets you add React state to function components. + - "useState is a Hook that lets you add React state to function components. [...] It returns a pair: the current state value and a function that lets you update it." + - To manage 'data' and 'toggle' states in this component. + + - `useEffect`: A Hook for performing side effects in function components. + - "The Effect Hook lets you perform side effects in function components. [...] If you're familiar with React class lifecycle methods, you can think of useEffect Hook as componentDidMount, componentDidUpdate, and componentWillUnmount combined." + - To fetch data from an API when the component mounts. + + - `useMemo`: A Hook that memoizes expensive computations. + - "useMemo will only recompute the memoized value when one of the dependencies has changed. This optimization helps to avoid expensive calculations on every render." + - To memoize the result of findLongestName function. + +2. **Axios**: A popular, promise-based HTTP client for making requests. + - To make a GET request to fetch data from an API. + +3. **Conditional Rendering**: The ability to render different UI based on certain conditions. + - To conditionally render an h1 element based on the 'toggle' state. + +4. **Event Handling**: The method of running a function in response to an event. + - Used in the onClick event of the Toggle button. + +## Operations + +1. Initial Component Mount: + - The component is rendered for the first time. + - 'data' state is initialized as null. + - 'toggle' state is initialized as false. + - useEffect hook triggers an API call to fetch comments. + - useMemo initializes but doesn't compute (as data is null). + - The component renders with an empty longest name and the Toggle button. + +2. API Call Completion: + - The API call completes and the response is received. + - 'data' state is updated with the fetched comments using setData. + - This state update triggers a re-render of the component. + - useMemo now computes findLongestName with the new data. + - The component re-renders, displaying the longest name. + +3. Toggle Button Click: + - User clicks the Toggle button. + - setToggle is called, flipping the 'toggle' state. + - This state update triggers another re-render. + - useMemo checks its dependencies and sees that 'data' hasn't changed, so it doesn't recompute. + - The component re-renders, potentially showing/hiding the "toggle" h1 element. + +4. Subsequent Toggle Button Clicks: + - Each click flips the 'toggle' state and causes a re-render. + - useMemo continues to return the memoized value without recomputation. + - Only the conditional rendering of the "toggle" h1 changes. + +This demonstrates how useMemo optimizes performance by avoiding unnecessary recalculations of the findLongestName function when only the unrelated 'toggle' state changes. + +## Usage + +To use this component in your React project: + +1. Install necessary dependencies (react, axios). +2. Copy the MemoTutorial component into your project. +3. Import and use the MemoTutorial component in your app. + +Example: + +```jsx +import MemoTutorial from './path/to/MemoTutorial'; + +function App() { + return ( +
+ +
+ ); +} +``` + +This project serves as a practical example of using React hooks for state management and performance optimization. + +## React Documentation References + +For more detailed information on the React concepts used in this project, refer to the following official React documentation: + +1. React Hooks: https://reactjs.org/docs/hooks-intro.html +2. useState: https://reactjs.org/docs/hooks-state.html +3. useEffect: https://reactjs.org/docs/hooks-effect.html +4. useMemo: https://reactjs.org/docs/hooks-reference.html#usememo +5. Conditional Rendering: https://reactjs.org/docs/conditional-rendering.html +6. Handling Events: https://reactjs.org/docs/handling-events.html + +These resources provide comprehensive explanations and examples for each concept, which can help in deeper understanding and more effective use of React in your projects. \ No newline at end of file diff --git a/src/UseReducer/ReducerTutorial.js b/src/UseReducer/ReducerTutorial.js index ac18def..a87a5c3 100644 --- a/src/UseReducer/ReducerTutorial.js +++ b/src/UseReducer/ReducerTutorial.js @@ -32,3 +32,65 @@ const ReducerTutorial = () => { }; export default ReducerTutorial; + +/* +what steps happen after Button Click:- + +Button Click Event: +The user clicks the button labeled "Click Here". This triggers the onClick event handler defined for the button. + + +

Expensive calculation result: {expensiveResult}

+

Store state: {JSON.stringify(storeState)}

+ {isPending &&

Updating...

} +
+ ); +}); + +export default AllHooksDemo; + +/* + +Here's a breakdown of how each hook is used: + +useState: Manages the 'text' state. +useReducer: Manages a 'count' state with increment/decrement actions. +useContext: Accesses a theme from a ThemeContext. +useRef: Creates a reference to the input element. +useImperativeHandle: Exposes a 'focusInput' method to parent components. +useEffect: Simulates connecting/disconnecting to an external system. +useLayoutEffect: Logs a message after layout calculations. +useInsertionEffect: Dynamically inserts CSS based on the theme. +useMemo: Memoizes the result of an expensive calculation. +useCallback: Memoizes a callback function. +useTransition: Marks state updates as transitions for better performance. +useDeferredValue: Creates a deferred version of the text input. +useDebugValue: Provides a debug label for custom hooks (though this isn't a custom hook, it's used for demonstration). +useId: Generates a unique ID for the input element. +useSyncExternalStore: Subscribes to an external store. +useActionState: This hook is not included in the example. + +Note that this component is overly complex and not practical for real-world use. It's designed solely to demonstrate the usage of all these hooks in one place. In a real application, you would typically use only the hooks necessary for your specific use case, and often in separate components or custom hooks. + + +*/