0% found this document useful (0 votes)
10 views186 pages

React PDF

This document provides a comprehensive overview of React, covering its fundamental concepts, advantages over Vanilla JavaScript, and the setup of React projects. It explains key features such as component-based design, state management, and the use of JSX, while also discussing the historical context of web development and the challenges that React addresses. Additionally, it highlights the importance of destructuring, rest, and spread operators in JavaScript for efficient coding practices.

Uploaded by

narendra vidda
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views186 pages

React PDF

This document provides a comprehensive overview of React, covering its fundamental concepts, advantages over Vanilla JavaScript, and the setup of React projects. It explains key features such as component-based design, state management, and the use of JSX, while also discussing the historical context of web development and the challenges that React addresses. Additionally, it highlights the importance of destructuring, rest, and spread operators in JavaScript for efficient coding practices.

Uploaded by

narendra vidda
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 186

👍
React Notes

🔴
This Notes Divide into Four Parts

🔴
Fundamental.

🔴
Intermediate.

🔴
Advanced.
Professional Dev.

🔴 Fundamental. ➖
Building Your First React App
1.​ Tools Used:
○​ CodeSandbox: An online code editor for React apps. Access it via
codesandbox.io or directly at react.new.
2.​ Steps to Create the App:
○​ Open App.js, delete existing content, and start from scratch.
Define a React component using a function:​
jsx​
Copy code​
function App() {
return (
<div>
<h1>Hello World!</h1>
<button>Get advice</button>
</div>
);
}
export default App;
○​
○​ Save and see updates in the preview.
3.​ Fetching Data:
○​ Use fetch() to retrieve advice from the API: https://api.adviceslip.com/advice.
○​ Handle response data using async/await.
4.​ React State:
Use useState to store and update data dynamically.​
Jsx

const [advice, setAdvice] = useState("");
○​
○​ Update state with setAdvice after fetching advice.
5.​ Dynamic Updates:
Use onClick on the button to trigger the getAdvice function:​
jsx​

<button onClick={getAdvice}>Get advice</button>
○​
6.​ Display State:
Use curly braces {} in JSX to display dynamic values:​
jsx​
<p>{advice}</p>
○​
7.​ Using Effects:
Use useEffect to fetch advice when the app loads:​
jsx​

useEffect(() => {
getAdvice();
}, []);
○​
8.​ Count Clicks:
Create another useState for counting button clicks:​
jsx​

const [count, setCount] = useState(0);
setCount((prevCount) => prevCount + 1);
○​
9.​ Creating Components:
Break UI into reusable components, e.g., a Message component for the count:​
jsx​

function Message({ count }) {
return <p>You have read {count} pieces of advice.</p>;
}
○​
10.​Props:
Pass data to components using props:​
jsx​

<Message count={count} />
○​
11.​Key React Concepts Covered:
○​ JSX: HTML-like syntax for UI.
○​ State: For dynamic updates.
○​ Props: Passing data to components.
○​ Effects: For side-effects like fetching data.
○​ Components: Reusable pieces of UI.
12.​Summary:
○​ A simple app to fetch and display advice.
○​ Core React features: state, props, effects, and components.
○​ Dynamic UI updates based on state changes.
○​
This lecture provides a comprehensive explanation of why modern front-end frameworks,
like React, exist and why they are essential in today's web development. Here's a
structured summary and key takeaways:

1. Historical Context of Web Development


●​ Before 2010: Websites were predominantly server-side
rendered.
○​ The server assembled HTML, CSS, and JS, and sent it to
the browser.
○​ JavaScript was minimal, often limited to simple animations
or interactivity via libraries like jQuery.
●​ The Rise of Single Page Applications (SPAs):
○​ SPAs shifted the rendering responsibility from the server to
the client.
○​ These applications consume data from APIs and create
dynamic, responsive UIs without reloading the page.

2. Challenges with Vanilla JavaScript for SPAs

Building complex SPAs with just Vanilla JavaScript leads to


significant issues:

1.​Complexity in DOM Manipulation:


○​ Requires extensive manual selection, traversal, and
manipulation of DOM elements.
○​ Results in spaghetti code that’s hard to maintain or debug.
2.​State Management Issues:
○​ Data (state) often stored directly in the DOM.
○​ Leads to poor structure, lack of centralization, and
numerous bugs.
3.​Interconnected Dependencies:
○​ UI elements and data states are interdependent.
○​ Keeping them synchronized becomes overwhelmingly
complex as the app grows.

3. The Role of Front-End Frameworks


Frameworks like React solve these challenges by:

1.​Synchronizing UI and Data:


○​ Automatically keep the UI updated as the data changes.
○​ Abstract the complexities of manual DOM updates.
2.​Enforcing Code Structure:
○​ Encourage organized, modular, and maintainable
codebases.
○​ Prevent "reinventing the wheel" with custom frameworks.
3.​Consistency for Teams:
○​ Standardize how components, state, and logic are
managed.
○​ Make collaboration and onboarding easier in larger teams.

4. Additional Benefits of Frameworks


●​ Enable building rich, responsive, and interactive applications that
feel like native desktop or mobile apps.
●​ Foster a community of tools, libraries, and practices to enhance
developer productivity.
●​ Modern server-side frameworks (e.g., Next.js) are bringing
server-side rendering back with improvements, combining the
best of both worlds.

Key Insight

Front-end frameworks exist because keeping a user interface


in sync with data is inherently hard. They simplify
development by:

●​ Handling complex data-to-UI synchronization.


●​ Offering robust patterns for building scalable applications.

React, along with Angular, Vue, and others, empowers developers


to focus on crafting engaging user experiences without wrestling
with the intricacies of low-level DOM management.

This foundation sets the stage to dive into how React works and
why it’s uniquely powerful for building SPAs!

React vs Vanilla JavaScript


Key Comparison Between React and Vanilla JavaScript

1.​ File Structure:


○​ React: Combines HTML-like code (JSX) inside JavaScript
for better integration.
○​ Vanilla JavaScript: Separates HTML and JavaScript files,
requiring manual integration.
2.​Element Selection:
○​ React: No manual DOM selection required. JSX handles
element references automatically.
○​ Vanilla JS: Requires manually selecting DOM elements
with document.querySelector.
3.​State Management:
○​ React: Automatically synchronizes state (data) with the
user interface.
○​ Vanilla JS: Developers must manually update the DOM to
reflect changes in state.
4.​Event Handling:
○​ React: Uses onClick or similar attributes directly in JSX
to handle events.
○​ Vanilla JS: Requires attaching event listeners to elements
after selecting them.
5.​UI Updates:
○​ React: Automatically updates the UI when state changes.
○​ Vanilla JS: Requires manually updating DOM elements like
textContent.
Key Insights

●​ React’s Advantage:
○​ Handles UI and state synchronization seamlessly.
○​ Reduces manual DOM manipulation and potential bugs.
○​ Simplifies code, especially for complex applications.
●​ When to Use Vanilla JS:
○​ Suitable for small, simple apps where manual DOM
manipulation is manageable.
○​ For more complex apps, React provides better scalability
and maintainability.
Main Takeaway

React automates the tedious process of keeping the UI and state in


sync, making it highly efficient for building modern, dynamic
applications. While Vanilla JS can work for small projects, React
shines in larger, more complex scenarios.

Overview of React
What is React?

●​ React is a JavaScript library for building user interfaces.


●​ Created by Facebook (now Meta) in 2011, it was open-sourced
in 2013.
●​ React specializes in:
1.​Rendering components on a webpage.
2.​Keeping the UI in sync with state changes by
automatically re-rendering components.
Key Features of React

1.​ Component-Based Design:


○​ UIs are built using reusable components like buttons,
navbars, or listings.
○​ Components can be combined and reused like LEGO
pieces.
2.​Declarative Syntax (JSX):
○​ React uses JSX, a mix of HTML, CSS, and JavaScript, to
describe the UI.
○​ Developers specify what the UI should look like, and React
handles the how.
3.​State-Driven Updates:
○​ React manages state (dynamic data like user input or API
results).
○​ When the state changes, React automatically re-renders
the UI to reflect the new state.
4.​React vs. DOM:
○​ React abstracts away the manual DOM manipulation
required in Vanilla JavaScript.
○​ React uses tools like the virtual DOM and Fiber tree for
efficient updates.
React: Library or Framework?

●​ React is officially a library (focused on the view layer).


●​ To build full applications, additional tools (e.g., routing or data
fetching) are required.
●​ Frameworks like Next.js and Remix extend React to offer more
complete solutions.
Why is React Popular?

1.​ Adoption:
○​ Used by major companies like Facebook, Instagram, and
others.
○​ High demand for React developers in the job market.
2.​Community:
○​ A large and active developer community.
○​ Extensive tutorials, Q&A support, and third-party libraries.
3.​Performance:
○​ Efficient updates through the virtual DOM.
○​ React "reacts" to state changes, ensuring smooth UI
interactions.
React’s Impact

●​ Revolutionized front-end development.


●​ Inspired other frameworks and libraries, influencing the entire
web development landscape.
Summary

React simplifies building dynamic UIs by:

●​ Rendering components based on their state.


●​ Keeping the UI in sync with state changes automatically. Its
popularity, community, and scalability make it a preferred
choice for modern web development.

Setting Up a New React Project


Common Tools for React Project Setup

1.​ Create-React-App (CRA):


○​ Developed to make starting React apps easy.
○​ Pre-configured with:
■​ Development server
■​ Webpack (module bundler)
■​ Linter (ESLint), formatter (Prettier)
■​ Testing library (Jest)
■​ Babel (enabling modern JavaScript features)
○​ Advantages:
■​ Quick and easy setup.
■​ Great for learning, tutorials, and experiments.
○​ Limitations:
■​ Uses outdated tools like Webpack, making it slower.
■​ Not recommended for real-world production projects.
○​ Current Status:
■​ Still useful for learning but not for building large apps.
2.​Vite:
○​ A modern build tool designed for speed and efficiency.
○​ Advantages:
■​ Extremely fast hot module replacement (instant
updates on save).
■​ Faster bundling, ideal for large-scale projects.
○​ Disadvantages:
■​ Requires manual setup of tools (e.g., ESLint, Prettier,
testing libraries).
■​ Can be tricky to configure for React-specific
requirements.
○​ Use Case:
■​ Best for production-ready, real-world applications.
■​ Recommended for the final, larger projects in this
course.

React Frameworks for Project Setup


●​ Examples: Next.js and Remix.
●​ Built on top of React, offering solutions for:
○​ Routing: Handling navigation between pages.
○​ Data Fetching: Managing server-side and client-side data needs.
○​ Server-Side Rendering (SSR): Rendering HTML on the server for better SEO
and performance.
●​ Advantages:
○​ Simplifies tasks React does not handle natively.
○​ Ideal for modern, production-ready applications.
●​ Considerations:
○​ React frameworks are not necessary for learning React basics.
○​ Recommended only for production projects after mastering React itself.

Recommended Approach in This Course


1.​ Small Learning Projects:
○​ Use Create-React-App for ease and quick setup.
2.​ Real-World Applications:
○​ Transition to Vite for a more modern, optimized setup.
3.​ Learning Progression:
○​ Master vanilla React first.
○​ Explore frameworks like Next.js only after building a solid React foundation.

JavaScript Destructuring
1. Introduction to Destructuring

Destructuring is a convenient way to extract values from arrays or


properties from objects into distinct variables. It's especially
useful when dealing with APIs or large datasets.

2. Setting Up the Environment

●​ Create a folder (e.g., JavaScript Review) and add script.js


from the starter files.
●​ Open the folder in VS Code (drag and drop or use the "Open"
option).
●​ Install Quokka.js (VS Code extension) to execute JavaScript
directly in the editor without needing an HTML setup.
○​ Start Quokka via the command palette (Ctrl+Shift+P).
○​ Use it to print and inspect variable outputs interactively.
3. Object Destructuring

●​ Extract multiple properties from an object in a concise way.


Example:

javascript

const book = getBook(2); // Simulating data


retrieval

const { title, author, pages, genres,


hasMovieAdaptation } = book;

console.log(title, author);

●​ Key Points:
○​ The variable names must match the object property
names.
○​ Order does not matter in object destructuring.
Benefits:

●​ Reduces repetitive code like book.title or book.author.


●​ Simplifies handling large objects (e.g., API responses).
Custom Variable Names:

If you need different variable names, use : to rename:

javascript

const { title: bookTitle, author: bookAuthor } =


book;
console.log(bookTitle, bookAuthor);

4. Array Destructuring

●​ Extract elements from arrays based on their order.


Example:

const genres = book.genres; // Example array:


['Sci-Fi', 'Humor', 'Drama']

const [primaryGenre, secondaryGenre] = genres;

console.log(primaryGenre, secondaryGenre); //
Outputs: Sci-Fi, Humor

●​ Key Points:
○​ The first variable matches the first element of the array, the
second variable matches the second element, and so on.
○​ Order does matter in array destructuring.
Skipping Elements:

Use commas to skip unwanted elements:

const [, , tertiaryGenre] = genres; // Skips


first two elements

console.log(tertiaryGenre); // Outputs: Drama


Default Values:

Provide default values for missing elements:

const [primary, secondary, other = 'N/A'] =


genres;

console.log(other); // Outputs: N/A if the third


element is absent
5. Practical Use Cases

●​ APIs:
Destructure response objects to directly access specific
properties.

React: Destructuring is common for props and state management.​



const { name, age } = props;

const [count, setCount] = useState(0);

6. Summary

●​ Object Destructuring: Use {} and match property names to variable


names.
●​ Array Destructuring: Use [] and extract elements by their
order.
●​ Reduces boilerplate code and enhances readability, especially
with complex data structures.
Rest and Spread Operators in JavaScript
1. Rest Operator (...)

The rest operator gathers remaining elements or properties into a


new array or object during destructuring.
Usage with Arrays:

●​ Extract specific elements and group the rest:

const [primaryGenre, secondaryGenre,


...otherGenres] = genres;

console.log(otherGenres); // Remaining elements


in the array

●​ Key Points:
○​ The rest operator must always be the last element in the
destructuring pattern.
○​ It collects all leftover values into an array.
Usage with Objects:

●​ Extract specific properties and group the rest:

const { title, author, ...otherDetails } =


book;

console.log(otherDetails); // Remaining
properties in an object
2. Spread Operator (...)

The spread operator expands elements from arrays or properties


from objects. It's used to create new arrays or objects by
spreading their contents.
Usage with Arrays:

●​ Combine or extend arrays:

const newGenres = [...genres, "Epic Fantasy"];

console.log(newGenres); // Adds "Epic Fantasy" at


the end

●​ Insert elements at the beginning:

const reversedGenres = ["Epic Fantasy",


...genres];

●​ Avoid nested arrays:

const combinedGenres = [...genres1, ...genres2];


Usage with Objects:

●​ Add new properties:

const updatedBook = { ...book, hasMovieAdaptation:


true };
Update existing properties:

const correctedBook = { ...book, pages: 1210 };

Properties listed later in the object literal override earlier ones.

For instance:​

const updatedBook = { pages: 1000, ...book };
// book.pages overrides 1000

Differences Between Rest and Spread


●​ Rest (...):
○​ Gathers values into an array or object.
○​ Used in destructuring.
●​ Spread (...):
○​ Spreads values into new arrays or objects.
○​ Used in array/object creation.
4. Practical Applications

●​ Arrays:
○​ Combine datasets: const allGenres =
[...genres1, ...genres2];
○​ Clone arrays: const clonedGenres = [...genres];
●​ Objects:
○​ Clone objects: const clonedBook = { ...book };

Merge objects:​
const completeBook = { ...book, ...extraDetails
};
●​ React Usage (Preview):

Update state immutably:​


const newState = { ...state, updatedProp:
newValue };
5. Key Takeaways

●​ Rest collects leftover elements or properties.


●​ Spread expands arrays/objects into new ones.
●​ Mastery of these operators is essential for working with React
and modern JavaScript development.

Example: Rest and Spread Operators

Imagine you have a box of crayons with these colors:

javascript

const crayons = ["Red", "Blue", "Green",


"Yellow", "Purple"];
Using the Rest Operator

You want to take the first two colors, but keep the rest of the
crayons in another box.

const [firstColor, secondColor, ...otherColors] =


crayons;

console.log(firstColor); // "Red"

console.log(secondColor); // "Blue"

console.log(otherColors); // ["Green", "Yellow",


"Purple"]
Explanation:

●​ The ...otherColors is like saying: "Gather the leftover


crayons and put them into a new box."
●​ So, the rest operator collects the remaining colors after the first
two.
Using the Spread Operator

Now, you want to create a new box with the same crayons, but add
a new color called "Orange."

javascript

const newCrayons = [...crayons, "Orange"];

console.log(newCrayons); // ["Red", "Blue",


"Green", "Yellow", "Purple", "Orange"]

Explanation:

●​ The ...crayons is like saying: "Take all the crayons out of the
first box and spread them into the new box."
●​ Then, you simply add "Orange" to the end.

Simple Summary:

●​ Rest (...): "Take what’s left and put it in a new container."


●​ Spread (...): "Unpack everything from one container and add it
to a new one."

Just like sorting and combining crayons! 🎨


Understanding Arrow Functions (Like Teaching a Child)

Imagine you're writing a shortcut to do simple tasks faster. Arrow


functions are like those shortcuts for writing functions in
JavaScript. They're quick, especially when the task is just one
line of code.

Let's Start with a Simple Example

Task: Get the year from a date like "2024-12-10"

Here’s how you can do it in the old way and the new arrow function
way
Old Way (Traditional Function):

