Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Explaination for useReducer hook #3

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 129 additions & 0 deletions src/UseCallback/README.md
Original file line number Diff line number Diff line change
@@ -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).
- `<Child returnComment={returnComment} />`: 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 `<Child returnComment={returnComment} />`.
- 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 `<div>`.

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 `<h1> toggle </h1>` 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
75 changes: 75 additions & 0 deletions src/UseContext/README.md
Original file line number Diff line number Diff line change
@@ -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)

95 changes: 95 additions & 0 deletions src/UseEffect/EffectTutorial.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<div>
Hello World
<h1>{data}</h1>
// {data}: Displays the fetched email data

<h1>{count}</h1>
// {count}: Displays the current count state

<button
onClick={() => {
setCount(count + 1);
}}
>
Click
</button>
// onClick: Event handler for button clicks
// setCount: Updates the 'count' state
// Increments count by 1 on each button click
</div>
);
}

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.


*/
23 changes: 22 additions & 1 deletion src/UseImperativeHandle/Button.js
Original file line number Diff line number Diff line change
@@ -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);
},
Expand All @@ -12,8 +28,13 @@ const Button = forwardRef((props, ref) => {
<>
<button>Button From Child</button>
{toggle && <span>Toggle</span>}
// 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.
15 changes: 15 additions & 0 deletions src/UseImperativeHandle/ImperativeHandle.js
Original file line number Diff line number Diff line change
@@ -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.

<div>
<button
onClick={() => {
Expand All @@ -18,3 +31,5 @@ function ImperativeHandle() {
}

export default ImperativeHandle;
// This statement exports the ImperativeHandle component as the default export of this module.
// It allows other files to import this component.
Loading