function getYear(dateString) {

return dateString.split("-")[0];

console.log(getYear("2024-12-10")); // Output:
2024

●​ function: This creates the function.


●​ dateString: The input (the date).
●​ split("-"): This splits the date into parts: "2024", "12",
"10".
●​ [0]: The first part (the year).
●​ return: Gives us the year back.
New Way (Arrow Function):
javascript

const getYear = (dateString) =>


dateString.split("-")[0];

console.log(getYear("2024-12-10")); // Output:
2024

●​ No function keyword: Just write the input (dateString)


directly.
●​ Arrow (=>): Points to what the function does.
●​ No return needed: If it’s one line, the result is automatically
returned.

Why Is the Arrow Function Cool?

1.​Short and Sweet:


○​ Traditional: function getYear(dateString) {
return ... }
○​ Arrow: (dateString) => ...
2.​Great for Small Tasks: It's perfect when you only need a quick
result.
Example in Real Use: Combine with a Sentence

Let’s use the arrow function in a sentence:

const getYear = (dateString) =>


dateString.split("-")[0];
const message = `The book was published in
${getYear("2024-12-10")}.`;

console.log(message);

// Output: "The book was published in 2024."

Summary:

●​ Arrow Functions are like shortcuts for small tasks.


●​ Write (input) => result instead of using function and
return.
●​ Great for simple, one-line tasks like getting the year from a date.

It’s just a faster, simpler way to do what you already know! 😊


Arrow Functions in JavaScript (Simple Explanation)

Arrow functions are a shorter way to write functions. They are


great for quick, simple tasks.

Syntax:

javascript

const functionName = (parameters) => result;

Example:

Regular Function:

javascript

function add(a, b) {

return a + b;
}
Arrow Function:

javascript

const add = (a, b) => a + b;

Both do the same thing but the arrow function is shorter

Key Points:

1.​Short and Easy: No need for the function keyword or


return if it's one line.
2.​Use for Small Tasks: Perfect for quick calculations or simple
operations.

3. If More Lines: Use {} and write return like normal.​


javascript​
Copy code​
const multiply = (a, b) => {

const result = a * b;

return result;

};

Arrow functions save time and keep your code clean! 😊


Logical Operators and Short-Circuiting in JavaScript (Simple
Explanation)

Logical operators like && (AND) and || (OR) have a cool feature
called short-circuiting, which means they sometimes stop
checking values early and return a result. Let's break this down
simply!

1. AND (&&) Operator

●​ Rule: If the first value is false, it immediately returns the first


value.
●​ If the first value is true, it checks the second value and returns
it.
Example:
javascript

console.log(false && "Hello"); // Output: false


console.log(true && "Hello"); // Output: "Hello"

●​ Why? If the first value is false, there's no point checking


further because AND needs both values to be true.

2. OR (||) Operator

●​ Rule: If the first value is true, it immediately returns the first


value.
●​ If the first value is false, it checks the second value and
returns it.
Example:
javascript
console.log(true || "Hello"); // Output: true
console.log(false || "Hello"); // Output: "Hello"

●​ Why? If the first value is true, it doesn’t matter what the second
value is because OR needs only one value to be true.

3. Default Values with OR

You can use || to set default values if the first value is falsy (e.g.,
false, 0, "", null, undefined).
Example:
javascript
const name = "" || "Default Name"; // Output:
"Default Name"

4. The Problem with OR

●​ OR treats 0 or "" (empty string) as false, which can


sometimes be wrong.
Example:
javascript
const reviewsCount = 0 || "No reviews"; //
Output: "No reviews"
// But we wanted: 0
5. The Nullish Coalescing Operator (??)

●​ Fix: Use ?? instead of || to check only for null or undefined.


It doesn’t treat 0 or "" as false.
Example:
javascript
const reviewsCount = 0 ?? "No reviews"; //
Output: 0

Summary:

●​ Use && when you want to check if both conditions are true.
●​ Use || to provide a default, but be careful with 0 or "".
●​ Use ?? if you want to handle only null or undefined.

These tricks are super useful for clean and smart code! 😊

Optional Chaining in JavaScript (Explained Simply)

The optional chaining operator (?.) helps you avoid errors when
accessing properties of objects that might not exist. It's a great
tool to safely handle situations where some data might be
undefined or null. Let’s simplify it with examples.

1. The Problem Without Optional Chaining


If you try to access a property of something that is undefined,
you'll get an error.
Example:
javascript

const book = {
reviews: {
Goodreads: {
reviewsCount: 200,
},
},
};

// This works because `Goodreads` exists.


console.log(book.reviews.Goodreads.reviewsCount);
// Output: 200

// This causes an error because `libraryanything`


doesn't exist.
console.log(book.reviews.libraryanything.reviewsC
ount);
// Error: Cannot read properties of undefined
(reading 'reviewsCount')

The code crashes when it tries to access .reviewsCount of


something that doesn’t exist (libraryanything in this case).

2. Solution: Optional Chaining (?.)


Use ?. to check if a property exists before trying to access it.
Example:
javascript
// Using optional chaining
console.log(book.reviews.libraryanything?.reviews
Count); // Output: undefined

●​ If libraryanything doesn't exist, the chain stops, and the


result is undefined.
●​ No errors, just a safe undefined.

3. Adding a Default Value

If undefined isn’t acceptable, combine optional chaining with the


nullish coalescing operator (??) to provide a default value.
Example:
javascript
const reviewsCount =
book.reviews.libraryanything?.reviewsCount ??
0;
console.log(reviewsCount); // Output: 0

Here:

●​ If reviewsCount doesn’t exist, it defaults to 0.

4. When to Use Optional Chaining

Use ?. whenever:

1.​You're unsure if a property exists.


2.​You're dealing with deeply nested objects.
3.​You want to avoid writing extra if checks.
Example:

Without optional chaining:

javascript
if (book.reviews && book.reviews.libraryanything)
{

console.log(book.reviews.libraryanything.review
sCount);
}

javascript
console.log(book.reviews.libraryanything?.reviews
Count);

5. Full Example

Let’s calculate the total reviews from two sources (Goodreads and
libraryanything):

javascript
function getTotalReviewCount(book) {
const goodreadsCount =
book.reviews.Goodreads?.reviewsCount ?? 0;
const libraryanythingCount =
book.reviews.libraryanything?.reviewsCount ??
0;
return goodreadsCount + libraryanythingCount;
}

// Test cases
const book1 = {
reviews: {
Goodreads: { reviewsCount: 200 },
libraryanything: { reviewsCount: 50 },
},
};
const book2 = {
reviews: {
Goodreads: { reviewsCount: 300 },
},
};

console.log(getTotalReviewCount(book1)); //
Output: 250
console.log(getTotalReviewCount(book2)); //
Output: 300

Summary:

1.​?.: Stops the chain if the value is undefined or null.


2.​??: Provides a default value when the result is undefined or
null.
Combine them for safe and concise code:​
javascript​

const value = object?.nestedProperty ??
defaultValue;

😊
Optional chaining saves time, avoids errors, and keeps your code
clean!

Example: Finding a Toy in a Box (Optional Chaining)

Imagine you have a box of toys, but sometimes the box is empty.
You want to find out if there’s a car toy inside without breaking
the box.

Without Optional Chaining (Risky Way):

You open the box, then look inside for the car.

javascript
Copy code
const toyBox = {}; // The box is empty!

console.log(toyBox.car.type);
// ERROR! You tried to check the `type` of a car
that doesn’t exist.

With Optional Chaining (Safe Way):


You gently check if there’s a car in the box before asking for its
type.

javascript
const toyBox = {}; // The box is empty!

console.log(toyBox.car?.type);
// Output: undefined (No error! The box is empty,
and there’s no car.)

If the box has a car:

javascript
const toyBox = {
car: { type: "red sports car" },
};

console.log(toyBox.car?.type);
// Output: "red sports car" (It safely found the
car!)

Simple Explanation:

●​ Without optional chaining:


You might break the box (error) if you look
for something that’s not there.
●​ With optional chaining (?.): You check carefully if the thing
exists first, and avoid breaking anything.
Explaining the map Method with a Simple Example
Imagine This:

You have a basket of apples, and each apple has a sticker with its
weight written on it. You want to make a list of just the weights
from all the apples.
The map Method in Action:

Let’s say your apples are represented as objects in an array:

javascript
const apples = [
{ color: "red", weight: 150 },
{ color: "green", weight: 130 },
{ color: "yellow", weight: 170 },
];

Now, you want a new array with only the weights of these apples.

Without map (The Long Way):

You'd write a loop to pick out the weights:

javascript
const weights = [];
for (let apple of apples) {
weights.push(apple.weight);
}

console.log(weights); // [150, 130, 170]

With map (The Easy Way):

The map method does this automatically by "mapping" each apple


to its weight:

javascript
const weights = apples.map(apple =>
apple.weight);

console.log(weights); // [150, 130, 170]

Simple Explanation:

●​ The map method takes an array, looks at each item, and


creates a new array based on some rule (like picking the
weights in this case).
●​ It does not change the original array.

What Happened Here?

1.​apples.map(apple => apple.weight) means:


○​ apple: Each item in the apples array (one at a time).
○​ apple.weight: The property you want to pick from each
apple.
2.​The result is a new array [150, 130, 170].

Why is map Useful?

It helps you quickly create new arrays by applying a rule to every


item.​
For example:

●​ Getting a list of names from a group of people.


●​ Converting prices from one currency to another.
●​ Doubling numbers in an array.

It's like a magic shortcut for transforming arrays!

Give an simple defination

The map method in JavaScript is a way to create a new array by


applying a specific rule or operation to each item in an existing
array. It does not change the original array.

For example:​
If you have numbers [1, 2, 3] and want to double them, you
can use map like this:

javascript
const numbers = [1, 2, 3];
const doubled = numbers.map(num => num * 2);
console.log(doubled); // [2, 4, 6]
Think of map as a tool that "transforms" each item in the array!

The filter method in JavaScript is used to pick specific items


from an array based on a condition. It loops through the array,
checks each item, and keeps only the ones that match the
condition. The result is a new array with the filtered items, and it
does not modify the original array.

Simple Example:

Imagine you have a basket of fruits, and you only want the apples.

javascript
const fruits = ['apple', 'banana', 'orange',
'apple', 'grape'];
const apples = fruits.filter(fruit => fruit ===
'apple');
console.log(apples); // ['apple', 'apple']

Here, the filter checks each fruit, and if it's an "apple," it keeps it in
the new array.

Key Points:

1.​Returns a new array: Only items that meet the condition are
included.
2.​Does not change the original array.
3.​Used to filter data, like finding books with more than 500 pages
or products in stock.
It's like a strainer that separates the items you want from the ones
you don't!

The filter method in JavaScript is used to create a new array


with only the items that meet a specific condition, leaving out the
rest. It does not change the original array.

The reduce method in JavaScript is used to combine all


elements of an array into a single value by repeatedly
applying a function to each element and an accumulator (a
running total or result). It does not change the original array.

It’s particularly useful for tasks like summing numbers, merging


data, or building new structures.

Sure! Let's say we want to find the total number of pages in a list
of books. Here's how we can do it using the reduce method,
explained like you're teaching a child:

Example:

Imagine you have this list of books:

javascript
const books = [
{ title: "Book 1", pages: 200 },
{ title: "Book 2", pages: 150 },
{ title: "Book 3", pages: 300 }
];

Now, we want to add up all the pages to find the total.


Code:
javascript
const totalPages = books.reduce((sum, book) => {
return sum + book.pages; // Add the current
book's pages to the sum
}, 0); // Start with 0 as the initial sum

console.log(totalPages); // Output: 650

Explanation:

1.​What does reduce do?


○​ Imagine you are holding a box (the accumulator, called
sum) where you will collect the total pages.
○​ You start with an empty box (0 as the initial value).
○​ For each book, you add its pages to the box.
2.​Step-by-step process:
○​ Start with sum = 0.
○​ Take the first book (Book 1) and add its pages (200) to
the box → Now, sum = 200.
○​ Move to the second book (Book 2) and add its pages
(150) to the box → Now, sum = 200 + 150 = 350.
○​ Finally, add the pages of the third book (300) → Now, sum
= 350 + 300 = 650.
3.​Result:
○​ The total number of pages is 650.

It's like going through a stack of books and adding their pages one

😊
by one until you know how many pages you'd need to read them
all.
Give another example​

Sure! Here's another simple example: Finding the total price of


items in a shopping cart.

Example:

Imagine you went shopping and your cart has these items:

javascript
Copy code
const cart = [
{ item: "Apple", price: 2 },
{ item: "Banana", price: 1 },
{ item: "Milk", price: 3 }
];

You want to calculate the total price of everything in your cart.

Code:
javascript
Copy code
const totalPrice = cart.reduce((sum, product) =>
{
return sum + product.price; // Add the current
product's price to the sum
}, 0); // Start with 0 as the initial sum
console.log(totalPrice); // Output: 6

Explanation:

1.​What are we doing?


○​ We’re starting with no money (sum = 0).
○​ Then, we add the price of each product in the cart to our
total.
2.​Step-by-step:
○​ Start with sum = 0.
○​ Look at the first item, Apple (price: 2). Add it to sum →
Now, sum = 0 + 2 = 2.
○​ Next, look at the second item, Banana (price: 1). Add it to
sum → Now, sum = 2 + 1 = 3.
○​ Finally, look at Milk (price: 3). Add it to sum → Now, sum =
3 + 3 = 6.
3.​Result:
○​ The total cost of your shopping cart is $6.

😊
This is like counting the money you'll need to pay for all the items,
one by one, until you know the final amount.

Here’s a simplified explanation with an example to help understand


the sort method:

Example: Sorting Numbers in a List


Imagine you have a list of numbers that you want to sort from
smallest to largest:

javascript

Copy code

const numbers = [10, 2, 5, 1, 8];

Sorting in Ascending Order:

To sort these numbers from smallest to largest:

javascript

Copy code

const ascending = numbers.slice().sort((a, b) =>


a - b);

console.log(ascending); // Output: [1, 2, 5, 8,


10]

●​ What happens?
○​ The sort method compares two numbers at a time (a and
b).
○​ If a - b is:
■​ Negative: a comes before b (smaller number first).
■​ Positive: b comes before a.
■​ Zero: The order doesn’t change.
Sorting in Descending Order:

To sort from largest to smallest:

javascript

Copy code

const descending = numbers.slice().sort((a, b) =>


b - a);

console.log(descending); // Output: [10, 8, 5, 2,


1]

●​ What happens?
○​ Now we subtract a from b. This flips the logic so bigger
numbers come first.

Key Points:

1.​Mutates Original Array:


○​ The sort method changes the original array. To avoid this,
use slice() to make a copy before sorting.
2.​Sorting Objects (Practical Use):
○​ For an array of objects, you compare specific properties.
For example:

javascript

Copy code
const books = [

{ title: "Book A", pages: 150 },

{ title: "Book B", pages: 300 },

{ title: "Book C", pages: 100 }

];

const sortedBooks = books.slice().sort((a, b) =>


a.pages - b.pages);

console.log(sortedBooks);

// Output: [{title: "Book C", pages: 100},


{title: "Book A", pages: 150}, {title: "Book
B", pages: 300}]

This way, you can use the sort method to organize arrays in
ascending or descending order based on any criteria.🎉
The sort method in JavaScript is used to
arrange the elements of an array in a specific
order, either ascending (smallest to largest) or
descending (largest to smallest).
●​ It works by comparing two elements at a time using a function
you provide.
●​ By default, it converts elements to strings and sorts them
alphabetically, but you can customize it to sort numbers or
objects.

For example:

javascript

const numbers = [5, 2, 9, 1];

const ascending = numbers.sort((a, b) => a - b);


// Sorts in ascending order

console.log(ascending); // [1, 2, 5, 9]

Here's a simple definition and examples for these essential array


operations in React to avoid mutating the original array:

1. Add an Element to an Array (Immutable Way)

●​ Definition: Create a new array by copying the original elements


and adding the new element.
●​ Why: React doesn't like direct changes (mutations).

Example:
javascript

const books = [{ id: 1, title: "Book 1" }, { id:


2, title: "Book 2" }];

const newBook = { id: 3, title: "Book 3" };

// Add new book

const updatedBooks = [...books, newBook];

console.log(updatedBooks);

// Result: [{id: 1, title: "Book 1"}, {id: 2,


title: "Book 2"}, {id: 3, title: "Book 3"}]

2. Delete an Element from an Array (Immutable Way)

●​ Definition: Use the filter method to create a new array


without the element you want to delete.
●​ Why: filter removes items without changing the original
array.

Example:

javascript
// Delete book with id = 2

const filteredBooks = books.filter(book =>


book.id !== 2);

console.log(filteredBooks);

// Result: [{id: 1, title: "Book 1"}]

3. Update an Element in an Array (Immutable Way)

●​ Definition: Use the map method to create a new array with the
updated element while keeping others unchanged.
●​ Why: map keeps the array length the same, updating only the
specified element.

Example:

javascript

// Update book with id = 1

const updatedBooksArray = books.map(book =>

book.id === 1 ? { ...book, title: "Updated Book


1" } : book

);

console.log(updatedBooksArray);
// Result: [{id: 1, title: "Updated Book 1"},
{id: 2, title: "Book 2"}]

Key Points to Remember

1.​Add: Use the spread operator [...] to include existing items


and append the new one.
2.​Delete: Use filter to exclude the element you want to
remove.
3.​Update: Use map to find and update only the target element.

These techniques are essential for handling arrays in React while


keeping data immutable!

**************************************

This is a great foundational walkthrough of how to work with


asynchronous JavaScript using Promises and the Fetch API.
Here's a summary and some key takeaways:

Summary:

1.​Fetch API Basics:


○​ The fetch() function is used to make HTTP requests and
returns a Promise.
○​ You provide the API URL to fetch().
2.​Promise States:
○​ pending: The operation is still in progress.
○​ fulfilled: The operation completed successfully.
○​ rejected: An error occurred.
3.​Handling the Promise:
○​ The then() method allows you to handle the fulfilled
state and process the data returned from the API.
○​ Data conversion (e.g., res.json()) is also asynchronous
and returns another Promise, requiring chaining another
then().
4.​Asynchronous Nature:
○​ JavaScript continues executing subsequent lines of code
without waiting for the asynchronous operation to complete.
○​ Callbacks registered with then() are executed only when
the data is ready.

Key Takeaways:

●​ Non-blocking Execution: JavaScript doesn’t pause for the


Fetch API or any asynchronous operations—it executes the rest
of the code and handles asynchronous tasks as they complete.
●​ Promise Chaining: Each asynchronous operation in the chain
must handle its Promise properly, enabling structured data
handling.
●​ Practical Application: While logging data is great for learning,
real-world applications often involve manipulating UI elements
(e.g., updating state in React).

Suggested Improvements for Explanation:

1.​Clarity on .json():
○​ Highlight that res.json() parses the response body into
a JavaScript object and why it returns a Promise.
2.​Error Handling:
Demonstrate catch() to handle errors in the chain for a more
robust solution:​
javascript​

fetch('https://jsonplaceholder.typicode.com/tod
os')

.then((res) => {

if (!res.ok) throw new Error(`HTTP error!


status: ${res.status}`);

return res.json();

})

.then((data) => console.log(data))

.catch((err) => console.error('Error:', err));

○​
3.​Async/Await Alternative:

Suggest using async/await for cleaner and more readable code,


which is especially useful for more complex workflows:​
javascript​

async function fetchData() {

try {

const res = await


fetch('https://jsonplaceholder.typicode.com/tod
os');
if (!res.ok) throw new Error(`HTTP error!
status: ${res.status}`);

const data = await res.json();

console.log(data);

} catch (err) {

console.error('Error:', err);

fetchData();

○​
4.​Practical Examples:
○​ Mention how the fetched data can be displayed or
processed further (e.g., rendering UI components in
React).

This explanation covers both conceptual understanding and


practical implementation details, providing a comprehensive
guide to asynchronous JavaScript with Promises.
Sure! Let’s break it down with a simple story and a simple
example:

The Story:

Imagine you're at a pizza shop. You order a pizza (this is like calling
the fetch function).

●​ While the pizza is being baked (fetching data), you don’t just sit
there doing nothing! You might chat with a friend or play a game
on your phone (this is JavaScript running other lines of code).
●​ When the pizza is ready, the chef calls you and hands it over
(this is like the then() method handling the data when it’s
ready).

The Example:

Here’s a simple code example that matches this story:

javascript

console.log("Ordering a pizza...");

fetch('https://jsonplaceholder.typicode.com/todos
/1')
.then((response) => response.json()) // Wait
for the "pizza" to be ready

.then((data) => {

console.log("Pizza is ready:", data); // Eat


the "pizza"

});

console.log("Playing a game while waiting for the


pizza...");

What Happens:

1.​You see "Ordering a pizza..." printed first because that happens


immediately.
2.​Then "Playing a game while waiting for the pizza..." gets
printed because JavaScript doesn’t wait for the pizza (or data) to
be ready.
3.​Finally, when the data arrives, you see "Pizza is ready:" and the
fetched data.

Ordering a pizza...

Playing a game while waiting for the pizza...


Pizza is ready: { userId: 1, id: 1, title:
"delectus aut autem", completed: false }

This shows how JavaScript handles tasks in the background

🍕
without stopping everything else—just like how you keep busy
while waiting for your pizza!

Async/Await in JavaScript
1.​ What is Async/Await?
○​ A cleaner way to work with Promises.
○​ Makes asynchronous code look like regular synchronous code.
2.​ How to Use Async/Await:
○​ Use async before a function to make it an async function.
○​ Use await inside the async function to pause code until a Promise
resolves.
Example Code:​
javascript​

async function getTodos() {
const response = await
fetch('https://jsonplaceholder.typicode.com/todos/1');
const data = await response.json();
console.log(data);
}
getTodos();
console.log("This runs before the data arrives.");
3.​
○​ What happens?
■​ Fetch starts, JavaScript moves to the next line.
■​ await pauses inside the getTodos function until data is fetched.
■​ Console logs data after fetching but only inside the async
function.
4.​ Key Points to Remember:
○​ await only works inside async functions.
Async functions always return a Promise.​
javascript​

const todos = getTodos(); // `todos` is a Promise, not the actual data.
○​
○​ To use the result outside, chain .then() or use another async
function.

5.​ Comparison with Promises:


Promise (Old Way):​
javascript​

fetch('url')
.then(res => res.json())
.then(data => console.log(data));
○​
Async/Await (New Way):​
javascript​

const response = await fetch('url');
const data = await response.json();
console.log(data);
○​ Async/Await is more readable and feels like normal code.
6.​ Common Use in React:
○​ Use async functions to fetch data and directly update the state inside
the function.
7.​ Remember:
○​ Async functions still rely on Promises.
○​ JavaScript doesn’t pause outside the async function—it just looks
paused inside.

Debugging React Apps


1.​Common Issues and Fixes:
○​ App not updating:
■​ Make sure the app is running (npm start).
■​ If it’s running but not updating, stop (Ctrl + C) and
restart (npm start).
○​ Browser not reloading:
■​ Do a hard reload (refresh button).
2.​Use Developer Tools:
○​ Keep the terminal open to check if the app is running.
○​ Open browser dev tools (console) to see errors or
warnings.
3.​Error Messages:
○​ Read the error message carefully.
○​ If unclear, copy it and Google the error.
○​ React’s large community ensures you’ll find solutions
online.
4.​Handling Bugs:
○​ Use ESLint to spot potential issues (e.g., unused
variables).
○​ Check the Problems tab in VS Code for errors.
○​ Compare your code with the correct final project code if
needed.
5.​React Version:
○​ Check your React version in the package.json file.
Example: Fixing a React Error

Problem:​
You try to return multiple elements in JSX, but React gives this
error:

"Adjacent JSX elements must be wrapped in an enclosing


tag."

Cause:​
React doesn’t allow multiple sibling elements without wrapping
them in a single parent.

Solution:​
Wrap the elements inside a <div> or a React Fragment.

Example Code:

Before (Error):

jsx

return (

<h1>Hello</h1>

<p>This is an error.</p>

);

After (Fixed):
jsx

return (

<div>

<h1>Hello</h1>

<p>This is fixed!</p>

</div>

);

Or with a React Fragment:

jsx

return (

<>

<h1>Hello</h1>

<p>This is fixed!</p>

</>

);
Explanation for Kids:​
Imagine you have two toys, and React says, "You can’t leave

😊
them loose; put them in a box first!" So, we wrap our toys
(elements) in a box (<div> or <>). Now React is happy!

React Components
1.​What Are Components?
○​ Components are the building blocks of any React app.
○​ React apps are made entirely of components.
○​ Each component:
■​ Has its own data, logic, and appearance.
■​ Renders a small piece of the user interface (UI).
2.​Why Use Components?
○​ They help build complex UIs by combining smaller
components like Lego pieces.
○​ Components can be nested (placed inside one another).
○​ Components can be reused, saving time and effort.
3.​Component Relationships:
○​ Components can have parent-child relationships:
■​ A parent component contains one or more child
components.
4.​Component Tree:
○​ A diagram showing the hierarchy and relationships
between components.
○​ Helps visualize how components are nested and
connected.

Example: Building a Simple UI

Imagine making a fruit shop app.


Breaking It into Components:

1.​ Parent Component:


○​ Shop: The main app that holds everything.
2.​Child Components:
○​ FruitList: Displays a list of fruits.
○​ FruitItem: Shows details of a single fruit (e.g., name,
price).
Code Example:

jsx

function Shop() {

return (

<div>

<h1>Welcome to the Fruit Shop!</h1>

<FruitList />

</div>

);
}

function FruitList() {

return (

<div>

<FruitItem name="Apple" price="$1" />

<FruitItem name="Banana" price="$0.5" />

<FruitItem name="Cherry" price="$2" />

</div>

);

function FruitItem(props) {

return (

<div>

<p>{props.name} - {props.price}</p>

</div>

);

}
Explanation for Kids:

●​ Shop is like the big box that holds everything.


●​ FruitList is a smaller box inside the Shop that lists all the fruits.
●​ FruitItem is the smallest box for each fruit.
●​ Props (like name and price) are like labels you stick on the
FruitItem boxes to tell them what to show.

This way, we can reuse FruitItem for each fruit, making our work
faster and neater! 😊

JSX in React
1.​What is JSX?
○​ JSX is a special syntax used in React to describe how
components look and behave.
○​ It looks like HTML, but it’s actually a mix of HTML, CSS,
and JavaScript.
○​ Each React component must return one block of JSX to
define its appearance.
2.​Why Use JSX?
○​ JSX makes code easier to write and read compared to
using plain JavaScript functions.
○​ React uses a tool called Babel to convert JSX into regular
JavaScript because browsers don’t understand JSX.
○​ Behind the scenes, JSX becomes React.createElement
function calls to render HTML.
3.​Declarative vs. Imperative:
○​ Imperative (Vanilla JavaScript):
■​ You tell the browser step-by-step what to do (e.g.,
select elements, update them manually).
■​ Example: "Go to this button, change its text to
'Clicked'."
○​ Declarative (React and JSX):
■​ You tell React what the UI should look like, and React
figures out the rest.
■​ Example: "Show this button text based on the data."
4.​Benefits of JSX and Declarative Approach:
○​ No need to manipulate the DOM directly (e.g., no
document.querySelector or addEventListener).
○​ The UI is always in sync with the data (e.g., props and
state).
○​ React handles the hard work of updating the UI for us.

Example: Button Text Update


With Imperative Approach (Vanilla JavaScript):

javascript

const button = document.querySelector('button');


button.addEventListener('click', () => {
button.textContent = 'Clicked!';
});

●​ Here, we tell the browser exactly how to update the text when
the button is clicked.

With Declarative Approach (React and JSX):


jsx

function App() {
const [text, setText] = React.useState("Click me");

return (
<button onClick={() => setText("Clicked!")}>
{text}
</button>
);
}

●​ Here, we tell React what the button should show based on the
text variable.
●​ React automatically updates the button when the text changes.

Explanation for Kids:


Imagine you’re building a Lego house.
●​ Imperative approach: You tell someone exactly which Lego
pieces to pick and where to place them.
●​ Declarative approach: You show a picture of the house and say,
"Build this."

😊
React with JSX is like showing the picture—it simplifies things and
lets React do the hard work for you!

JSX and React's Separation of Concerns


1.​Traditional vs. React's Approach:
○​ Traditional Web Development:
■​ HTML, CSS, and JavaScript are in separate files (one
technology per file).
■​ This was called traditional separation of concerns.
○​ React's Approach:
■​ Each component contains its HTML (JSX), CSS, and
JavaScript together.
■​ This is called component-based separation of
concerns, meaning one concern per component
instead of per file.
2.​Why Combine Everything in a Component?
○​ In modern apps, JavaScript controls HTML and UI behavior
tightly.
○​ If JavaScript and UI (HTML/JSX) are so connected, it
makes sense to keep them together.
○​ This is called co-location: putting related things close
together.
3.​Benefits of React's Component-Based Approach:
○​ All data, logic, and UI for a specific part of the app are in
one place (the component).
○​ Makes components easier to understand, change, and
reuse.
4.​React Still Has Separation of Concerns:
○​ React separates concerns per component, not per file.
○​ Each component handles one part of the UI and keeps
everything related to that part together.

Example: Button Component

Traditional Approach:

HTML file:​
html​

<button id="myButton">Click me</button>

●​
CSS file:​
css​

#myButton {

background-color: blue;

color: white;

●​

JavaScript file:​
javascript​

const button =
document.getElementById('myButton');

button.addEventListener('click', () => {

alert('Button clicked!');

});

●​
●​ All logic, style, and UI are in different files.
React Approach:

jsx

function Button() {
return (

<button

style={{ backgroundColor: "blue", color:


"white" }}

onClick={() => alert("Button clicked!")}

>

Click me

</button>

);

●​ All related parts (UI, logic, style) are in one component.

Explanation for Kids:

Imagine you have a toy box for every type of toy.

●​ Traditional way: You keep the toy car in one box, its wheels in
another, and instructions in a third box.
●​ React way: You put the toy car, its wheels, and its instructions
all in one box.

😊
React makes it easier to find and work on one "toy" (or part of your
app).
Props in React
1.​What are Props?
○​ Props (short for properties) are used to pass data from a
parent component to a child component.
○​ They allow communication between components and help
configure or customize child components.
○​ Props are like arguments in JavaScript functions.
2.​What Can We Pass as Props?
○​ Any type of value:
■​ Single values (e.g., numbers, strings).
■​ Arrays, objects, functions, or even other React
components.
3.​Props vs. State:
○​ Props: Data from parent to child. Immutable (cannot be
changed by the child).
○​ State: Internal component data that can change over
time.
4.​Why Are Props Immutable?
○​ React uses pure functions for components to avoid side
effects (unexpected changes to external data).
○​ If props were mutable, changing them in a child would also
change the parent, creating bugs.
5.​One-Way Data Flow:
○​ Data flows from parent to child only (top to bottom).
○​ This makes React apps predictable, easy to understand,
and debug.
Example: Greeting Component

jsx

function Greeting(props) {

return <h1>Hello, {props.name}!</h1>;

function App() {

return <Greeting name="Alice" />;

Explanation (Like Teaching a Child):

●​ Imagine you're a teacher writing a note to a student.


●​ The teacher (parent) passes the note (props) with the student's
name to the student (child).
●​ The student just reads the note and can't change it.

In the example, Greeting is the student. The name prop is the


note passed by the App (teacher).

Fun Fact: Props make React apps organized because each

😊
component knows only what it’s told, just like following
instructions!
Rules of JSX
1.​What is JSX?
○​ JSX looks like HTML, but it works with JavaScript.
○​ You can add JavaScript expressions in JSX by using
curly braces {}.
2.​Allowed in JSX:
○​ Variables, arrays, objects, operators (e.g., ternary ? :),
and loops (e.g., map).
3.​Not Allowed in JSX:
○​ Statements like if/else, for, or switch.
4.​JSX Produces Expressions:
○​ JSX creates JavaScript expressions that can be stored in
variables, passed to functions, or used in conditions.
○​ Example: Assign JSX to a variable or use it in a conditional.
5.​One Parent Rule:
○​ JSX must have one root element (like a container).
○​ To include multiple elements, wrap them in a React
Fragment (like <></>).
6.​Differences from HTML:
○​ Class → className
○​ Inline styles → Use objects (e.g., style={{ color:
'red' }})
○​ Self-closing tags required for empty elements (e.g., <img
/>).

Example: JSX in Action

jsx
function Greeting() {

const name = "Alice";

const message = <p>Hello, {name}! Welcome to


React.</p>;

return (

<div>

{message}

<p>This is a simple JSX example.</p>

</div>

);

Explanation (Like Teaching a Child):

●​ Think of JSX as LEGO blocks. Each block is a small HTML-like


piece, but you can mix it with JavaScript using {}.
●​ In this example:
○​ name = "Alice" is like writing a name on one LEGO
block.
○​ {name} puts that name into the sentence "Hello, Alice!"
●​ To avoid the blocks falling apart, you need one box (parent
element) to hold all the pieces, like the <div> here.
JSX = Build things step by step, like playing with LEGO! 😊
LEGO refers to a popular toy brand known for its colorful
interlocking plastic bricks that you can use to build models,
like houses, cars, or anything you imagine.

When people talk about "LEGO" outside of toys, they often mean:

●​ Building things step by step or combining smaller pieces to


create something bigger—just like how LEGO bricks connect.

For example, in coding or design, saying "it's like LEGO" means

😊
you can create something complex by putting together small,
reusable pieces.

Rendering Lists in React


1.​What is Rendering a List?
○​ Rendering a list means creating a component for each
item in an array.
○​ Example: If you have 4 items in an array, you dynamically
create 4 components.
2.​How to Render a List?
○​ Use the map method to loop through the array and return a
component for each item.
○​ Example: For a list of pizzas, render a pizza component for
each pizza in the array.
3.​Key Rules for Rendering Lists:
○​ Each list item must have a unique key prop for better
performance and to avoid warnings.
○​ The map method works because it creates a new array of
JSX elements.
○​ React doesn't use forEach here because it doesn’t return
anything.
4.​Why Use a Key?
○​ React uses the key to efficiently track changes, additions,
or deletions in the list.
5.​Semantic Markup:
○​ Use proper HTML structure, like <ul> for unordered lists
and <li> for list items.

Example: Rendering a Pizza List

Here’s a simple way to render a list of pizzas dynamically:


Pizza Data

javascript

const pizzaData = [

{ id: 1, name: "Margherita" },

{ id: 2, name: "Pepperoni" },

{ id: 3, name: "Veggie" },

];
Rendering the List

javascript

function App() {

return (

<ul>

{pizzaData.map((pizza) => (

<li key={pizza.id}>{pizza.name}</li>

))}

</ul>

);

What Happens?

●​ pizzaData.map: Loops through the array.


●​ <li>: Creates a list item for each pizza.
●​ key={pizza.id}: Gives each item a unique key.
React Fragments

1.​What is a React Fragment?


○​ A React Fragment lets you group multiple elements
without adding extra HTML to the DOM.
○​ It solves the problem where JSX must have one parent
element.
2.​Why Use React Fragments?
○​ Avoids adding unnecessary elements like <div> that could
mess up your layout or styling.
○​ Keeps the HTML structure clean.
3.​How to Use a Fragment?
○​ Instead of wrapping elements in a <div>, use <> and </>
(the shorthand for a fragment).
○​ If you need to use a key (e.g., in lists), use the full syntax:
<React.Fragment>.

Example: Using React Fragments

Without Fragment (Throws Error)

javascript

function App() {

return (

<>

<p>No pizzas available</p>

<ul>
<li>Pizza 1</li>

<li>Pizza 2</li>

</ul>

</>

);

Output in DOM

html

<p>No pizzas available</p>

<ul>

<li>Pizza 1</li>

<li>Pizza 2</li>

</ul>

Why Not Just Use <div>?

If you wrap elements with <div> instead of a fragment:


javascript

function App() {

return (

<div>

<p>No pizzas available</p>

<ul>

<li>Pizza 1</li>

<li>Pizza 2</li>

</ul>

</div>

);

Output in DOM (Unnecessary Div Added):

html

<div>

<p>No pizzas available</p>


<ul>

<li>Pizza 1</li>

<li>Pizza 2</li>

</ul>

</div>

This extra <div> can mess up your layout, which fragments avoid.

Key Takeaway

React Fragments allow you to group elements without affecting

😊
the DOM. Use them whenever you don’t want extra wrapper
elements in your HTML!

Conditional Text and Class Names in React


1.​What is Conditional Text?
○​ Use conditional rendering to change the content inside an
element based on certain conditions.
○​ Example: Show "Sold Out" if a pizza is unavailable;
otherwise, show the price.
2.​How to Do Conditional Text?

Use the ternary operator inside JSX:​


jsx​

condition ? "If true, show this" : "If false,
show this"

○​

Example:​
jsx​

<span>{pizza.soldOut ? "SOLD OUT" :
`$${pizza.price}`}</span>

○​
3.​What is Conditional Class?
○​ Add a class name conditionally to an element (e.g., to
make it look grayed out).

Use a template literal for class names:​


jsx​

`baseClass ${condition ? "conditionalClass" :
""}`

○​

Example:​
jsx​
Copy code​
<li className={`pizza ${pizza.soldOut ?
"sold-out" : ""}`}></li>

○​
4.​Benefits in React:
○​ No need for manual DOM manipulation like in plain
JavaScript.
○​ JSX makes it cleaner and declarative.

Example: Conditional Text and Class

Imagine we’re making a pizza app.


Code Example:

jsx

function PizzaItem({ pizza }) {

return (

<li className={`pizza ${pizza.soldOut ?


"sold-out" : ""}`}>

<span>{pizza.soldOut ? "SOLD OUT" :


`$${pizza.price}`}</span>

</li>

);

// Example Data:
const pizza = { name: "Margherita", price: 10,
soldOut: true };

// Renders:

<PizzaItem pizza={pizza} />

What Happens?

●​ If Sold Out:
○​ The text will show "SOLD OUT."
○​ The li will have the class pizza sold-out.
○​ It will look grayed out.
●​ If Not Sold Out:
○​ The text will show the price, e.g., $10.
○​ The li will have the class pizza.

Key Takeaway

React makes it super easy to set text and classes based on

😊
conditions. Use ternary operators and template literals to keep
the code simple and clean.
React Basics Recap
1.​Components
○​ Building blocks of a React app.
○​ Self-contained: includes data, logic, and appearance.
○​ Return JSX to describe what users see on the screen.
2.​JSX
○​ Combines HTML, CSS (via style prop), and JavaScript
(inside {} curly braces).
○​ Declarative: describes what the UI should look like.
3.​Component Tree
○​ Components are organized into a tree:
■​ Parent Component: Uses/includes other
components.
■​ Child Component: Used by its parent.
○​ Example: App → Header, Menu, Footer → Pizza Items,
Order.
4.​Props
○​ Pass data from parent to child components.
○​ Props are read-only (cannot mutate them).
○​ Example: Pass different pizza objects to a Pizza
component.
○​ Data flows downward only (parent → child).
5.​Lists
○​ Render multiple components by looping through arrays
using the map() method.
○​ Example: Create a pizza list from an array of pizza objects.
6.​Conditional Rendering
○​ Render components based on conditions:
■​ Use &&, ternary operators, or multiple returns.
○​ Example: Show "Sold Out" text if a pizza is unavailable.
7.​Key Theoretical Concepts
○​ Imperative vs Declarative: React focuses on declarative
code.
○​ Separation of Concerns: Keep logic, data, and UI
structured.
○​ Props Immutability: Props should not be changed.

Key Takeaways

React simplifies building user interfaces by using components, JSX,

😊
props, lists, and conditional rendering—all while leveraging
JavaScript skills you already know!

Understanding State in React


1.​What is State?
○​ State is data a component can hold and "remember" over
time.
○​ Acts as the "memory" of a component.
○​ Examples:
■​ Notification count
■​ Input field text
■​ Active tab in a component
■​ Shopping cart content
2.​Why is State Important?
○​ Makes apps interactive by changing the UI based on
actions.
○​ Keeps data in sync with the user interface.
○​ Helps a component persist local variables between
renders.
3.​How is State Different from Props?
○​ Props: Data passed into a component from outside.
○​ State: Data managed within the component itself.
4.​Key Features of State:
○​ React re-renders the component whenever the state
updates.
○​ Allows for dynamic changes to the UI.
5.​State Terminology:
○​ Piece of State: A single state variable (e.g., count,
isActive).
○​ State: General term for all pieces of state in a component.
6.​Tools for Managing State in React:
○​ useState hook
○​ useReducer hook
○​ Context API
○​ External tools like Redux
7.​Summary:
○​ State updates trigger UI updates.
○​ State is a powerful tool to create interactive components.
○​ Mastering state is crucial to React development.

Let’s now practice using state in code!

Example: Counting Button Clicks

Let’s build a simple button that keeps track of how many times it’s
clicked. This is a perfect example of using state in React.

Code:

Javascript
import React, { useState } from 'react';

function Counter() {

// 1. Create a state variable called "count"


with a starting value of 0.

const [count, setCount] = useState(0);

// 2. This function updates the state when the


button is clicked.

const handleClick = () => {

setCount(count + 1); // Increases the count


by 1

};

return (

<div>

<h1>You clicked the button {count}


times!</h1>

<button onClick={handleClick}>Click
me!</button>
</div>

);

export default Counter;

Explanation (Like teaching a child):

1.​Imagine you have a notebook to keep score while playing a


game.
○​ State is like that notebook—it remembers the score.
2.​In our example:
○​ We have a count (like your score) that starts at 0.
○​ Each time you click the button, we write the new score
(count + 1) in the notebook.
3.​The button has a job:
○​ When you press it, it adds 1 to the score and updates what
you see on the screen.
4.​React does the hard work:
○​ It sees that the score (state) has changed and updates the
screen for you!

What Happens When You Click the Button?

1.​You click the button → React notices.


2.​The state (count) changes → React updates the screen to show
the new number.
3.​You see the updated message: "You clicked the button X times!"

😊
That’s how state works—just like keeping track of something
important in a notebook and showing it when needed!

How State Works in React


1.​React is Declarative
○​ React does not manipulate the DOM directly.
○​ Instead, it re-renders components when data changes.
2.​Re-Rendering
○​ React calls the component function again to update the
view.
○​ This creates a new version of the component.
○​ React keeps the state intact during re-renders (unless the
component is removed).
3.​State Updates Trigger Re-Rendering
○​ State changes (using setState from useState)
automatically re-render the component.
○​ Example: Clicking a button updates state, and React
updates the view.
4.​Example: Advice App
○​ Click button → Fetch new advice → Update state →
React re-renders view.
○​ Example advice: Old view shows "Stay consistent", new
state updates to "Quality beats quantity".
5.​Why is it called React?
○​ React reacts to state changes by updating the user
interface automatically.

Key Takeaway

To update a component's view, update its state. React handles the


rest by re-rendering and keeping the UI in sync with the data.

React State - Key Ideas and Guidelines

1.​State is Isolated in Components


○​ Each component manages its own state.
○​ State changes in one component do not affect others.
○​ Example: Multiple counters on a page operate
independently.
2.​UI as a Function of State
○​ The entire app UI reflects the current state.
○​ React updates the UI automatically based on state
changes.
3.​React Philosophy
○​ UI = State + JSX + Event Handlers.
○​ React simplifies UI by managing how data evolves over
time.
4.​When to Use State
○​ Use state for dynamic data that changes over time.
○​ Examples:
■​ A modal's isOpen state (true = show, false = hide).
■​ Any data that must update in response to user
interaction.
○​ Avoid state for static variables (use const instead).
5.​State Guidelines
○​ Create a new state variable for any dynamic data.
○​ Update state inside event handlers to reflect changes.
○​ Visualize the UI as a reflection of state changes.
○​ Don’t overuse state—only use it when re-rendering is
needed.
6.​Avoid Common Mistakes
○​ Don’t use state for every variable (unnecessary re-renders
= bad performance).
○​ Use state only when it’s essential for dynamic updates.

Key Takeaway

Mastering state makes React development easier. Focus on


understanding when to use state and how it drives the UI.

React State - Key Ideas and Guidelines

1.​State is Isolated in Components


○​ Each component manages its own state.
○​ State changes in one component do not affect others.
○​ Example: Multiple counters on a page operate
independently.
2.​UI as a Function of State
○​ The entire app UI reflects the current state.
○​ React updates the UI automatically based on state
changes.
3.​React Philosophy
○​ UI = State + JSX + Event Handlers.
○​ React simplifies UI by managing how data evolves over
time.
4.​When to Use State
○​ Use state for dynamic data that changes over time.
○​ Examples:
■​ A modal's isOpen state (true = show, false = hide).
■​ Any data that must update in response to user
interaction.
○​ Avoid state for static variables (use const instead).
5.​State Guidelines
○​ Create a new state variable for any dynamic data.
○​ Update state inside event handlers to reflect changes.
○​ Visualize the UI as a reflection of state changes.
○​ Don’t overuse state—only use it when re-rendering is
needed.
6.​Avoid Common Mistakes
○​ Don’t use state for every variable (unnecessary re-renders
= bad performance).
○​ Use state only when it’s essential for dynamic updates.

Key Takeaway

Mastering state makes React development easier. Focus on


understanding when to use state and how it drives the UI.
How State Works in React

1.​React is Declarative
○​ React does not manipulate the DOM directly.
○​ Instead, it re-renders components when data changes.
2.​Re-Rendering
○​ React calls the component function again to update the
view.
○​ This creates a new version of the component.
○​ React keeps the state intact during re-renders (unless the
component is removed).
3.​State Updates Trigger Re-Rendering
○​ State changes (using setState from useState)
automatically re-render the component.
○​ Example: Clicking a button updates state, and React
updates the view.
4.​Example: Advice App
○​ Click button → Fetch new advice → Update state →
React re-renders view.
○​ Example advice: Old view shows "Stay consistent", new
state updates to "Quality beats quantity".
5.​Why is it called React?
○​ React reacts to state changes by updating the user
interface automatically.

Key Takeaway
To update a component's view, update its state. React handles the
rest by re-rendering and keeping the UI in sync with the data.

React State - Key Ideas and Guidelines

1.​State is Isolated in Components


○​ Each component manages its own state.
○​ State changes in one component do not affect others.
○​ Example: Multiple counters on a page operate
independently.
2.​UI as a Function of State
○​ The entire app UI reflects the current state.
○​ React updates the UI automatically based on state
changes.
3.​React Philosophy
○​ UI = State + JSX + Event Handlers.
○​ React simplifies UI by managing how data evolves over
time.
4.​When to Use State
○​ Use state for dynamic data that changes over time.
○​ Examples:
■​ A modal's isOpen state (true = show, false = hide).
■​ Any data that must update in response to user
interaction.
○​ Avoid state for static variables (use const instead).
5.​State Guidelines
○​ Create a new state variable for any dynamic data.
○​ Update state inside event handlers to reflect changes.
○​ Visualize the UI as a reflection of state changes.
○​ Don’t overuse state—only use it when re-rendering is
needed.
6.​Avoid Common Mistakes
○​ Don’t use state for every variable (unnecessary re-renders
= bad performance).
○​ Use state only when it’s essential for dynamic updates.

Key Takeaway

Mastering state makes React development easier. Focus on


understanding when to use state and how it drives the UI.

Difference Between State and Props

1.​State
○​ Internal data owned by the component.
○​ Acts as the component's memory (persists across
re-renders).
○​ Can be updated by the component itself.
○​ Updating state causes a re-render.
○​ Used to make components interactive.
2.​Props
○​ External data passed from parent to child components.
○​ Similar to function parameters.
○​ Read-only: Cannot be modified by the receiving
component.
○​ Re-render occurs if props are updated by the parent.
○​ Used to configure child components (like settings).
3.​Connection Between State and Props
○​ If state is passed as a prop:
■​ Updating the state causes both parent and child
components to re-render.
■​ Ensures the child component stays in sync with the
state.

Key Takeaway

●​ State = Component's internal data (dynamic, interactive).


●​ Props = Parent-to-child communication (read-only, configurable).
●​ Use state for interaction, props for configuration.

React State Management

1.​State in React:
○​ State is the most important concept in React, representing
data that changes during the app's lifecycle.
○​ useState is used to create and manage state in React
components.
2.​What is State Management?
○​ Deciding when to create state, what type of state is
needed, where to place it, and how data flows in the app.
○​ Think of state management as giving each piece of state a
"home" in your code.
3.​Types of State:
○​ Local State: Used in a single component or passed to its
child components (e.g., search bar input).
○​ Global State: Shared across multiple components (e.g.,
shopping cart data). Use tools like React Context API or
Redux for global state.
4.​Key Guideline:
○​ Start with local state and move to global state only if
absolutely necessary.
5.​When to Create State:
○​ Static Data: If the data doesn’t change, use a regular
variable (e.g., const).
○​ Derived State: If new data can be computed from existing
state or props, derive it instead of creating new state.
○​ useRef: Use for data that doesn’t need to trigger
re-renders but persists over time.
○​ New State: Use useState when the data changes and
should re-render the component.
6.​Where to Place State:
○​ Single Component: Place state in the component that
uses it.
○​ Child Component: Pass state via props if needed by a
child component.
○​ Sibling or Parent Components: Move state to the first
common parent (this is called lifting state up).
○​ Global: Use global state if needed by many components
across the app.
7.​Decision Flow Summary:
○​ Is the data static? → Use a variable.
○​ Can it be derived? → Compute it from existing state/props.
○​ Does it need to re-render? → Use useState.
○​ Where is it needed? → Place it locally, lift it up, or make it
global.
8.​Practice and Intuition:
○​ Over time, deciding when and where to create/lift/derive
state becomes intuitive. Use flow charts or guides at the
start to help.
Key Concepts to Remember: Local state, lifting state up, derived
state, global state, Context API, Redux.

Lifting State Up in React


1.​Recap of Form Component:
○​ Form uses two controlled inputs: description and
quantity (state is local to the form).
○​ On form submission, a new item object is created and
logged to the console.
2.​Need for State in App:
○​ Items (packing list) need to be stored and updated as the
app grows.
○​ Use flow chart to decide:
1.​Data will change → Needs state.
2.​Data can't be derived → Create new state.
3.​Data should re-render the UI → Use useState.
3.​Creating Items State:

Define state in App using:​


javascript​

const [items, setItems] = useState([]);

○​

Add a function handleAddItems to update the items array:​


javascript​

const handleAddItems = (newItem) => {
setItems((currentItems) => [...currentItems,
newItem]);
};

○​
4.​Why Move State to Parent Component:
○​ items are needed in the PackingList component (for
rendering).
○​ State can’t flow sideways or upward; move items state to
the common parent (App component).
5.​Passing State and Functions as Props:

Pass items to PackingList as a prop:​


javascript​

<PackingList items={items} />

○​

Pass handleAddItems to Form as a prop:​


javascript​

<Form onAddItems={handleAddItems} />

○​
6.​Lifting State Up:
○​ Definition: Moving state to the closest common parent
component so sibling components can share it.
○​ Steps:
1.​Identify common parent.
2.​Move state to the parent.
3.​Pass state and functions as props to children.
7.​Summary:
○​ Form Component: Creates new items and calls
onAddItems to update the state.
○​ PackingList Component: Renders the items passed
from the parent.
○​ App Component: Holds items state and updates it via
handleAddItems.

Key Concept

●​ React's Unidirectional Data Flow: Data flows down the


component tree via props; sibling components can share data
only if the state is lifted to a common parent.

Lifting State Up & Child-to-Parent Communication

1.​Lifting State Up:


○​ Problem: Two sibling components need the same state,
but React only allows one-way data flow (from parent to
child).
○​ Solution:
■​ Move the state to the closest common parent of
both components.
■​ Pass the state down as props to the child
components.
2.​Example: Checkout Page:
○​ Promotions Component:
■​ Initially held the coupons state (list of applied
coupons).
■​ But Total Component also needs coupons to
calculate discounts.
○​ Fix: Move coupons state to Checkout Component (the
parent of both).
■​ Pass coupons as a prop to Promotions and
Total.
3.​Child-to-Parent Communication:
○​ Problem: After lifting state, the child (e.g., Promotions)
cannot directly update the parent’s state.
○​ Solution:
■​ Pass the parent’s setter function (setCoupons) as a
prop to the child.
■​ The child calls this function to update the parent’s
state.
4.​Key Terms:
○​ One-Way Data Flow: Data flows from parent to child via
props.
○​ Inverse Data Flow: Passing down a setter function lets the
child trigger updates in the parent, simulating "data flowing
up."
5.​Practical Steps:
○​ Lift state to the parent when multiple siblings need it.
○​ Pass state and setter functions as props to children.
○​ Child calls the setter function to update parent state.
6.​Takeaway:
○​ Lifting State enables sharing state across sibling
components.
○​ Child-to-Parent Communication allows updates to parent
state from child components.
○​ Both techniques rely on React's one-way data flow and are
common in React apps.​

Example: Sharing Candy and Keeping Count 🍬
Imagine you and your little sibling are playing a game where you
both share candies from the same bowl. But you need to know
how many candies are left after you each take one.

Problem:

●​ You: "I need to know how many candies are in the bowl!"
●​ Sibling: "Me too! But I also need to tell the bowl when I take
one."
●​ How can both of you share the candy count and update it at the
same time?

Solution:

Let’s pretend the bowl is your parent.

1.​Step 1: Move the Candy Count to the Parent (The Bowl 🍬 )


○​ The bowl (parent) keeps the number of candies.
○​ Whenever you or your sibling need the number of candies,
the bowl tells you.
2.​Step 2: Sharing the Candy Count
○​ The bowl shares the candy count with you and your sibling
so both of you know how many are left.
3.​Step 3: Telling the Bowl About Changes
○​ When you take a candy, you can’t directly change the count
yourself.
○​ Instead, you say:
■​ “Hey, bowl! I took one candy.”
■​ The bowl then updates the count for everyone.
4.​Result:
○​ Both you and your sibling always know the updated
number of candies in the bowl because the bowl (parent)
handles everything.

In React Terms:

●​ The candy count is the "state."


●​ The bowl (parent) keeps the state (e.g., candies).
●​ The setter function is like saying, “Hey, bowl! I took one candy.”
●​ You and your sibling are child components receiving the candy
count (state) as a "prop."

Code Example:
jsx
function Bowl() {
const [candies, setCandies] =
React.useState(10); // Parent keeps count

const takeCandy = () => setCandies(candies -


1); // Child tells parent to update

return (
<div>
<p>Number of candies: {candies}</p> {/*
Share count */}
<Child takeCandy={takeCandy} />
<Sibling takeCandy={takeCandy} />
</div>
);
}

function Child({ takeCandy }) {


return <button onClick={takeCandy}>I take a
candy!</button>;
}

function Sibling({ takeCandy }) {


return <button onClick={takeCandy}>I take a
candy too!</button>;
}

Simple Takeaway:

●​ Parent (bowl) keeps track of candies for everyone.


●​ Children (you and sibling) can tell the parent when they take
one.
●​ Everyone always knows the right candy count because the
parent (bowl) updates it!

🔴 Intermediate 👍

Study Notes: Thinking in React - Components


1.​Key Questions About Components:
○​ How to split a UI into components?
○​ When to create new components?
2.​Component Size:
○​ Avoid huge components: Too many responsibilities, hard to
reuse, complex.
○​ Avoid overly small components: Too abstract, confusing to
navigate.
○​ Aim for a balanced size: Logical separation, clear
responsibilities, manageable complexity.
3.​Guidelines for Splitting Components:
○​ Logical Separation: Split when parts of the code/layout
don’t belong together.
○​ Reusability: Extract reusable parts into new components.
○​ Single Responsibility: Keep components focused on one
task or feature.
○​ Complexity: Break components that are too complex or
depend on too many props.
4.​General Tips:
○​ Each new component creates an abstraction—don’t
overuse it too early.
○​ Name components clearly and descriptively.
○​ Don’t declare components inside other components.
Co-locate related components in the same file.
○​ Apps will naturally have components of varying
sizes—small, medium, and large.
○​ Small components are usually highly reusable; large ones
may not be reusable, and that’s okay.
5.​Practical Approach:
○​ Start with a bigger component, then split it as needed.
○​ Follow best practices, but adapt to your coding style for
productivity.
Key Takeaway: Balance is essential—create logical, reusable, and
manageable components while keeping your coding workflow
productive!

Categories of React Components

React components can be grouped into three main categories


based on their role in the application:

1.​Stateless/Presentational Components:
○​ Definition: Components with no state.
○​ Purpose: Simply receive props and display data or
content.
○​ Examples: Logo, number of results, individual movie
cards.
○​ Characteristics: Often small and reusable.
2.​Stateful Components:
○​ Definition: Components that manage their own state.
○​ Purpose: Handle dynamic data and interactions.
○​ Examples: Search bar with input state.
○​ Characteristics: Can still be reusable despite having state.
3.​Structural Components:
○​ Definition: Components responsible for the structure of the
app.
○​ Purpose: Act as pages, layouts, or screens by composing
smaller components.
○​ Examples: A homepage layout or dashboard screen.
○​ Characteristics: Can be large and non-reusable or small
and reusable.
○​ Common in large apps: Provide structure as apps grow in
complexity.

Key Point:​
These categories emerge naturally—don’t force components into
them. They serve as a helpful way to think about and organize
your code as your app evolves.

Prop Drilling and State Lifting

1.​Problem with Current State Location:


○​ The movies state is in the MovieList component.
○​ But it’s also needed in NumResults.
2.​Solution: Lift State Up:
○​ Move the movies state to the closest shared parent, which
is the App component.
○​ Pass movies down as props to the components that need
it.
3.​What is Prop Drilling?
○​ Passing props through multiple nested components that
don’t need them, just to reach a deeply nested component.
○​ Example: movies prop was passed from App → Main →
ListBox → MovieList.
○​ Intermediate components (Main and ListBox) didn’t need
the data but had to forward it.
4.​Issues with Prop Drilling:
○​ Becomes tedious and hard to manage as the app grows.
○​ Makes code less clean and harder to maintain.
5.​Temporary Fix:
○​ Pass the movies prop to all necessary components.
○​ Use movies.length in NumResults to display the
number of results.
6.​Future Solution:
○​ Learn better alternatives to prop drilling, like component
composition or state management tools (e.g., Context
API).

Key Takeaway: Prop drilling works but is inefficient for deeply


nested components. Solutions like Context API help manage
shared state more effectively.

Prop Drilling Example in React (Explained Simply)

Imagine you have a toy that your little brother wants. But, instead
of giving it directly to him, you pass it to your sister, who passes
it to your cousin, and then finally, it reaches your little brother.
Your sister and cousin don’t even want the toy—they’re just
helping to pass it along. This extra passing around is like prop
drilling.

React Example:

Here’s a simple example:

jsx
function App() {
const message = "Hello from App!"; // The toy
(data)

return <Parent message={message} />; // Pass


the toy to Parent
}

function Parent({ message }) {


return <Child message={message} />; // Pass the
toy to Child
}

function Child({ message }) {


return <GrandChild message={message} />; //
Pass the toy to GrandChild
}

function GrandChild({ message }) {


return <p>{message}</p>; // Finally, use the
toy (show the message)
}

What Happened Here?

1.​App: Has the data (message), but GrandChild needs it.


2.​Parent and Child: Only pass the data—they don’t actually use
it.
3.​GrandChild: Finally shows the data (Hello from App!).

Why is Prop Drilling a Problem?

●​ If there are many layers, passing props becomes messy and


hard to manage.
●​ Imagine 10 people passing a toy—it’s exhausting!
●​ It’s better to find a shortcut, like directly giving the toy to your
brother.

Shortcut (Context API):

The Context API in React can help by letting the GrandChild get
the data directly from App, skipping the middle components.

How React Works (Introduction)

1.​Purpose of This Section:


○​ Learn how React works behind the scenes.
○​ Understand internal React concepts, not just how to use
them.
2.​Why This Is Important:
○​ Makes you a better, more confident React developer.
○​ Helps you ace React interview questions.
○​ Puts you in the top 5% of React developers.
3.​Challenging but Rewarding:
○​ This is an intense section.
○​ Knowledge here is essential before moving further.
4.​If It Feels Overwhelming:
○​ At least watch the summary lecture at the end of this
section.
○​ It will help reinforce everything covered.
5.​Exciting Takeaway:
○​ Understanding React’s internals gives you an edge
professionally.

Ready? Let’s dive into how React really works! 🎉

Components, Instances, and React Elements

1.​Components:
○​ A blueprint or template describing a part of the UI.
○​ Written as a JavaScript function that returns React
elements (using JSX).
2.​Component Instances:
○​ Created whenever a component is used in code.
○​ Each instance:
■​ Has its own state, props, and lifecycle.
■​ Exists as part of the component tree.
3.​React Elements:
○​ The result of calling a component function.
○​ A big immutable object stored in memory.
○​ Contains all the info needed to create DOM elements.
4.​DOM Elements:
○​ The final, visual representation of components on the
browser.
○​ React elements are converted into DOM elements during
rendering.
5.​Key Concept:
○​ Component = Blueprint
○​ Instance = Actual copy with state and props
○​ React Element = Info needed for rendering
○​ DOM Element = Visible output in the browser

🚀
This flow: Component → Instances → React Elements → DOM
Elements helps React create and update the UI efficiently!

How React Renders Behind the Scenes

1.​React Rendering Overview:


○​ Components → Component Instances → React Elements
→ DOM → Screen.
○​ Initial Part: Transforming components into React elements.
○​ Second Part: How React elements become visible on the
screen (focus of this section).
2.​Phases of Rendering:
○​ Render Phase:
■​ React calls component functions.
■​ Figures out what DOM changes are needed.
■​ No DOM updates or visual changes happen here.
○​ Commit Phase:
■​ React updates the DOM (add, update, or delete
elements).
■​ Produces visible changes on the screen.
○​ Repaint Phase:
■​ The browser repaints the screen with updated DOM.
3.​Triggering Renders:
○​ Initial Render: Happens when the app runs for the first
time.
○​ Re-render: Happens when state updates in any
component.
4.​Key Notes:
○​ Rendering involves the entire component tree, not just
the updated component.
○​ React schedules renders for when the JavaScript engine is
free (not immediate).
○​ Multiple state updates in a short time are batched to
optimize performance.
5.​Terminology Clarification:
○​ React’s "rendering" = figuring out changes (no visual
update yet).
○​ DOM updates + screen changes happen in the commit
phase.

🚀
Understanding this process helps us know how React efficiently
manages UI updates!

How React Render Phase Works

1.​Render Phase Overview


○​ React calls component functions to create an updated
virtual DOM (a tree of React elements).
○​ The virtual DOM is fast because it's just a JavaScript
object.
○​ React compares the new virtual DOM with the existing
Fiber tree to find changes.
○​ The result is a list of changes (called effects) to apply to
the actual DOM later.
2.​What is the Virtual DOM?
○​ The virtual DOM is a tree-like structure created from
components.
○​ It’s not the real DOM; it’s just React’s way to figure out what
should change.
3.​What is the Fiber Tree?
○​ The Fiber tree stores information about components, like
state, props, and tasks.
○​ It’s never recreated, just updated to track changes.
4.​Reconciliation Process
○​ React compares the new virtual DOM with the current
Fiber tree (called diffing).
○​ Changes are added to the list of effects (e.g., add,
update, or delete DOM elements).
5.​Why Not Update the Entire DOM?
○​ Updating the DOM is slow, so React updates only the
parts that changed.

Simple Example: React Render Phase

Let’s pretend we’re building a LEGO house.

1.​Virtual House (Virtual DOM)


○​ You draw a new LEGO house design on paper (React
creates a new virtual house).
2.​Compare Designs (Diffing)
○​ You compare the new design to your current LEGO house.
○​ You notice only the door needs to change.
3.​Fiber List (Tracking Changes)
○​ You write down:
■​ Remove the blue door.
■​ Add a red door.
4.​Actual Build (Commit Phase)
○​ Later, you follow your list and update the real LEGO house.

Another Example: Show/Hide a Modal

1.​Initial State
○​ You have a button and a modal (a popup window).
○​ The modal is hidden (showModal = false).
2.​State Update
○​ You click the button, changing showModal to true.
3.​Render Phase
○​ React creates a new virtual DOM:
■​ Adds the modal component.
○​ Compares with the old Fiber tree:
■​ Notices the modal is new and adds it to the effects
list.
4.​Commit Phase
○​ React updates the actual DOM to show the modal on the
screen.

🚀
Think of React as a super-smart LEGO builder who only changes
the blocks that need updating, saving time and energy!
State Update Batching in React
1. What is Batching?

●​ React batches multiple setState calls in the same event


handler into one render.
●​ This improves performance by avoiding unnecessary re-renders.
2. How It Works

●​ React processes all state updates in the event handler together.


●​ Example: Updating 3 state variables in one event handler
triggers only 1 re-render, not 3.
3. Asynchronous State Updates

●​ State updates are not immediate.


●​ Updated state is only available after the re-render.
●​ Accessing state immediately after setState will give the old
(stale) value.
4. Using Previous State
If you need the updated state to calculate the next value, use a
callback in setState:​
javascript​

setState((prevState) => prevState + 1);

●​
5. React 18 and Beyond

●​ Before React 18:


○​ Batching worked only in event handlers.
○​ No batching in timeouts, promises, or native events (e.g.,
addEventListener).
●​ React 18+:
○​ Automatic batching happens everywhere, including
timeouts, promises, and native events.
6. Disabling Batching (Rare Cases)
Use ReactDOM.flushSync to exclude specific updates from
batching:​
javascript​

ReactDOM.flushSync(() => setState(value));

●​
7. Why Batching Matters

●​ Reduces unnecessary renders.


●​ Ensures efficient and consistent UI updates.

React's automatic batching optimizes performance, but


understanding when updates are applied helps avoid confusion
with stale state.

Events in React
1. Event Propagation in the DOM

●​ Events travel in two phases:


1.​Capturing Phase: From the root to the target element.
2.​Bubbling Phase: From the target back up to the root.
●​ Event handlers typically listen during the bubbling phase.
●​ Use event.stopPropagation() to stop an event from
bubbling further (rarely needed).
2. Event Delegation

●​ Instead of adding event handlers to each element, add one to a


parent element and use event.target to handle child events.
●​ Useful for handling events on many elements (e.g., 1000
buttons).
3. How React Handles Events

●​ React registers all event handlers on the root DOM container


(event delegation).
●​ Events bubble up to the root, where React matches and handles
them.
●​ This improves performance by reducing the number of event
listeners.
4. Synthetic Events in React

●​ React uses Synthetic Events, a wrapper around native DOM


events.
●​ They ensure consistency across browsers.
●​ Key methods:
○​ event.stopPropagation()
○​ event.preventDefault()
5. Key Differences: React vs Vanilla JavaScript

●​ Event Prop Names:


○​ React: CamelCase (e.g., onClick).
○​ HTML: Lowercase (e.g., onclick).
●​ Prevent Default Behavior:
○​ React: Use event.preventDefault().
○​ JavaScript: Can use return false.
●​ Capturing Phase: Use onEventCapture in React (e.g.,
onClickCapture).
6. Important Notes

●​ React events work with the DOM tree, not the React component
tree.
●​ Synthetic events like focus, blur, and change bubble in React
(unlike in native DOM).
●​ scroll events do not bubble in React.

React simplifies event handling while optimizing performance and


consistency across browsers. Understanding the basics of event
propagation and delegation helps troubleshoot issues effectively.

React as a Library vs Framework


1. React is a Library, Not a Framework

●​ Library:
○​ Provides specific tools (e.g., React is for building UI
components).
○​ Developers choose additional tools/libraries (e.g., routing,
state management).
○​ Offers freedom but requires decision-making.
●​ Framework:
○​ All-in-one solution (e.g., Angular, Vue).
○​ Includes routing, state management, styling, etc., out of the
box.
○​ Less freedom but faster setup and fewer decisions.
2. React Ecosystem

●​ React has a huge third-party library ecosystem for:


○​ Routing: React Router.
○​ State management: Redux, React Query.
○​ Styling: Tailwind, styled-components.
○​ Forms, animations, UI components, etc.
●​ Picking the right libraries depends on your app's needs.
3. React Frameworks

●​ Examples: Next.js, Remix, Gatsby.


●​ Built on top of React, extending its functionality.
●​ Opinionated: Handle routing, state, styling for you.
●​ Advantages:
○​ Easier and faster development.
○​ Server-side rendering, static site generation.
○​ Suitable for full-stack applications.
4. Key Takeaways

●​ React offers flexibility but requires more decisions.


●​ Frameworks like Next.js simplify setup and improve developer
experience.
●​ Focus on mastering React and its essential libraries before
exploring frameworks.

By learning React, you gain the skills to build apps with either just
React or with frameworks for more advanced use cases.
Key Takeaways from React Section
1. Components and Instances

●​ A component is like a blueprint for a UI.


●​ A component instance is the actual version created with props,
state, and effects.
●​ Component instances return React elements when rendered.
2. Rendering in React

●​ Rendering= Calling component functions and preparing updates


(not updating the DOM).
●​ Commit Phase: Actual DOM updates happen here, handled by
ReactDOM or other renderers (e.g., React Native).
●​ Triggers for Rendering:
○​ Initial render.
○​ State updates.
3. Reconciliation and Diffing

●​ React compares renders to see changes (diffing).


●​ DOM is updated only where necessary (improves performance).
●​ Key Prop:
○​ Keeps elements in the DOM between renders.
○​ Changing keys forces a reset of state.
4. Rules and Best Practices

●​ Never declare a component inside another component.


●​ Render logic (JSX) should not have side effects like API calls or
timers.
●​ Side effects belong in useEffect or event handlers.
5. State and Events

●​ State updates are batched (grouped) for performance.


●​ State updates are asynchronous; you can't access updated
state immediately.
●​ React uses synthetic events for consistent cross-browser
behavior.
6. React is a Library, Not a Framework

●​ React provides flexibility to choose tools (routing, state


management, etc.).
●​ Many libraries to learn, but they allow tailored app development.
●​ Example libraries: React Router, Redux, React Query, etc.

Take time to review and let these key points sink in before moving
to the next section!

Component Lifecycle
1. What is Component Lifecycle?

●​ Lifecycle = Phases a component instance goes through over


time.
●​ Includes: Mounting, Re-rendering, and Unmounting.
2. Lifecycle Phases

1.​ Mounting (Initial Render):


○​ Component is rendered for the first time.
○​ Props and state are created.
○​ Component is "born."
2.​Re-rendering (Optional):
○​ Happens when:
■​ Props change.
■​ Parent component re-renders.
■​ Context changes.
○​ Component updates based on state or props.
3.​Unmounting:
○​ Component is removed from the screen.
○​ State and props are destroyed.
○​ Component "dies."
3. Why is Lifecycle Important?

●​ You can run specific code during each phase using the
useEffect hook.
●​ Useful for tasks like:
○​ Fetching data.
○​ Cleaning up resources.

This sets the stage for understanding and using useEffect


effectively!

Side Effects and useEffect

1. What is a Side Effect?

●​ Interaction between a component and the outside world.


●​ Examples: Fetching data, updating the browser title, or working
with timers.
2. Where to Create Side Effects in React?

1.​ Event Handlers:


○​ Triggered by user actions (e.g., button clicks).
○​ Preferred method for side effects when tied to user events.
2.​Effects (useEffect Hook):
○​ Automatically runs code during specific phases:
■​ When the component mounts (initial render).
■​ When it re-renders (optional, controlled by the
dependency array).
■​ When it unmounts (via cleanup function).
3. Parts of an Effect

●​ Effect Code: Runs during mounting/re-rendering.


●​ Dependency Array: Controls when the effect re-runs.
●​ Cleanup Function: Runs before the component re-renders or
unmounts.
4. Key Comparison: Event Handlers vs. Effects

●​ Event Handlers: React to specific user actions (e.g., button clicks).


●​ Effects: Synchronize the component with external systems (e.g.,
API data).
5. Best Practices

●​ Prefer event handlers for side effects when possible.


●​ Use useEffect for side effects that need to sync with external
systems.
●​ Avoid overusing useEffect unnecessarily.
6. Purpose of Effects

●​ Not just about lifecycle phases (mount, re-render, unmount).


●​ Aim: Synchronize the component with the external world.

This helps build a clear understanding of when and how to use


useEffect effectively!
useEffect Dependency Array
1. Default Behavior

●​ useEffect runs after every render by default.


●​ To control when it runs, we use a dependency array.
2. What is a Dependency Array?

●​ A list of state variables and props that the effect depends on.
●​ React re-executes the effect when any dependency changes.
3. Key Rules

●​ Include all state and props used in the effect in the array.
●​ Missing dependencies cause bugs (e.g., stale closures).
4. Types of Dependency Arrays

1.​ Multiple Dependencies:


○​ Example: [x, y, z]
○​ Runs on the initial render and when x, y, or z changes.
2.​Empty Array ([]):
○​ Runs only on mount (initial render).
○​ Use if the effect doesn't depend on any state/props.
3.​No Array:
○​ Runs on every render (not recommended).
5. Effect Execution Timing

●​ Effects run after the browser paints the screen


(asynchronously).
●​ This prevents blocking the UI rendering.
●​ If an effect updates state, it triggers another render.
6. UseEffect vs LayoutEffect

●​ useEffect: Runs after the browser updates the screen


(default).
●​ useLayoutEffect: Runs before the browser paints. Rarely
needed.
7. Key Takeaways

●​ useEffect is for synchronizing side effects with state/props.


●​ Properly use the dependency array to avoid bugs and control
re-runs.
●​ Avoid overusing effects to keep code efficient.

This knowledge helps manage side effects and the component


lifecycle effectively!

Cleanup Function in useEffect

1. What is a Cleanup Function?

●​ A function returned from an effect to "clean up" after it.


●​ Optional: Only use it when needed.
2. When Does it Run?

1.​ Before the next effect runs (on re-render).


2.​When the component unmounts (cleanup after the component
disappears).
3. Why Use a Cleanup Function?

●​ Prevent bugs like race conditions or unnecessary side effects.


●​ Example scenarios:
○​ Cancel HTTP requests.
○​ Unsubscribe from APIs.
○​ Stop timers.
○​ Remove event listeners.
4. Best Practices

●​ Use cleanup to reset side effects (e.g., revert a page title).


●​ One effect, one purpose: Use multiple useEffect hooks for
clarity.
●​ Clean up long-running processes to keep the app efficient.
5. Key Takeaway

●​ Cleanup functions help manage side effects across the


component lifecycle (mount, re-render, unmount).

Example: Cleaning Up a Timer with useEffect

Imagine we have a timer that counts the seconds a user spends on


a page. When the user leaves the page, we need to stop the
timer so it doesn’t keep running in the background.
Code Example:
javascript
import React, { useState, useEffect } from
"react";

function TimerComponent() {
const [seconds, setSeconds] = useState(0);

useEffect(() => {
// Start the timer
const timer = setInterval(() => {
setSeconds((prev) => prev + 1);
}, 1000);

// Cleanup function: Stop the timer when the


component unmounts
return () => {
clearInterval(timer);
console.log("Timer stopped!");
};
}, []); // Empty array: Effect runs only once
when the component mounts

return <h1>Time on page: {seconds}


seconds</h1>;
}

export default TimerComponent;

Explanation (Simple Terms):

1.​What’s Happening?
○​ When the component loads, we start a timer that adds 1
second every second.
○​ If the user closes the page or goes to another screen, we
don’t want the timer to keep running.
2.​How Do We Stop the Timer?
○​ Inside the useEffect, we return a cleanup function:
clearInterval(timer).
○​ This cleanup tells React, “Hey, stop the timer when the user
leaves this component.”
3.​Why is Cleanup Important?
○​ Without the cleanup, the timer keeps running forever in the
background, wasting memory and causing bugs.
○​ The cleanup makes sure everything is tidy when the
component is no longer needed.
4.​Fun Analogy for a Child:
○​ Imagine you’re playing with a toy (timer).
○​ When it’s bedtime (leaving the component), you put the toy

😊
back in the box (cleanup) so it doesn’t make noise at night!

Listening to Keypress Events with Cleanup in React

1.​What Are We Doing?


○​ We want to close a movie details page by pressing the
Escape key, not just clicking a button.
2.​How Do We Listen for Keypresses?
○​ Use document.addEventListener to listen for
keydown events globally.
3.​Why Do We Need Cleanup?
○​ Without cleanup, multiple event listeners will be added
every time the component re-renders or mounts, causing
bugs like repeated actions or memory issues.
4.​Steps to Implement:
○​ Add the event listener when the component mounts.
○​ Remove the event listener when the component unmounts
or re-renders.
○​ Use a cleanup function inside useEffect to handle this.
5.​Dependency Array:
○​ Include all necessary dependencies (like functions) in the
useEffect array to avoid issues with stale values.

Example: Closing Movie Details with the Escape Key


javascript

import React, { useEffect } from "react";

function MovieDetails({ onCloseMovie }) {


useEffect(() => {
// Define the event listener function
const handleKeyDown = (event) => {
if (event.code === "Escape") {
onCloseMovie();
console.log("Closing movie details...");
}
};

// Add the event listener


document.addEventListener("keydown",
handleKeyDown);

// Cleanup: Remove the event listener when


component unmounts
return () => {
document.removeEventListener("keydown",
handleKeyDown);
console.log("Event listener removed.");
};
}, [onCloseMovie]); // Dependency array
includes the onCloseMovie function

return <div>Movie Details Here</div>;


}

export default MovieDetails;

Explanation (Simple Terms):

1.​What Happens?
○​ When you press the Escape key, the handleKeyDown
function checks if it’s the Escape key.
○​ If yes, it calls onCloseMovie to close the movie details.
2.​Why Cleanup?
○​ Imagine stacking blocks each time you mount the
component. Without cleanup, the blocks pile up endlessly.
Cleanup removes the extra blocks, keeping it neat.
3.​Child-Friendly Analogy:
○​ Adding an event listener is like ringing a doorbell to get
attention.
○​ Cleanup is like unplugging the doorbell when you don’t
need it anymore, so it doesn’t keep ringing by mistake!
Deep Dive into React Hooks

1.​Hooks Overview:
○​ Hooks are easy to start with but take time to master.
○​ A strong understanding is essential for React developers.
2.​What We'll Learn:
○​ Rules of Hooks: Why they exist and how to follow them.
○​ useState: Explore it further for managing state.
○​ useRef: Learn its purpose and usage.
○​ Custom Hooks: Create our own reusable Hooks.
3.​useEffect:
○​ Won't revisit in this section but will explore later.
4.​Goal:
○​ Build a solid foundation in Hooks while finishing the project.

Custom Hooks in React


1.​What are Custom Hooks?
○​ Custom hooks are used to reuse logic in React, especially
logic that uses React hooks.
○​ They allow us to share non-visual, stateful logic across
components.
2.​When to Create a Custom Hook?
○​ If the logic does not use hooks, use a regular function.
○​ If the logic uses hooks, create a custom hook.
3.​How to Create a Custom Hook?
○​ A custom hook is just a JavaScript function.
○​ It must start with the word "use" (e.g., useFetch).
○​ It can take arguments and return data (e.g., objects or
arrays).
4.​Purpose of Custom Hooks:
○​ They should solve one specific problem.
○​ Make them reusable and portable (usable in different
projects).
5.​Rules of Hooks Apply:
○​ Follow the same rules as built-in hooks (e.g., call hooks at
the top level, only in React functions).
6.​Key Points:
○​ Custom hooks are for logic reusability, not UI (use
components for UI reusability).
○​ There are many shared custom hook libraries available on
NPM.

Example:

A useFetch custom hook to fetch data:

javascript
import { useState, useEffect } from "react";

function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);

useEffect(() => {
async function fetchData() {
const response = await fetch(url);
const result = await response.json();
setData(result);
setLoading(false);
}
fetchData();
}, [url]);

return { data, loading };


}

export default useFetch;

Usage:

javascript
function App() {
const { data, loading } =
useFetch("https://api.example.com/data");

if (loading) return <p>Loading...</p>;


return <div>{JSON.stringify(data)}</div>;
}

🔴 Advanced.
useRef Hook
1.​ What is useRef?
○​ Creates a ref (reference), a mutable object with a current property.
○​ The current property can hold any value and persists across renders.
2.​ Use Cases for useRef
○​ Store variables that stay the same between renders (e.g., previous state,
setTimeout IDs).
○​ Select and store DOM elements.
3.​ Key Characteristics
○​ Refs do not cause re-renders when updated.
○​ Usually used for data not part of the visual output (e.g., in event handlers or
effects).
○​ Refs are mutable, unlike state, which is immutable.
4.​ State vs. Ref
○​ State: Causes re-renders when updated.
○​ Ref: Does not trigger re-renders; only remembers data.
○​ State updates are asynchronous, while ref updates are immediate.
5.​ When to Use useRef
○​ Use state for data that should re-render the UI.
○​ Use ref for data to persist between renders but not re-render the UI.
6.​ Best Practices
○​ Avoid using refs in render logic to prevent side effects.
○​ Perform ref mutations inside useEffect or event handlers.

Example: Using useRef to Store a Timer ID

Imagine you’re playing a game, and you press a button to start a timer. You want to
remember the timer so you can stop it later. This is where we use useRef because it
can "hold" the timer for us without affecting the game screen (UI).

Code Example:
javascript

import React, { useRef } from 'react';

function Timer() {
const timerRef = useRef(null); // Create a box to hold the timer
ID

const startTimer = () => {


timerRef.current = setInterval(() => {
console.log("Timer running...");
}, 1000); // Save the timer ID in the box
console.log("Timer started:", timerRef.current);
};

const stopTimer = () => {


clearInterval(timerRef.current); // Use the box to stop the
timer
console.log("Timer stopped:", timerRef.current);
};

return (
<div>
<button onClick={startTimer}>Start Timer</button>
<button onClick={stopTimer}>Stop Timer</button>
</div>
);
}

export default Timer;

Explanation (Like Teaching a Child):

1.​ What is useRef?​


Think of useRef as a magic box where you can put something and it stays there even if
you move things around in the room (re-render).
2.​ What Happens Here?
○​ When you press "Start Timer," we put the timer ID (a special number) into our
box (timerRef.current).
○​ When you press "Stop Timer," we take that number from the box and use it to
stop the timer.
3.​ Why Use useRef?
○​ The timer ID doesn’t need to re-paint the game screen (it’s hidden work).
○​ We just need to remember it for later, and useRef is great at holding on to things
quietly.

😊
It’s like keeping your game tools in a drawer—they don’t need to be on the table all the time,
but you know where to find them when you need them!

Class-Based React (Optional)


1.​ What Are Class Components?
○​ Older way of writing React components using classes instead of functions.
○​ Relied on lifecycle methods (special functions for managing component
behavior).
2.​ Why Learn Them?
○​ Rarely Used Now: Hooks and functional components have replaced them.
○​ Still Useful: You might see them in older codebases or need to convert them into
function components.
3.​ Key Points:
○​ Not necessary for most modern projects.
○​ Only dive into this if you're curious or need to work with older React code.
4.​ Advice:
○​ Skip this section if it feels overwhelming or unnecessary for now.

😊
○​ Come back later if your job requires understanding class components.
It’s a look into React’s past but not a priority for learning modern React!

Function Components vs. Class Components


1.​ Function Components
○​ Modern approach introduced in 2019 with hooks (e.g., useState,
useEffect).
○​ Easier to write and read with less boilerplate code.
○​ Use hooks for state and side effects.
○​ No need for the this keyword.
○​ Cleaner code with lifecycle-related logic in one place (via hooks).
○​ Use regular functions or arrow functions to handle events.
2.​ Class Components
○​ Older approach (2015) using ES6 classes and lifecycle methods.
○​ Requires extending React.Component.
○​ Uses the this keyword for props and state.
○​ Handles side effects with multiple lifecycle methods (e.g.,
componentDidMount).
○​ Needs a render() method to return JSX.
○​ Event handlers must be class methods.
3.​ Key Differences
○​ State Management:
■​ Function components use useState.
■​ Class components use this.state.
○​ Side Effects:
■​ Function components use useEffect.
■​ Class components use lifecycle methods.
○​ Code Simplicity:
■​ Function components are easier and cleaner to write.
■​ Class components can feel more structured to understand lifecycle
stages.
4.​ Advantages of Function Components
○​ Less code, no this keyword.
○​ Easier state-sharing with custom hooks.
○​ Unified logic for side effects.
5.​ Advantages of Class Components
○​ Lifecycle methods have clear names (e.g., componentDidMount).
○​ May feel easier for beginners to grasp lifecycle stages.

Conclusion: Function components are the future of React, but class components are still
important for understanding older codebases!

Key Lifecycle Methods in Class Components


1.​ Lifecycle Methods Overview
○​ Used for side effects during mounting, updating, and unmounting of
components.
○​ Similar to useEffect in function components.

2. Key Lifecycle Methods


1.​ componentDidMount (On Mount)
○​ Runs once after the component renders for the first time.
○​ Ideal for fetching data or reading from local storage.
○​ Similar to useEffect([]).
2.​ componentDidUpdate (On Update)
○​ Runs after every re-render.
○​ Gets previous props and previous state as arguments.
○​ Ideal for responding to state/prop changes, like fetching updated data.
○​ Similar to useEffect([dependency]).
3.​ componentWillUnmount (On Unmount)
○​ Runs just before the component is removed.
○​ Ideal for cleanup tasks (e.g., clearing timers, canceling API calls).
○​ Similar to the cleanup function in useEffect.

3. Features Built Using Lifecycle Methods

1.​ Search While Typing


○​ componentDidUpdate: Checks if the location state changes and fetches new
weather data.
2.​ Remember Location
○​ Save: componentDidUpdate stores the location in local storage whenever it
changes.
○​ Retrieve: componentDidMount retrieves the saved location from local storage
on reload.

4. Important Notes

●​ Class-based lifecycle methods can spread logic across multiple methods, making
them harder to maintain compared to hooks.
●​ Lifecycle methods are useful for understanding and working with older codebases.

5. Practice Suggestion

●​ Convert the example app from class components to function components using hooks
(useEffect, useState).
●​ Share your implementation to improve understanding.
Imagine you have a toy car.​
Sometimes you want to:

1.​ Start the car (when you first get it).


2.​ Change something about it (like adding stickers or switching the wheels).
3.​ Turn it off and put it away.

In React, class components are like that toy car: they need special steps to handle these
things. We use lifecycle methods to know what’s happening and what to do.

Example: A Weather App


Let’s say we have a weather app that shows the weather for your city.

componentDidMount – Starting the Car

○​ This runs when the app loads for the first time.
○​ It’s like opening your toy box and picking the car to play with.
○​ Example: We can fetch weather data when the app starts.

js​
Copy code​
componentDidMount() {
fetchWeather(); // Get the weather when the app loads.
}

componentDidUpdate – Adding Stickers

○​ This runs whenever you change something in the app, like typing a new city
name.
○​ It’s like adding stickers to your toy car to make it look cooler.
○​ Example: Fetch new weather data when the city name changes.

js​
Copy code​
componentDidUpdate(prevProps, prevState) {
if (prevState.city !== this.state.city) {
fetchWeather(); // Fetch weather only if the city changed.
}
}

componentWillUnmount – Putting the Car Away

○​ This runs when you close the app or stop using something.
○​ It’s like turning off your toy car and putting it back in the toy box.
○​ Example: Clean up timers or stop any leftover tasks.

js​

componentWillUnmount() {
clearTimer(); // Clean up anything we don’t need.
}

Why It’s Useful

Lifecycle methods help us know:

●​ When to start something (like loading data).


●​ When to update something (like getting new info).
●​ When to clean up (so nothing is left running when we’re done).

Isn’t that just like playing with a toy? 😊

Advanced React (Part 3)


What's Coming:

1.​ Advanced State Management


○​ useReducer Hook: Manage complex state.
○​ Context API: Share data between components without props.
○​ Redux: Advanced state management tool.
2.​ Real-World Project
○​ Build a Single Page Application (SPA).
○​ Use Vite (fast setup tool) and React Router (for navigation).
3.​ Performance Optimization
○​ useMemo: Prevent unnecessary calculations.
○​ useCallback: Avoid re-creating functions.

Key Takeaway:

🚀
You’ll learn state management and performance optimization by working on exciting
projects.

useState vs. useReducer


When to Use useState

●​ Ideal for simple, independent state (e.g., numbers, strings, arrays, or basic objects).
●​ State updates happen directly via setState.
●​ Updates feel imperative, making it easier to understand and use.
●​ Best for components with fewer pieces of state.

When to Use useReducer

●​ Best for complex or interdependent state (e.g., multiple related states).


●​ Centralizes state update logic in a reducer function.
●​ Updates are triggered by dispatching actions (more declarative).
●​ Useful when:
○​ States are frequently updated together.
○​ The component has complex state logic or too many event handlers.
○​ Willing to invest time in writing a reducer.

How to Choose

1.​ Simple State​


→ Use useState.
2.​ Multiple States
○​ Do states frequently update together?
■​ Yes → Consider useReducer.
■​ No → Check:
■​ Do you have 3+ related states or objects?
■​ Yes → Consider useReducer.
■​ No → Use useState.
3.​ Event Handler Overload​
→ Use useReducer if too many handlers make the component confusing.

Key Takeaways

●​ Default to useState unless you encounter complex or interrelated state.


●​ useReducer is more powerful but slightly harder to implement.
●​ Use useReducer when you need centralized state logic and cleaner components.

Keep practicing with useReducer to master it!

Introduction to React Router


What is React Router?

●​ A popular library used in almost all React projects.


●​ Allows building apps with multiple pages that feel smooth like smartphone apps.
●​ Enables creating Single Page Applications (SPAs).

What Will We Learn?

1.​ How to use React Router for navigation.


2.​ Hands-on experience building a SPA called Worldwide.
3.​ Learn a new styling method called CSS Modules.

Key Takeaways

●​ React Router makes SPAs fluid and user-friendly.


●​ CSS Modules help style React apps effectively.
●​ Get ready to dive into a real-world project and learn by doing!

Styling in React Applications


Why Many Styling Options?

●​ React is unopinionated about styling, leading to various methods.


●​ Multiple third-party libraries provide styling solutions.

Styling Options in React

1.​ Inline Styles


○​ Applied via the style prop.
○​ Locally scoped to the specific JSX element.
○​ Common in React due to separation of concerns.
2.​ Global CSS (External CSS File)
○​ Styles applied using className prop.
○​ Shared across all components.
○​ Issues: Hard to manage in large apps (class clashes, unintended effects).
3.​ CSS Modules (Used in This Project)
○​ Write one CSS file per component.
○​ Styles are scoped to the specific component.
○​ Reflects React's modular design philosophy.
4.​ CSS-in-JS (e.g., styled-components)
○​ Write CSS inside JavaScript files.
○​ Styles are tied directly to React components.
○​ Emphasizes component encapsulation.
5.​ Utility-First CSS Frameworks (e.g., Tailwind)
○​ Use predefined utility classes for styling.
○​ Design directly in JSX without writing separate CSS.
6.​ UI Component Libraries (e.g., Material UI, Chakra UI)
○​ Prebuilt, pre-styled components for common UI needs.
○​ No CSS writing required.
○​ Suitable for rapid development but not ideal for beginners.

Key Takeaways

●​ Avoid global CSS in large apps to prevent style clashes.


●​ CSS Modules provide scoped styles, ensuring modularity and reusability.
●​ Explore other methods like CSS-in-JS or Tailwind as needed.
●​ UI libraries can simplify projects but might limit customization.

Storing State in the URL with React Router


Why Store State in the URL?
1.​ Global Accessibility:
○​ State in the URL can be accessed by any component without passing props.
2.​ Page Navigation:
○​ Easily pass data between pages without temporary app storage.
3.​ Bookmark & Share:
○​ Share or bookmark a page with exact UI state (e.g., filters or settings).

Examples of UI State for the URL

●​ Open/closed panels.
●​ Filters and sorting orders.
●​ Specific page data (e.g., city details).

Parts of the URL for State

1.​ Path Parameters (Params):


○​ Pass data to the next page (e.g., app/cities/Lisbon loads the Lisbon page).
○​ Different params load different data (e.g., Berlin shows Berlin page).
2.​ Query Strings:
○​ Store global state accessible across the app (e.g., ?lat=40&lng=-3 for map
position).

Benefits of Params and Query Strings

●​ Params:
○​ Send data directly via the URL for page-specific content.
○​ Example: /cities/Lisbon → Displays Lisbon details.
●​ Query Strings:
○​ Store additional state (e.g., map coordinates).
○​ Example: /cities/Lisbon?lat=40&lng=-3.

Key Takeaways

●​ Use the URL to reduce dependency on React state.


●​ Great for sharing, bookmarking, and simplifying state management.
●​ Practice makes it easier to implement effectively.

React Context API


What is the Context API?

●​ A system to pass data through the component tree without prop drilling.
●​ Allows components to share global state directly without passing props.

Why Use the Context API?

●​ Solves the prop drilling problem, where passing props through multiple levels
becomes cumbersome.
●​ Makes state accessible to deeply nested components directly.

Key Parts of Context API

1.​ Provider:
○​ Shares a value (data) with all child components.
○​ Usually placed at the top of the component tree.
○​ value can include state variables and functions.
2.​ Consumer:
○​ Components that read the value from the context.
○​ Can be many consumers for a single provider.

How It Works

●​ Value Updates:​
When the provider's value changes, all consumers using that context re-render
automatically.
●​ Re-rendering Rule:​
Context updates cause subscribed components to re-render, similar to how state
updates work.

Benefits

●​ No need to pass props down multiple levels.


●​ Flexible and supports multiple contexts in a single app.
●​ Simplifies state sharing across components.

Key Takeaway

The Context API is a powerful tool for managing state in a React app, especially for avoiding
prop drilling and making global state easily accessible.

Simple Example of Context API: Sharing a Favorite Color


Imagine we have a family, and the parent wants to share their favorite color with the children,
but without telling it to each child one by one. Instead, the parent writes the favorite color on a
board that all children can look at anytime.

In React, the parent is like the Provider, the board is the Context, and the children are
Consumers.

Code Example:

We’ll create an app where the favorite color is shared with child components.

jsx

import React, { createContext, useState, useContext } from 'react';

// 1. Create the Context (the board)


const ColorContext = createContext();

function Parent() {
// 2. The parent's favorite color (state)
const [favoriteColor, setFavoriteColor] = useState("Blue");

return (
// 3. Provide the favorite color to all children
<ColorContext.Provider value={favoriteColor}>
<h1>Parent's Favorite Color: {favoriteColor}</h1>
<Child />
<OtherChild />
</ColorContext.Provider>
);
}

function Child() {
// 4. Use the favorite color (read from the board)
const color = useContext(ColorContext);

return <h2>Child says: Parent's favorite color is {color}!</h2>;


}
function OtherChild() {
// 5. Another child using the same favorite color
const color = useContext(ColorContext);

return <h2>Other Child: I also know the favorite color is


{color}!</h2>;
}

export default Parent;

Explanation (Like Teaching a Child):

1.​ Create a Board (Context):​


The ColorContext is a special tool where we write the favorite color so everyone can
see it.
2.​ Parent Shares Color:​
The ColorContext.Provider is like the parent writing "Blue" on the board.
3.​ Children Look at the Board:​
The useContext(ColorContext) is like the children looking at the board to know the
color.

Output:

Parent's Favorite Color: Blue


Child says: Parent's favorite color is Blue!
Other Child: I also know the favorite color is Blue!

🎨
This way, the parent shares their favorite color with all children without telling them directly.

State Management Overview


1.​ State Types
○​ Local State: Needed by one or a few components.
○​ Global State: Needed by many components across the app.
○​ UI State: Controls the app's interface (e.g., open panels, filters).
○​ Remote State: Data fetched from a server (e.g., API data).
2.​ Deciding Local vs. Global State
○​ Trick: Ask, "If this component was duplicated, should the state update in both
copies?"
■​ No: Local state.
■​ Yes: Global state.
3.​ State Tools and Locations
○​ Local State: Use useState, useReducer, or useRef.
○​ Lift State: Move state to a parent component if needed by related components.
○​ Global State: Use Context API or state management libraries.
○​ URL: Store shareable or bookmarkable global state (e.g., filters).
○​ Browser Storage: Use local storage or session storage for persistent data.
4.​ State Management Tools
○​ Local UI State: Use useState or useReducer.
○​ Local Remote State: Fetch API data in useEffect and manage with
useState.
○​ Global Remote State: Use libraries like React Query, SWR, or Redux for better
performance.
○​ Global UI State: Use Context API with useState/useReducer or libraries like
Redux.
5.​ State Tools Overview
○​ Use simpler tools like useState for small apps.
○​ Use specialized tools like React Query for remote data in larger apps.
○​ Context API is great for UI state; consider libraries for large-scale apps.

Tip: Understand state needs (local/global, UI/remote) to choose the right tool. Use the Context
API for UI state, and libraries for complex global or remote state.

Optimizing React Performance


1.​ Section Focus
○​ Learn about renders in React.
○​ Understand and fix wasted renders.
○​ Use advanced React tools to boost performance.
○​ Go deeper into useEffect and its behavior.
2.​ Goals
○​ Make React apps faster and smoother.
○​ Understand how React works internally for better optimizations.
3.​ Key Concepts to Explore
○​ Identifying unnecessary renders.
○​ Optimizing performance with tools and techniques.
○​ Advanced useEffect practices.

Tip: Pay attention to how components re-render and the role of dependencies in useEffect.
This section is about making React apps both efficient and professional

Memoization and React's memo ➖


1.​ What is Memoization?
○​ Memoization stores the result of a function in a cache.
○​ If called with the same inputs, it returns the cached result without re-executing
the function.
○​ For different inputs, the function executes normally.
2.​ Memoization in React
○​ Optimizes components by avoiding unnecessary re-renders.
○​ Tools: memo (for components), useMemo, and useCallback (for objects and
functions).
3.​ React's memo Function
○​ Prevents a component from re-rendering when the props are unchanged.
○​ Without memo, child components re-render whenever the parent re-renders.
○​ With memo, child components only re-render if props change.
4.​ Important Notes
○​ Does not prevent re-renders caused by:
■​ Changes in the component's own state.
■​ Changes in the context the component subscribes to.
○​ Only useful for:
■​ Heavy components that are slow to render.
■​ Components that re-render frequently with the same props.
5.​ When Not to Use memo
○​ If props often change.
○​ For lightweight or infrequently rendered components.

Takeaway: Use memo selectively to optimize performance by reducing unnecessary renders for
slow, frequently re-rendered components with stable props.
useMemo and useCallback ➖
1.​ Issue with Memoized Components
○​ Functions and objects are recreated on every render.
○​ Even if they look identical, they are treated as new props.
○​ This causes memo to fail as it sees the props as "changed."
2.​ Solution: Stabilize Props
○​ Use useMemo to memoize values (e.g., objects).
○​ Use useCallback to memoize functions.
3.​ How useMemo and useCallback Work
○​ Both return cached values if dependencies stay the same.
○​ If dependencies change, the value or function is recreated.
○​ Dependencies are passed in an array, similar to useEffect.
4.​ Main Use Cases
○​ Stabilize objects or functions passed as props to prevent wasted renders.
○​ Avoid expensive recalculations by caching results of computations.
○​ Prevent infinite loops in hooks like useEffect by memoizing dependencies.
5.​ When Not to Use
○​ Avoid overusing these hooks.
○​ Use them only for performance-critical scenarios.

Key Idea: Memoization with useMemo and useCallback improves performance by stabilizing
values or functions across renders and reducing unnecessary calculations.

useEffect Rules and Guidelines


1. Dependency Array Rules

●​ Include All Reactive Values:


○​ Add all state, props, context values, or any value derived from these to the
dependency array.
○​ This avoids stale closures.
●​ Don't Use Objects/Arrays Directly:
○​ Objects/arrays are re-created on every render and will cause unnecessary
re-runs.

2. Fixing Dependency Issues


●​ For Functions:
○​ Move the function inside the effect if only used there.
○​ Use useCallback to memoize functions used in multiple places.
○​ Move non-reactive functions outside the component.
●​ For Objects:
○​ Include only the required properties if they are primitives.
○​ Use similar strategies as for functions.
●​ Use useReducer:
○​ Simplifies dependency handling when related values are involved.

3. React Guarantees

●​ No need to include setState or dispatch functions in the dependency array—they


are stable.

4. When to Avoid useEffect

●​ User Events:
○​ Handle clicks/keystrokes with event handlers, not effects.
●​ Data Fetching:
○​ For larger apps, use libraries like React Query instead of useEffect.
●​ Synchronizing State:
○​ Avoid setting state based on other states inside effects. Use derived state or
event handlers instead.

5. General Advice

●​ useEffect is an escape hatch and should be used sparingly.


●​ Overusing effects can lead to performance issues and unnecessary re-renders.
●​ Always consider simpler alternatives before using useEffect.

Introduction to Redux
1. What is Redux?

●​ Redux is a state management library for handling complex application state.


●​ Learning it will be easier if you understand the useReducer Hook.

2. Learning Steps

●​ Start Simple: Learn Redux fundamentals in isolation.


●​ Integration: Add Redux to a small app.
●​ Modern Approach: Use the Redux Toolkit for simplified code.
●​ API Requests: Use Thunks to handle API calls in Redux.

3. Why Redux?

●​ Helps manage state in large, complex apps.


●​ Makes the app more scalable and maintainable.

Redux can seem tough but is straightforward and fun to learn with the right approach! 🎉

Understanding Redux
1. What is Redux?

●​ A library to manage global state in web apps.


●​ Can work with any framework, often used with React via react-redux.
●​ Stores all global state in a centralized store.

2. How Redux Works

1.​ Action: A plain object with a type and optional payload.


2.​ Dispatch: Sends the action to the store.
3.​ Reducer: A pure function in the store calculates the new state based on the action.
4.​ Store: Central container holding the global state.
5.​ Re-render: React components using updated state automatically re-render.

3. Comparison with useReducer

●​ Redux is like useReducer but centralized and global.


●​ Think of Redux as useReducer + Context API.

4. Advanced Features

●​ Use action creators to automate creating action objects.


●​ Multiple reducers for different app features or data domains.

5. When to Use Redux

●​ Ideal for apps with frequent updates to large global UI state.


●​ Less relevant for managing remote data, for which tools like React Query are better.
6. Redux Toolkit

●​ A modern, simplified way to use Redux.


●​ Learn classic Redux first for a strong foundation.

7. Redux Cycle

1.​ Action Creator generates an action.


2.​ Dispatch sends it to the store.
3.​ Reducer processes the action and updates state.
4.​ Store holds the updated state.
5.​ Components consuming the state re-render.

Bank Analogy:

●​ You (action creator) give instructions (action) to the bank teller (dispatcher).
●​ The teller updates the vault (store), not you directly.

🚀
Redux simplifies state logic by separating it from the rest of the app. With practice, it becomes
clear and manageable!
Redux Middleware
1. What is Middleware?

●​ Middleware is a function in Redux that sits between dispatching an action and the
reducer.
●​ It allows running custom logic (like API calls) before the action reaches the reducer.

2. Why Middleware?

●​ Reducers must be pure functions (no side effects).


●​ To avoid putting asynchronous logic (e.g., API calls) in components or reducers.
●​ Keeps components clean and data-fetching logic centralized.

3. Uses of Middleware

●​ Perform asynchronous actions (e.g., API calls).


●​ Logging, timers, pausing, or canceling actions.
●​ Handle side effects in the Redux cycle.

4. Thunk Middleware

●​ Redux Thunk: A popular middleware for handling asynchronous actions.


●​ Lets you delay dispatching an action until some async operation (e.g., API call) is
complete.

5. How Thunk Works

1.​ Dispatch an action.


2.​ Action goes to the Thunk Middleware instead of directly to the reducer.
3.​ Perform async operation (e.g., fetch data).
4.​ Once data arrives, dispatch the updated action to the store.
5.​ Reducer updates the state with the fetched data.

6. Key Benefits

●​ Centralized async logic.


●​ Keeps Redux reducers pure and components clean.
●​ Enables deferring dispatch until required data is ready.

Middleware is essential for handling side effects and enhancing Redux functionality! 🚀
Redux Dev Tools
1. What are Redux Dev Tools?

●​ A tool to debug and inspect Redux state and actions.


●​ Helps track state changes and find bugs.

2. Setup Steps

1.​ Install the Redux DevTools Chrome Extension.

Install the NPM package:​


bash​

npm install redux-devtools-extension

2.​ Import and use composeWithDevTools to wrap applyMiddleware in your Redux


store setup.

3. Features

●​ Inspect Actions: View dispatched actions, their type, and payload.


●​ Track State Changes: See how the state changes after each action.
●​ Time Travel: Jump between different state transitions to debug issues.
●​ Slider: Move through state transitions smoothly to see updates step by step.
●​ Manual Dispatch: Dispatch actions manually to test functionality.

4. Finding Bugs

●​ Helps identify issues by inspecting actions and their effects on state.


●​ Example: Debugged a bug caused by resetting a value to an empty string instead of the
initial state.

5. Use Cases

●​ Debugging complex state transitions.


●​ Manually testing Redux actions without modifying the UI.
●​ Visual
Redux Toolkit
1. What is Redux Toolkit?

●​ Modern way of writing Redux code.


●​ Recommended by the Redux team.
●​ Built on top of classic Redux, fully compatible.

2. Why Use Redux Toolkit?

●​ Less Boilerplate: Reduces setup code.


●​ Focus on Logic: Automatically sets up middleware, dev tools, and action creators.
●​ Simplified Reducers:
○​ Allows "mutating" state in reducers using Immer.
○​ Simplifies working with complex state objects.

3. Key Features

1.​ Immer:
○​ Lets you write reducers as if mutating state directly.
○​ Handles nested objects and arrays more easily.
2.​ Automatic Action Creators:
○​ Creates action creators based on reducers.
3.​ Built-in Middleware Setup:
○​ Automatically configures Thunk middleware.
○​ Dev tools are pre-configured.

4. Compatibility

●​ Classic Redux and Redux Toolkit can coexist in the same app.

5. Biggest Advantage

●​ Simplifies Complex Code: Makes Redux easier and faster to implement for real-world
projects.
Redux vs. Context API
Context API + useReducer

Advantages:

●​ Built into React; no extra packages or bundle size increase.


●​ Simple for single state slices.
●​ Good for infrequent updates (e.g., themes, user preferences).

Disadvantages:

●​ Repeating setup for multiple state slices can cause "provider hell."
●​ No built-in async handling (needs custom solutions).
●​ Performance optimization requires extra effort.
●​ Limited DevTools (basic React developer tools).

Redux

Advantages:

●​ Easier to add new state slices after setup.


●​ Built-in middleware supports async operations.
●​ Optimized performance with minimized re-renders.
●​ Excellent DevTools for debugging complex state.

Disadvantages:

●​ Requires additional packages (increases bundle size).


●​ Initial setup is more complex.

Recommendations

1.​ Use Context API for:


○​ Simple, rarely changing global state (e.g., themes, language, authenticated user).
○​ Solving prop drilling or managing state in small app sub-trees.
2.​ Use Redux for:
○​ Large apps with frequent state updates (e.g., shopping carts, filters).
○​ Complex or nested state structures.

Key Takeaway

Choose the right tool based on your project's needs, not trends. Context is great for small-scale
state needs, while Redux shines in large-scale, complex apps.
Part 4 - Professional React Development {2-Project}
Focus of Part 4

●​ Transition from learning React basics to building professional web applications.


●​ Combine React with its library ecosystem for real-world projects.

Tools Used

●​ React Query
●​ Supabase
●​ Tailwind CSS

Features in Projects

●​ Authentication.
●​ Data filtering and pagination.
●​ Beautiful charts.
●​ Dark mode and context menus.
●​ Modals and more.

Outcome

●​ Gain skills to build high-quality, real-world applications independently.


●​ Apply advanced React tools and features in practical projects.

First Project of Part 4

Focus

●​ Build a pizza ordering app using React Router.


●​ Use React Router's modern data loading capabilities.

Key Learning Points

●​ Learn to plan a professional React project step by step.


●​ Transition to more serious, professional app development.

Outcome

●​ Gain practical experience in structuring and building real-world React applications.


Planning a Professional React App
Project Overview

●​ Client: Fast React Pizza Company.


●​ Goal: Build a front-end for ordering pizzas (back-end API is already done).
●​ Features:
○​ Order multiple pizzas from a menu.
○​ No user accounts (just name, phone, address).
○​ Optional GPS location for delivery.
○​ Priority orders (+20% cost).
○​ Payment on delivery only.
○​ Users can track orders via unique ID.

Planning Steps

1.​ Requirements:
○​ Simple app for pizza ordering.
○​ Features include menu display, cart, order placement, and tracking.
2.​ Feature Categories:
○​ User: Input name for app access.
○​ Menu: Load and display pizzas from API.
○​ Cart: Add/update pizzas for order.
○​ Order: Place and track orders.
3.​ Pages:
○​ Home: Input user name.
○​ Menu: Display pizzas.
○​ Cart: Manage selected items.
○​ New Order: Place orders.
○​ Order Lookup: Check order status with ID.
4.​ State Management:
○​ User & Cart: Global UI state (local in app).
○​ Menu & Order: Global remote state (from API).

Tech Stack

●​ Routing: React Router.


●​ Styling: Tailwind CSS.
●​ State Management:
○​ Remote State: React Router data fetching.
○​ UI State: Redux for complex state handling.
Key Focus

●​ Apply professional planning steps.


●​ Explore modern React tools like React Router's data fetching.
●​ Practice Redux in real-world scenarios.

Tailwind CSS Introduction(Crash Course) ➖(Link) Tailwind css docs


1. What is Tailwind CSS?

●​ A utility-first CSS framework.


●​ Allows you to style components directly in HTML or JSX.
●​ Very popular, especially with React.

2. Why Use Tailwind CSS?

●​ Customization: High flexibility to design unique styles.


●​ Speed: Helps quickly build UIs without writing custom CSS.
●​ Popular Choice: Widely used in modern web development.

3. Setup

●​ Tailwind will be set up from scratch in this section.

4. Skipping

●​ If not interested, you can skip this section and continue with the project.

5. Next Steps

●​ After learning Tailwind basics, you will use it to style the components in your app.

Tailwind CSS Overview


What is Tailwind CSS?

●​ A utility-first CSS framework.


●​ Packed with pre-built classes (e.g., flex, text-center, rotate-90).
●​ Styles are written directly in HTML or JSX.
Utility-First CSS Approach

●​ Focuses on small, single-purpose classes.


●​ Classes are combined to create components and layouts.
●​ Removes the need to write custom CSS.

Pros of Tailwind CSS

1.​ No Class Naming


○​ No need to think of unique class names.
2.​ All-in-One Place
○​ Write HTML and styles together.
○​ No switching between files.
3.​ Readability
○​ Easy to understand and revisit project styles.
4.​ Design System
○​ Predefined colors, fonts, and spacing ensure consistency.
5.​ Time-Saving
○​ Quick responsive design and less CSS writing.
6.​ Great Documentation
○​ Excellent guides and VS Code integration for auto-completion.

Cons of Tailwind CSS

1.​ Cluttered Markup


○​ HTML/JSX can look messy with too many classes.
2.​ Learning Curve
○​ Requires memorizing Tailwind class names.
3.​ Setup Time
○​ Initial setup takes 5-10 minutes per project.
4.​ Vanilla CSS Transition
○​ Feels like moving away from traditional CSS, though Tailwind stays close to it.

Conclusion

●​ Tailwind is a controversial but powerful tool.


●​ Benefits often outweigh the cons.
●​ Try it yourself to decide if it suits your workflow.

Next Steps

●​ Style your project entirely with Tailwind CSS in the upcoming lessons.

●​ Why Use Tailwind?


○​ Speeds up development.
○​ Customizable design system.
○​ No need to write separate CSS files for most cases.

Beginner Topics

1. Setup and Configuration

●​ Install Tailwind CSS via npm, Yarn, or CDN.


●​ Configure using the tailwind.config.js file.

Add it to your CSS file:​


Css
@tailwind base;
@tailwind components;
@tailwind utilities;

●​
●​ Use PostCSS or frameworks like Next.js for integration.

2. Utility Classes Basics

●​ Spacing: p-4, m-2 (padding, margin).


●​ Typography: text-lg, font-bold.
●​ Colors: bg-blue-500, text-white.
●​ Borders: border, border-red-500.
●​ Flexbox/Grid: flex, grid, gap-4.

3. Responsive Design

●​ Add breakpoints using prefixes:


○​ sm:, md:, lg:, xl:, 2xl:.

Example:​
html​

<div class="text-base md:text-lg lg:text-xl">Responsive
Text</div>

●​

4. Hover, Focus, and Other States


●​ Use state modifiers: hover:, focus:, active:, etc.

Example:​
html​

<button class="bg-blue-500 hover:bg-blue-700 text-white">Hover
Me</button>

●​

Intermediate Topics

1. Customization

●​ Modify the tailwind.config.js file to customize the default theme.

Example: Add custom colors:​


js​

module.exports = {
theme: {
extend: {
colors: {
customBlue: '#1DA1F2',
},
},
},
};

●​
●​ Override spacing, typography, or other default values.

2. Plugins

●​ Use official plugins like @tailwindcss/forms, @tailwindcss/typography, etc.

Add plugins in tailwind.config.js:​


js​

plugins: [require('@tailwindcss/forms')],

●​
3. Dark Mode
Enable dark mode in configuration:​
js​

module.exports = {
darkMode: 'class', // or 'media'
};

●​

Use dark: prefix for styling dark mode.​


html​

<div class="bg-white dark:bg-gray-800">Dark Mode Example</div>

●​

4. Combining Classes
Use multiple utilities together:​
html​

<div class="flex items-center justify-center h-screen
bg-gray-200">
Centered Content
</div>

●​

Advanced Topics

1. Dynamic Styling with @apply


Reuse utility classes in custom CSS:​
css​

.btn {
@apply bg-blue-500 text-white font-bold py-2 px-4 rounded;
}

●​

2. PurgeCSS for Optimization


Remove unused classes in production:​
js​

module.exports = {
purge: ['./src/**/*.{js,jsx,ts,tsx,html}'],
};

●​

3. Custom Components
Build custom components using utility classes:​
html​

<div class="card p-6 bg-white shadow-md rounded-lg">
Custom Component
</div>

●​

4. Advanced Animations
Use transition, duration, and ease utilities:​
html​

<button class="bg-blue-500 hover:bg-blue-700 transition-all
duration-300">
Animated Button
</button>

●​

5. Using Tailwind with Frameworks

●​ Combine Tailwind with frameworks like React, Next.js, or Vue.

Example in React:​
jsx​

<button className="bg-green-500 text-white px-4 py-2">React
Button</button>

●​

6. Advanced Configurations
●​ Add custom variants or themes.

Example: Create a custom variant for "focus-within":​


module.exports = {
variants: {
extend: {
backgroundColor: ['focus-within'],
},
},
};

Best Practices

●​ Use Consistent Patterns: Follow utility-first principles for all styling.


●​ Optimize for Production: Enable PurgeCSS and minification for small CSS files.
●​ Avoid Overuse of @apply: Use only when creating reusable classes.
●​ Organize Code: Use consistent class ordering for readability.

Tailwind CSS Study Notes: Beginner to Advanced


1. Setting Up Tailwind CSS

Definition: Setting up Tailwind CSS involves configuring your project with the Tailwind
framework, enabling you to use its utility-first classes for styling.

Example:

# Install Tailwind CSS via npm

npm install -D tailwindcss postcss autoprefixer

npx tailwindcss init

2. Working With Color


Definition: Tailwind provides a wide range of built-in color utilities that can be used for text,
background, borders, and more, ensuring consistent and beautiful designs.

Example:

<div class="text-blue-500 bg-gray-100 border-red-400"></div>

3. Styling Text

Definition: Tailwind offers utilities for styling text, such as font size, weight, alignment, and
decoration.

Example:

<p class="text-lg font-bold text-center underline">Hello,


Tailwind!</p>

4. The Box Model: Spacing, Borders, and Display

Definition: Tailwind allows precise control over margins, padding, borders, and display
properties using intuitive utility classes.

Example:

<div class="p-4 m-2 border-2 border-gray-300"></div>

5. Responsive Design

Definition: Tailwind's responsive utilities allow you to build designs that adapt to different
screen sizes effortlessly.

Example:

<div class="text-sm md:text-lg lg:text-xl">Responsive Text</div>


6. Using Flexbox

Definition: Tailwind simplifies working with Flexbox, making it easy to align and distribute
elements.

Example:

<div class="flex justify-center items-center">

<div class="p-2">Item 1</div>

<div class="p-2">Item 2</div>

</div>

7. Using CSS Grid

Definition: Tailwind's grid utilities help create complex layouts with minimal effort.

Example:

<div class="grid grid-cols-3 gap-4">

<div>1</div>

<div>2</div>

<div>3</div>

</div>

8. Styling Buttons: Element States and Transitions

Definition: Tailwind makes it simple to style buttons and add hover, focus, and active states,
along with smooth transitions.

Example:

<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2


px-4 rounded transition duration-300">

Click Me
</button>

9. Styling Form Elements

Definition: Tailwind provides utilities to style input fields, checkboxes, radio buttons, and other
form elements.

Example:

<input class="border-2 border-gray-300 p-2 rounded


focus:border-blue-500" placeholder="Enter text">

10. Reusing Styles With @apply

Definition: The @apply directive in Tailwind allows you to reuse multiple utility classes in your
custom CSS.

Example:

/* custom.css */

.btn {

@apply bg-blue-500 text-white py-2 px-4 rounded;

<button class="btn">Reusable Button</button>

11. Reusing Styles With React Components

Definition: React components can encapsulate reusable Tailwind styles, making your UI
consistent and modular.

Example:

const Button = ({ children }) => (


<button className="bg-green-500 text-white py-2 px-4
rounded">{children}</button>

);

12. Absolute Positioning, z-index, and More

Definition: Tailwind simplifies positioning and layering with utilities for absolute, relative, and
fixed positioning, as well as z-index.

Example:

<div class="relative">

<div class="absolute top-0 left-0 z-10">Overlay</div>

</div>

13. Configuring Tailwind: Custom Font Family

Definition: Tailwind allows customization of the default theme, such as adding custom fonts.

Example:

// tailwind.config.js

module.exports = {

theme: {

extend: {

fontFamily: {

sans: ['CustomFont', 'Arial', 'sans-serif'],

},

},

},
};

<p class="font-sans">Custom Font Text</p>

14. Styling the Menu

Definition: Use Tailwind to design a responsive and visually appealing menu.

Example:

<nav class="bg-gray-800 p-4">

<ul class="flex space-x-4">

<li class="text-white hover:text-blue-400">Home</li>

<li class="text-white hover:text-blue-400">Menu</li>

<li class="text-white hover:text-blue-400">Contact</li>

</ul>

</nav>

15. Styling the Cart

Definition: Tailwind can be used to style a cart layout with items and totals dynamically
displayed.

Example:

<div class="p-4 border rounded shadow">

<h2 class="text-xl font-bold">Your Cart</h2>

<div class="flex justify-between mt-2">

<span>Pizza</span>
<span>$10</span>

</div>

</div>

16. Styling the Order Form

Definition: Create a user-friendly order form with Tailwind's form utilities.

Example:

<form class="space-y-4">

<input class="block w-full border p-2 rounded" placeholder="Name">

<input class="block w-full border p-2 rounded"


placeholder="Address">

<button class="bg-green-500 text-white py-2 px-4 rounded">Place


Order</button>

</form>

17. Styling the Order Overview

Definition: Display order details neatly with Tailwind's spacing, alignment, and typography
utilities.

Example:

<div class="p-4 border rounded shadow">

<h2 class="text-xl font-bold">Order #12345</h2>

<p class="mt-2">Status: <span


class="text-green-500">Delivered</span></p>

</div>
Adding a Shopping Cart with Redux Toolkit

What This Section Covers

1.​ Implementing a Shopping Cart


○​ Use Redux Toolkit to manage the cart.
2.​ Exploring Advanced React Router
○​ Learn data loading features in React Router.
3.​ Real-World Redux Use Cases
○​ Practical examples of Redux in action.

Prerequisite

●​ Understanding of Redux basics (covered in earlier sections).

Next Steps

●​ Dive into the project and start building!

Real-World Full-Stack Project


Overview

●​ Build a professional and stunning project.


●​ Use modern tools and libraries from the React ecosystem.

Technologies Used

1.​ Frontend:
○​ Styled Components: For component-based styling.
○​ React Query: For efficient data fetching and caching.
○​ React Hook Form: For handling forms easily.
○​ React Router: Advanced routing and navigation.
2.​ Backend:
○​ Superbase: Set up a backend and database from scratch.

Goal

●​ Learn how to build full-stack projects.


●​ Work with real-world libraries for a professional workflow.
Next Step

●​ Start by setting up the project and diving into Styled Components.

Supabase Crash Course : Buildings a Back-End! ➖


Setting Up a Free Backend with Supabase

Overview

In this section, you'll learn to create and manage a backend for your application using
Supabase.

Key Topics Covered

1.​ Application Data:


○​ Plan and discuss the data needed for the app.
2.​ Database Tables:
○​ Create and organize tables in the Supabase database.
3.​ Data Loading:
○​ Use the Supabase API to fetch and load data into the app.
4.​ Table Relationships:
○​ Briefly model relationships between different database tables.

What You’ll Achieve

●​ Gain the ability to build full-stack applications independently.


●​ Understand database and API integration with a frontend application.

Why This Matters

●​ Learning Supabase equips you with essential tools for modern app development.
●​ A powerful step towards building complete, production-ready apps.

Get ready to dive in and explore the potential of Supabase! 🎉


Introduction to Supabase
What is Supabase?

●​ A service for quickly creating a backend with a Postgres database.


●​ Provides a ready-to-use API to interact with the database.
●​ Simplifies backend setup – no backend coding needed.

Why Use Supabase?

1.​ Easy Setup: Automatically creates a database and API.


2.​ Frontend-Friendly: Perfect for frontend developers to start projects quickly.
3.​ Complete Solution:
○​ User Authentication: Manage users effortlessly.
○​ File Storage: Store and manage files.
4.​ API or Library: Access via API or its JavaScript library.

Benefits

●​ Build full-stack apps without backend knowledge.


●​ Saves time with simple and automatic setup.
●​ Popular and fast-growing service in the developer community.

Next Step

●​ Start building the backend for the Wild Oasis Management App using Supabase.​

Planning and Creating Database Tables in Supabase


Key Concepts

1.​ State Modeling:


○​ Think about state at a higher level (pages or features), not components.
○​ Define state slices (or categories) based on app features.
2.​ Features and Related States:
○​ Bookings: Manages booking data.
○​ Cabins: Tracks cabin details.
○​ Guests: Stores guest information.
○​ Dashboard & Check-in/Check-out: Use booking data for stats and updates.
○​ Settings: Requires its own data table.
○​ Authentication: Needs a table for user information.
3.​ State to Tables:
○​ Each state slice becomes a table in the Supabase database.

Bookings Table Details

●​ A booking connects a guest and a cabin.


●​ Use foreign keys to link tables:
○​ Guest ID: Links to the guest table.
○​ Cabin ID: Links to the cabin table.

Technical Terms

●​ Primary Key: Unique identifier for a table (e.g., Guest ID in the guest table).
●​ Foreign Key: Field in one table that references the primary key of another table.

Next Steps

1.​ Create simple tables (Cabins, Guests, etc.).


2.​ Set up the Bookings table and link it to other tables using foreign keys.

Understanding will improve as you start implementing! 😊

Managing Remote State with React Query ➖


Key Concepts

1.​ React Query:


○​ A powerful library for managing remote state in React apps.
○​ Handles fetching, caching, syncing, and updating remote data seamlessly.
2.​ Integration with Supabase:
○​ React Query will manage data stored in the Supabase backend.
○​ Simplifies handling of remote data for the project.
3.​ Advantages:
○​ Eliminates manual effort for managing remote state.
○​ Provides an efficient and smooth workflow.
○​ Feels "magical" due to its simplicity and power.

Next Steps

●​ Start integrating React Query into the project.


●​ Use it for fetching and storing all remote data from Supabase.

React Query will make the app development faster and easier! 🚀

React Query
What is React Query?

React Query is a powerful library for managing server-state (remote state) in React
applications. It simplifies fetching, caching, syncing, and updating server data, making it easier
to work with APIs and databases.

Key Features of React Query

1.​ Data Fetching and Caching


○​ Automatically caches API responses for better performance.
○​ No need to refetch unchanged data repeatedly.
2.​ Background Synchronization
○​ Automatically keeps data in sync with the server.
○​ Refetches data in the background when components remount or windows regain
focus.
3.​ Optimistic Updates
○​ Updates UI instantly while waiting for server responses.
○​ Rollbacks to previous state if the request fails.
4.​ Stale-While-Revalidate
○​ Marks data as "stale" after a defined time.
○​ Fetches fresh data while displaying the cached data.
5.​ Query Invalidation
○​ Automatically or manually invalidates outdated data.
○​ Ensures up-to-date data without unnecessary API calls.
6.​ DevTools
○​ React Query includes dev tools for debugging, inspecting cache, and managing
server state.
7.​ Pagination and Infinite Scroll
○​ Built-in support for paginated and infinite queries.
8.​ Error Handling
○​ Centralized error management for API requests.
○​ Custom error recovery strategies.

Uses of React Query

1.​ API Management


○​ Fetch, manage, and cache data from REST or GraphQL APIs.
2.​ Database Integration
○​ Works seamlessly with backend services like Supabase, Firebase, and others.
3.​ Global State for Server Data
○​ Manages remote data across the app, reducing the need for global state libraries
like Redux.
4.​ Offline Support
○​ Automatically syncs data when the app goes offline and reconnects.
5.​ Polling
○​ Periodically refetches data for real-time updates.

Advantages of React Query

●​ Improved Performance: Reduces redundant API calls with smart caching.


●​ Simplified Codebase: Handles complex server-state logic for you.
●​ Scalability: Works well in both small and large projects.
●​ Reactivity: Automatically re-renders components when data changes.

Important Concepts

1.​ Queries
○​ Used to fetch and cache data.

Example:​

const { data, error, isLoading } = useQuery('todos', fetchTodos);

2.​ Mutations
○​ For creating, updating, or deleting data.
Example:​

const mutation = useMutation(addTodo);

mutation.mutate(newTodo);

3.​ Query Keys


○​ Unique identifiers for each query to track and cache.
○​ Example: ['todos', { status: 'completed' }].
4.​ QueryClient
○​ Central store for managing queries and cache.

When to Use React Query

●​ Apps with heavy API interactions or server-state management.


●​ Projects requiring real-time updates or background syncing.
●​ Scenarios needing caching, pagination, or offline support.

Best Practices

1.​ Use Descriptive Query Keys: Helps in managing cache effectively.


2.​ Set Cache Timeouts Appropriately: Adjust cache time to balance performance and
freshness.
3.​ Handle Errors Gracefully: Implement error boundaries or fallback UI.
4.​ Use DevTools for Debugging: Helps in identifying cache and query issues.

React Query in Comparison

●​ Redux: Use Redux for client state and React Query for server state.
●​ Apollo Client: Similar functionality but React Query is API-agnostic and easier for
non-GraphQL APIs.

Why Learn React Query?

●​ It simplifies server-state management, which can otherwise be complex.


●​ Encourages efficient and declarative data fetching patterns.
●​ It’s a modern tool used in professional React projects.
React Query empowers developers to focus on building features rather than managing server
data intricacies.

Advanced React Patterns ➖


Key Topics:

1.​ Render Props Pattern​

○​ Technique to share logic between components using a function as a prop.


2.​ Higher-Order Components (HOCs)​

○​ A function that takes a component and returns a new enhanced component.


3.​ Compound Component Pattern (Instructor's Favorite)​

○​ Components designed to work together and share internal state.


○​ Example: Building reusable components like:
■​ Modal Window
■​ Context Menu

Highlights:

●​ Advanced concepts for professional React projects.


●​ Practical applications to enhance your project skills.
●​ Exclusive content beyond typical React courses.

Note: This section is advanced but highly rewarding for boosting React expertise!​

Advanced React Patterns Overview ➖


Key Concepts:

1.​ Types of Reusable Code in React:​

○​ UI Reusability: Achieved using components and props.


■​ Props work as the component's API to customize appearance and
behavior.
■​ The children prop allows passing content or components into a
component.
○​ Stateful Logic Reusability: Achieved using custom hooks.
2.​ Advanced Patterns:​

○​ Render Props Pattern:


■​ Pass a function as a prop to control what a component renders.
■​ Useful for sharing logic with JSX while allowing flexibility.
■​ Less common today due to custom hooks but still valuable for specific
cases.
○​ Compound Component Pattern:
■​ Multiple components working together as one "super component."
■​ Manages internal state independently of the parent component.
■​ Ideal for creating self-contained, flexible components.

Key Takeaways:

●​ These patterns are not built into React but emerged as clever solutions to specific
problems.
●​ Mastering Render Props and Compound Components sets you apart as a React
developer.
●​ Learn and apply these patterns in practice for advanced React development.​
Higher-Order Component (HOC) Pattern ➖
Key Concepts:

1.​ What is an HOC?​

○​ A Higher-Order Component (HOC) is a function that takes a component as


input and returns a new, enhanced component.
○​ Used to add functionality to a component without modifying its code.
2.​ Naming Convention:​

○​ Typically named with a with prefix (e.g., withToggles).


3.​ How it Works:​

○​ The HOC wraps the original component and adds new props or logic.
○​ Example: A withToggles HOC adds toggle functionality to a ProductList
component.
4.​ Steps to Use HOC:​

○​ Pass the base component to the HOC function.


○​ HOC returns a new component with additional features.
○​ Use the enhanced component in your app.

Key Takeaways:

●​ HOCs were widely used before React Hooks for sharing logic.
●​ They are still relevant for understanding how some libraries (e.g., Redux) work.
●​ Use HOCs to extend functionality when direct modification isn’t possible (e.g., third-party
components).

Example Use Case:

●​ Add toggle functionality to a product list component using withToggles.


●​ Original component remains unmodified, while the enhanced version includes new
features.

Next Topic: Compound Component Pattern.​



Compound Component Pattern in React ➖
1.​ Definition:​

○​ A pattern to create related components that work together for a specific task.
○​ Example: A counter, modal windows, pagination, or tables.
2.​ Structure:​

○​ Parent Component: Holds the shared logic/state.


○​ Child Components: Depend on the parent and make sense only when used with
it.
○​ Example: HTML <select> and <option> elements (options are meaningful
only inside a select box).

Benefits

●​ Flexibility: Arrange or omit child components as needed.


●​ Reusable: Components adapt without requiring extra props.
●​ Cleaner API: Avoids "prop explosion" (too many props).

Steps to Implement

1.​ Create a Context:​

○​ Use React's createContext to share state and functions among components.


○​ Example: CounterContext.
2.​ Create the Parent Component:​

○​ Store shared state (e.g., count for a counter).


○​ Provide state and functions via the context.
○​ Use children prop to render nested components.
3.​ Create Child Components:​

○​ Use useContext to access shared state/functions from the context.


○​ Implement specific functionality, e.g., increase/decrease buttons, label, or
count display.
4.​ Attach Child Components to Parent:​

○​ Add child components as properties of the parent component for cleaner exports.

Example:​
Counter.Label = Label;
Counter.Increase = IncreaseButton;

Counter.Decrease = DecreaseButton;

○​

Example: Counter

// Parent Component

const Counter = ({ children }) => {

const [count, setCount] = useState(0);

const increase = () => setCount((prev) => prev + 1);

const decrease = () => setCount((prev) => prev - 1);

return (

<CounterContext.Provider value={{ count, increase, decrease }}>

<span>{children}</span>

</CounterContext.Provider>

);

};

// Child Components

const Count = () => {

const { count } = useContext(CounterContext);

return <span>{count}</span>;

};
const Increase = ({ icon }) => {

const { increase } = useContext(CounterContext);

return <button onClick={increase}>{icon || "+"}</button>;

};

const Decrease = ({ icon }) => {

const { decrease } = useContext(CounterContext);

return <button onClick={decrease}>{icon || "-"}</button>;

};

// Attach Child Components

Counter.Count = Count;

Counter.Increase = Increase;

Counter.Decrease = Decrease;

// Usage Example

<Counter>

<Counter.Label>My Counter</Counter.Label>

<Counter.Decrease icon=" ➖" />


<Counter.Count />

<Counter.Increase icon=" ➕" />


</Counter>;
Advantages

●​ Easy to rearrange or omit components.


●​ Encapsulates state and logic in one place.
●​ Avoids excessive props and reduces coupling.

0—------------------------The ENd—-----------------

You might also like