Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
6 views

react-notes

The document provides an overview of key concepts in React, including the differences between declarative and imperative programming, the structure and benefits of Single Page Applications (SPAs), and the use of components and props. It also covers advanced topics such as controlled vs uncontrolled components, state management with hooks, and the Virtual DOM. Additionally, it discusses rendering techniques like Server-Side Rendering (SSR) and Client-Side Rendering (CSR), along with practical examples and best practices for building React applications.

Uploaded by

Ayesha Shaw
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views

react-notes

The document provides an overview of key concepts in React, including the differences between declarative and imperative programming, the structure and benefits of Single Page Applications (SPAs), and the use of components and props. It also covers advanced topics such as controlled vs uncontrolled components, state management with hooks, and the Virtual DOM. Additionally, it discusses rendering techniques like Server-Side Rendering (SSR) and Client-Side Rendering (CSR), along with practical examples and best practices for building React applications.

Uploaded by

Ayesha Shaw
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 39

Table of Contents

Introduction to Declarative vs Imperative Programming----------------------------------------------------------------2


React as a Single Page Application (SPA)------------------------------------------------------------------------------------- 3
JavaScript and DOM vs React and ReactDOM: A Closer Look-----------------------------------------------------------4
JSX and Babel------------------------------------------------------------------------------------------------------------------------ 5
Components and Props in React------------------------------------------------------------------------------------------------ 6
Components------------------------------------------------------------------------------------------------------------------------------------- 6
Props----------------------------------------------------------------------------------------------------------------------------------------------- 7
Controlled vs. Uncontrolled Components in React------------------------------------------------------------------------ 10
State Management and Its Importance------------------------------------------------------------------------------------- 13
Introduction to React Hooks: useState-------------------------------------------------------------------------------------------------14
useRef--------------------------------------------------------------------------------------------------------------------------------------------18
Side Effects in React:-------------------------------------------------------------------------------------------------------------- 23
Lifecycle Phases:------------------------------------------------------------------------------------------------------------------- 23
useEffect and Unmount Phase------------------------------------------------------------------------------------------------------------24
Context API-------------------------------------------------------------------------------------------------------------------------------------28
Chakra UI: A Guide to Installation, Style Props, and Key Components---------------------------------------------------------31
Introduction to Declarative vs Imperative Programming

Programming paradigms are fundamental to how we think about and write code.

Imperative Programming

Focuses on how to perform tasks:

 The developer specifies every step required to achieve the desired outcome.

 Typically involves direct manipulation of state and data structures.

Declarative Programming

Focuses on what the outcome should be:

 Developers describe the desired result without explicitly outlining the steps to achieve it.

 The underlying system determines the execution steps.

Declarative vs Imperative Programming: In Depth

Imperative Programming in Action

Example: Using JavaScript to manipulate the DOM directly.

<script>
const element = document.createElement("p");
element.textContent = "Hello, World!";
document.body.appendChild(element);
</script>
 The programmer explicitly creates the element, sets its content, and appends it to the DOM.

 Every change to the DOM must be coded manually, leading to verbose and error-prone scripts.

Declarative Programming in Action

Example: Using React to define a UI component declaratively.

const root = ReactDOM.createRoot(document.getElementById("root"));

root.render(<p>Hello, World!</p>);

 The developer specifies what the UI should look like in its final state.

 React handles the underlying DOM manipulations, making the code simpler, cleaner, and easier to maintain.

HTML and CSS as Declarative Paradigms

HTML and CSS are inherently declarative:

 HTML: Describes the structure of the web page (e.g., a <div> is a container).

 CSS: Defines how elements should look (e.g., "Make this container blue").
React as a Single Page Application (SPA)
What is an SPA?

 A Single Page Application (SPA) is a web application that loads a single HTML page and dynamically updates
the content as the user interacts with the app.

 SPAs use JavaScript and frameworks like React to handle routing, state management, and dynamic content
rendering on the client side.

Key Characteristics of SPAs

1. Single HTML Load:

 The server delivers one HTML file at the beginning, and further interactions are handled dynamically
via JavaScript.

2. Client-Side Routing:

 SPAs use libraries like React Router to navigate between "pages" without reloading the browser.

3. Improved User Experience:

 Faster interactions because only specific components are updated, not the entire page.

4. Dynamic Content Rendering:

 SPAs leverage ReactDOM and the Virtual DOM for efficient, seamless UI updates.

Benefits of SPAs

Feature Advantages
Speed Faster page transitions without full reloads.
Smooth User Feels like a native application.
Experience
Reduced Server Load Minimizes server requests after the initial load.

Limitations of SPAs

Feature Challenges
SEO Search engines may struggle to index SPA content.
Initial Load Time Loading the entire app initially can take longer.
JavaScript Heavily reliant on JavaScript execution.
Dependency

Server-Side Rendering (SSR) vs Client-Side Rendering (CSR)

What is SSR?

 Server-Side Rendering (SSR) generates HTML content on the server for each request.

 The browser receives a fully-rendered page, improving load times and SEO performance.

Example of SSR Workflow:

1. User requests a URL.

2. The server processes the request, runs React on the server, and generates HTML.
3. The browser receives the HTML, which is displayed immediately.

Framework Support for SSR: React frameworks like Next.js support SSR.

What is CSR?

 Client-Side Rendering (CSR) is React's default behavior where JavaScript runs in the browser to dynamically
generate and render the UI.

Example of CSR Workflow:

1. User requests a URL.

2. The server responds with a blank HTML page and JavaScript files.

3. The browser downloads and executes the JavaScript to render the UI.

Frameworks/Tools: React (default), Angular, Vue.

Comparison of SSR vs CSR

Feature Server-Side Rendering (SSR) Client-Side Rendering (CSR)


SEO Better SEO; crawlers see complete HTML. Poor SEO; content may load after crawling.
Load Time Faster initial load. Slower initial load but faster interactions.
Performance Relies on server processing power. Relies on browser processing power.
Interactivity Delayed interactivity due to server round Immediate after JavaScript execution.
trips.

When to Use SSR, CSR, or Hybrid Rendering

Rendering When to Use


Type
SSR SEO-critical pages, blogs, e-commerce sites.
CSR Highly interactive apps, SPAs, dashboards.
Hybrid Use SSR for landing pages and CSR for the rest.

JavaScript and DOM vs React and ReactDOM: A Closer


Look

The DOM: Traditional Approach

The Document Object Model (DOM) is a browser-based representation of the webpage’s structure. Direct
manipulation of the DOM with JavaScript allows developers to update elements dynamically.

Example:

<script>
const element = document.createElement("h1");
element.textContent = "Imperative Example";
document.body.appendChild(element);
</script>
React and ReactDOM: The Declarative Alternative

React introduces the Virtual DOM (VDOM), an in-memory representation of the actual DOM. ReactDOM bridges the
gap between React components and the browser’s actual DOM.

How ReactDOM and the Virtual DOM Work

The Virtual DOM (VDOM)

 What is it? A lightweight copy of the DOM that exists in memory, allowing React to make efficient updates.

 How does it work?

 React compares the current VDOM with the previous one (a process called "diffing").

 Only the elements that have changed are updated in the actual DOM (known as "reconciliation").

 Why does it matter?

 Direct DOM manipulations are slow because browsers re-render the entire UI for even small
changes.

 React's VDOM minimizes these re-renders, making updates faster and more efficient.

ReactDOM

ReactDOM acts as a renderer that applies the Virtual DOM changes to the actual DOM.

Example:

const root = ReactDOM.createRoot(document.getElementById("root"));

root.render(<h1>Declarative Example</h1>);

Key Differences Between Direct DOM and React's Virtual DOM

Feature Direct DOM (Vanilla JS) React's Virtual DOM


Control Complete control over every DOM change. Abstracted control through React.
Performance Slower due to frequent re-renders. Faster, updates only the changed parts.
Ease of Use Requires detailed, verbose instructions. Declarative and simpler to manage.
Code Maintenance Harder to debug and maintain. Cleaner, reusable components.
Use Case Suitable for small, simple applications. Ideal for dynamic, complex UIs.

JSX and Babel


What is JSX?

 JavaScript XML (JSX) allows you to write HTML-like syntax in JavaScript files.

 It simplifies creating React components.

Example JSX Code:

const element = <h1>Hello, World!</h1>;


Babel: Transforming JSX

Browsers don’t understand JSX. Babel compiles it into plain JavaScript:


Transpiled Output:

const element = React.createElement("h1", null, "Hello, World!");

JSX and Babel in Action

1. Write JSX Code:

const root = ReactDOM.createRoot(document.getElementById("root"));


root.render(<p>Seize the day!</p>);
2. Compile with Babel: Add Babel to your project for real-time transpilation:

<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel">
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<h1>Carpe Diem</h1>);
</script>

Advanced JSX Features

Key Features

 Interpolation: Embed JavaScript logic in JSX.

const userName = "Alice";

const element = <p>Hello, {userName}!</p>;

 Event Handling: Add interactive functionality.

const button = <button onClick={() => alert("Clicked!")}>Click Me</button>;

 Fragments: Group multiple elements without extra wrappers.

<>

<p>First Element</p><p>Second Element</p>

</>

 Inline Styling: Add styles dynamically.

const box = <div style={{ color: "blue", fontSize: "20px" }}>Styled Box</div>;

Components and Props in React


Introduction

React components are the building blocks of any React application. They encapsulate UI logic and presentation,
enabling developers to create reusable, modular, and maintainable interfaces. Props (short for properties) allow data
to flow from parent components to child components, making components dynamic and customizable.

Components
A React component is a JavaScript function (or class) that returns JSX. Components can be:

1. Functional Components: Modern, lightweight components defined as JavaScript functions.

function Greet(props) {
return <h1>Hello, {props.name}!</h1>;
}
2. Class Components: Older, stateful components defined using ES6 classes.

class Greet extends React.Component {


render() {
return <h1>Hello, {this.props.name}!</h1>;
} }

Props
Props allow components to:

 Receive Data: Passed down from parent components to children as attributes.

 Stay Immutable: Props are read-only, ensuring unidirectional data flow.

Example:

function Greet({ name }) {


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

const element = <Greet name="Alice" />;


ReactDOM.createRoot(document.getElementById("root")).render(element);

Key Concepts

Feature Description
Dynamic Content Props allow for rendering variable data.
Reusability Components can be reused with different props.
Unidirectional Flow Data flows from parent to child only.
Immutability Props cannot be modified by the receiving component.

2. React Component Architecture

Overview

React applications follow a component hierarchy, where the application is composed of multiple nested
components. This promotes:

1. Reusability: Components can be reused across different parts of the application.

2. Isolation: Each component is self-contained and can be developed independently.

3. Maintainability: Code is modular and easier to manage.

Component Tree Example

For an e-commerce application, the hierarchy might look like this:

App

├── Header
├── Product List
│ ├── Product Item
│ │ ├── Add To Cart Button
├── Footer
Component Composition

React encourages composition over inheritance, meaning components are combined to build more complex UIs.
Example:
function Navbar() {
return <div>Navbar</div>;
}
function Sidebar() {
return <div>Sidebar</div>;
}
function Content() {
return <div>Main Content</div>;
}
function App() {
return (
<>
<Navbar />
<div>
<Sidebar />
<Content />
</div>
</>
);
}

3. Children Props in React

What is the children Prop?

The children prop is a special prop in React that allows developers to pass any JSX or components between the
opening and closing tags of a parent component.

Example:

function Container({ children }) {


return <div className="container">{children}</div>;
}
// Usage
<Container>
<h1>Hello World</h1><p>This is a paragraph.</p>
</Container>;

Use Cases

1. Flexible Layouts: Pass different layouts or components into a wrapper.

2. Reusable Components: Create generalized components like Card, Modal, or Container.

Example: A Reusable Card Component:

function Card({ title, children }) {


return (
<div className="card">
<h2>{title}</h2>
<div>{children}</div>
</div>
);
}
// Usage<Card title="My Card">
<p>This is the card content!</p>
</Card>;

4. Conditional Rendering and Styling

Conditional Rendering

React provides tools to render components or elements based on conditions.

 if-else Statements:
function Message({ isLoggedIn }) {
if (isLoggedIn) {
return <p>Welcome back!</p>;
} else {
return <p>Please log in.</p>;
}
}
 Ternary Operator:

function Message({ isLoggedIn }) {


return <p>{isLoggedIn ? "Welcome back!" : "Please log in."}</p>;
}
Short-Circuit Evaluation:

function Warning({ showWarning }) {


return showWarning && <p>Warning: You are offline!</p>;
}

Conditional Styling

React allows dynamic styling using JavaScript.

Example: Dynamic Button Styling:

function Button({ isPrimary }) {


const style = {
backgroundColor: isPrimary ? "blue" : "gray",
color: "white",
padding: "10px",
};
return <button style={style}>Click Me</button>;
}

Comprehensive Example: Blog Page with All Concepts

This example demonstrates:

 Components and props.

 children props for flexible layouts.

 Conditional rendering and styling.

Code Implementation:

function Header() {
return <header>Blog Header</header>;
}
function Footer() {
return <footer>Blog Footer</footer>;
}
function BlogCard({ title, content, isFeatured }) {
const cardStyle = {
border: "1px solid gray",
padding: "10px",
backgroundColor: isFeatured ? "lightyellow" : "white",
};
return (
<div style={cardStyle}>
<h2>{title}</h2>
<p>{content}</p>
</div>
);
}
function App() {
const blogs = [
{ title: "React Basics", content: "Learn the basics of React.", isFeatured: true },
{ title: "Advanced React", content: "Delve deeper into React.", isFeatured: false },
];
return (
<>
<Header />
<main>
{blogs.map((blog, index) => (
<BlogCard
key={index}
title={blog.title}
content={blog.content}
isFeatured={blog.isFeatured}
/>
))}
</main>
<Footer />
</> );
}ReactDOM.createRoot(document.getElementById("root")).render(<App />);

Controlled vs. Uncontrolled Components in React

Introduction

In React, form elements like inputs, textareas, and select elements can be managed in two ways:

1. Controlled Components: React fully manages the state of the form element.

2. Uncontrolled Components: The DOM itself manages the state of the form element.

Understanding these two approaches is crucial for building forms in React effectively.

Controlled Components

Definition:

In controlled components, the value of a form element is controlled by React state. The component's state acts as the
"single source of truth."

Key Features:

 React state controls the input value.

 Requires an onChange handler to update the state.

 Synchronous and predictable.

Example:

import React, { useState } from 'react';

function ControlledForm() {
const [inputValue, setInputValue] = useState('');
const handleChange = (e) => {
setInputValue(e.target.value);
};
const handleSubmit = (e) => {
e.preventDefault();
console.log(`Submitted Value: ${inputValue}`);
};
return (
<form onSubmit={handleSubmit}>
<label>
Name:
<input type="text" value={inputValue} onChange={handleChange} />
</label>
<button type="submit">Submit</button>
</form>
);
}
export default ControlledForm;

How It Works:

1. The value attribute of the <input> is tied to the React state (inputValue).

2. When the user types, the onChange handler updates the state.

3. React re-renders the component with the updated state, ensuring the input reflects the current state.

Advantages:

 Single Source of Truth: React state controls the form, making data flow predictable.

 Validation: Easier to perform validation and enforce rules dynamically.

 Integration: Works seamlessly with React's state and lifecycle methods.

Disadvantages:

 Verbose Code: Requires additional state and handlers for every input.

 Performance: Frequent re-renders may impact performance for large forms.

Uncontrolled Components
Definition:

In uncontrolled components, the form element's state is managed by the DOM itself. React accesses the value
through a ref.

Key Features:

 DOM state is the source of truth.

 Uses refs to retrieve input values.

 Asynchronous and less predictable.

Example:

import React, { useRef } from 'react';


function UncontrolledForm() {
const inputRef = useRef(null);

const handleSubmit = (e) => {


e.preventDefault();
console.log(`Submitted Value: ${inputRef.current.value}`);
};
return (
<form onSubmit={handleSubmit}>
<label>
Name:
<input type="text" ref={inputRef} />
</label>
<button type="submit">Submit</button>
</form>
);
}
export default UncontrolledForm;

How It Works:

1. The <input> is uncontrolled, so its state is managed by the DOM.

2. The ref (inputRef) provides access to the input value when needed.

3. The component doesn't re-render when the input value changes.

Advantages:

 Simpler Code: No need to manage state or handlers for inputs.

 Performance: Fewer re-renders, as the input state is not managed by React.

 Use Cases: Ideal for simple forms or when integrating with non-React libraries.

Disadvantages:

 Validation: Harder to validate and enforce rules dynamically.

 Limited React Control: React has less control over the form element's behavior.

 Debugging: Accessing and managing refs can make debugging harder.

4. Key Differences

Aspect Controlled Components Uncontrolled Components


State State is managed by React. State is managed by the DOM.
Management
Value Access Through React state (value prop). Through ref to access the DOM node.
Validation Easy to validate and enforce rules. Validation requires manual handling via ref.
Re-renders Component re-renders on every state No re-renders on input value change.
update.
Code Complexity Requires additional state and handlers. Simpler and requires less code.
Use Case Complex forms with dynamic validation. Simple forms or when integrating with
libraries.

5. Choosing Between Controlled and Uncontrolled Components

When to Use Controlled Components:

 Complex forms with real-time validation.

 When the form data needs to be synchronized with React state.

 Dynamic forms where input values affect other parts of the UI.

When to Use Uncontrolled Components:

 Simple forms where React doesn't need to manage input values.

 Forms where performance is critical, and re-renders need to be minimized.

 When integrating with non-React libraries that rely on direct DOM manipulation.
6. Mixing Controlled and Uncontrolled Components

In some cases, you might combine both approaches to balance simplicity and control. For example, a form might
have some inputs managed by React state and others accessed via refs.

Example:

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


function MixedForm() {
const [email, setEmail] = useState('');
const nameRef = useRef(null);
const handleSubmit = (e) => {
e.preventDefault();
console.log(`Name: ${nameRef.current.value}, Email: ${email}`);
};
return (
<form onSubmit={handleSubmit}>
<label>
Name (Uncontrolled):
<input type="text" ref={nameRef} />
</label>
<label>
Email (Controlled):
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</label>
<button type="submit">Submit</button>
</form>
);
}

7. Summary Table

Feature Controlled Uncontrolled


State Source Managed by React. Managed by the DOM.
Value React state (value prop). ref to access DOM elements.
Access
Validation Dynamic and easier to implement. Requires manual handling via ref.
Reactivity Updates trigger re-renders. Changes do not cause re-renders.
Complexity More verbose, requires state and handlers. Simpler, no need for state or handlers.
Best For Complex, dynamic forms with validation. Simple forms, performance-critical use cases.

State Management and Its Importance


What is State in React?

 Definition: State represents dynamic data or "the memory" of a React component. It determines how a
component behaves and renders based on changes.

 Example: A button's label toggling between "Start" and "Stop" is determined by state.

Why is State Management Important?

1. Dynamic UIs: State enables components to react to user interactions, such as clicks or form inputs.

2. Component Isolation: State allows components to encapsulate and manage their own data independently.

3. Reactivity: React automatically re-renders components when state changes, ensuring the UI stays up-to-date.

Example Without State:

function Counter() {
let count = 0;
function increment() {
count++;
console.log(count); // No UI update
}
return <button onClick={increment}>Count: {count}</button>;
}
With State:

function Counter() {
const [count, setCount] = React.useState(0);

function increment() {
setCount(count + 1); // Triggers UI re-render
}
return <button onClick={increment}>Count: {count}</button>;
}

Introduction to React Hooks: useState


What are Hooks?

Hooks are special functions introduced in React 16.8 to enable state and side effects in functional components.

What is useState?

 Purpose: Allows functional components to manage state.

 Returns: An array with two elements:

i. The current state value.

ii. A function to update the state.

Syntax:

const [state, setState] = React.useState(initialState);


Key Features of useState

1. Initial State: Can be any data type (string, number, object, array, etc.).

2. State Setter Function: Replaces the current state with a new value.

3. Reactivity: State updates trigger component re-renders.

Example:

function Example() {
const [count, setCount] = React.useState(0);
function increment() {
setCount(count + 1);
}
return <button onClick={increment}>Count: {count}</button>;
}
3. Examples of State Management

Managing Simple Data Types

 String State:

function Greeting() {
const [name, setName] = React.useState("Guest");
return (
<div>
<p>Hello, {name}!</p>
<button onClick={() => setName("Alice")}>Set Name</button>
</div>
);
}
 Boolean State:
function Toggle() {
const [isOn, setIsOn] = React.useState(false);
return (
<button onClick={() => setIsOn(!isOn)}>
{isOn ? "Switch Off" : "Switch On"}
</button>
);
}
Working with Arrays

Adding Items to an Array:


function ItemList() {
const [items, setItems] = React.useState([]);
function addItem() {
setItems([...items, `Item ${items.length + 1}`]);
}
return (
<div>
<button onClick={addItem}>Add Item</button>
<ul>
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
</div>
);
}
Removing Items from an Array:
function RemoveItemList() {
const [items, setItems] = React.useState(["Item 1", "Item 2", "Item 3"]);
function removeLastItem() {
setItems(items.slice(0, -1));
}
return (
<div>
<button onClick={removeLastItem}>Remove Last Item</button>
<ul>
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
</div>
);}
Working with Objects
Updating Object Properties:

function UserProfile() {
const [user, setUser] = React.useState({ name: "Alice", age: 25 });
function updateAge() {
setUser({ ...user, age: user.age + 1 });
}
return (
<div>
<p>Name: {user.name}</p>
<p>Age: {user.age}</p>
<button onClick={updateAge}>Increase Age</button>
</div>
);
}

Working with Arrays of Objects

Adding to an Array of Objects:

function TodoList() {
const [todos, setTodos] = React.useState([]);

function addTodo() {
const newTodo = { id: todos.length + 1, task: `Task ${todos.length + 1}` };
setTodos([...todos, newTodo]);
}
return (
<div>
<button onClick={addTodo}>Add Todo</button>
<ul>
{todos.map((todo) => (
<li key={todo.id}>
{todo.task}
</li>
))}
</ul>
</div>
);
}
Updating an Item in an Array of Objects:

function UpdateTodo() {
const [todos, setTodos] = React.useState([
{ id: 1, task: "Learn React", completed: false },
]);

function toggleComplete(id) {
setTodos(
todos.map((todo) =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
)
);
}
return (
<ul>
{todos.map((todo) => (
<li key={todo.id}>
<span style={{ textDecoration: todo.completed ? "line-through" : "none" }}>
{todo.task}
</span>
<button onClick={() => toggleComplete(todo.id)}>
{todo.completed ? "Undo" : "Complete"}
</button>
</li>
))}
</ul>
);

Best Practices for State Management

1. Keep State Local:

 Manage state within the component that needs it. Lift it up only if necessary.

2. Avoid Overuse:

 Not every piece of data needs to be in state (e.g., constants, derived data).

3. Update State Immutably:

 Use ...spread operators to ensure immutability when updating objects or arrays.

4. Minimize State Complexity:

 Use simpler states or multiple smaller states instead of deeply nested ones when possible.

Summary

 State is a cornerstone of React, enabling dynamic UIs.

 The useState hook allows functional components to manage and update state.

 React supports state management for various data types, from strings to complex arrays of objects.

 Best practices ensure state remains clean, predictable, and efficient.


Interactive To-Do List with State Management

This application combines everything discussed above: useState, state management for arrays of objects, and
dynamic UI updates with React. It serves as a practical implementation of state management concepts.

Application Features

1. Add new tasks to the list.

2. Mark tasks as complete/incomplete.

3. Delete tasks from the list.

Code Implementation

import React, { useState } from "react";


import ReactDOM from "react-dom/client";
import "./styles.css"; // Optional: Add CSS for better styling

function App() {
const [tasks, setTasks] = useState([]);
const [taskInput, setTaskInput] = useState("");

// Add a new task


function addTask() {
if (taskInput.trim() === "") {
alert("Task cannot be empty!");
return;
}
const newTask = {
id: tasks.length + 1,
text: taskInput,
completed: false,
};
setTasks([...tasks, newTask]);
setTaskInput(""); // Clear input field
}
// Toggle task completion
function toggleTaskCompletion(taskId) {
setTasks(
tasks.map((task) =>
task.id === taskId ? { ...task, completed: !task.completed } : task
)
);
}
// Delete a task
function deleteTask(taskId) {
setTasks(tasks.filter((task) => task.id !== taskId));
}

return (
<div className="app">
<h1>To-Do List</h1>

{/* Task Input */}


<div className="input-container">
<input
type="text"
placeholder="Enter a task"
value={taskInput}
onChange={(e) => setTaskInput(e.target.value)}
/>
<button onClick={addTask}>Add Task</button>
</div>
{/* Task List */}
<ul className="task-list">
{tasks.length > 0 ? (
tasks.map((task) => (
<li key={task.id} className="task-item">
<span
className={task.completed ? "completed" : ""}
onClick={() => toggleTaskCompletion(task.id)}
>
{task.text}
</span>
<button onClick={() => deleteTask(task.id)}>Delete</button>
</li>
))
) : (
<p>No tasks added yet!</p>
)}
</ul>
</div>
);
}

// Render the application


const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);

useRef
Introduction

useRef is a React Hook designed to manage references to DOM elements or store values across component renders
without triggering re-renders. It serves as a container for mutable data that remains consistent across re-renders,
akin to a "box" that safely holds a value. This hook is particularly useful for accessing DOM elements directly,
managing focus, or storing values like timers or animation frames that do not directly influence the component's
output.

Detailed Explanation

What is useRef?

useRef is part of React's Hooks API, allowing developers to maintain a consistent reference to a value or a DOM
element throughout the component's lifecycle. It returns a mutable object with a .current property, which can be
initialized with a value of any type. Unlike state updates with useState, updates to a useRef value do not cause the
component to re-render, making it ideal for keeping track of values or DOM elements that do not directly impact the
visual output of the component.

Basic Syntax

Here's how to use useRef:

1. Importing useRef: import { useRef } from 'react';

2. Initialization: const myRef = useRef(initialValue);

3. Accessing Ref: Use myRef.current to access the stored value.

Why is it useful?

useRef provides a way to persist values across renders without triggering re-renders, offering a performance benefit
for certain operations like accessing DOM elements, storing previous state for comparison, or keeping track of values
that don't need to trigger visual updates. It's a critical tool for handling imperatives, such as focus management or
integrating with third-party DOM libraries.

Real World Examples :

1. Form Input Focus: Automatically focus a text input when a component loads.

2. Animation: Keep track of animation frames in a component.

3. Comparing Props: Compare current props with previous ones to decide on rendering logic.
4. Building Custom Element say a custom video player and managing it.

5. Storing interval ids and persist across re-renders.

6. Building custom components like Pin Component above.

Real-world examples or analogies

Consider useRef as a personal notebook that you carry throughout the day. You can jot down notes (values) in it,
refer back to them whenever needed, or even replace them with new notes. The notebook remains the same (the
reference doesn't change), and your actions of writing or reading from it don't announce themselves to the world (do
not cause re-renders).

Code Implementation | Examples

Why not just use useState?

Great question! The main difference between useState and useRef is that useState will cause your component to re-
render when the state changes. useRef doesn't do that. It's like a silent ninja, keeping your value safe without making
a fuss.

Let’s understand with simpler example the working of useRef along with useState

import { useState } from "react";


// useState remembers value though re-renders but
// but it triggers re-renders
const ButtonWithUseState = () => {
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(count + 1);
};
console.log("ButtonWithUseState rendering...");
return (
<div>
<h1>Count : {count}</h1>
<button onClick={handleClick}>BUTTON WITH USE STATE</button>
</div>
);
};

export default ButtonWithUseState;


import { useState, useRef } from "react";
// useRef also remembers value through re-renders;
// but does not trigger re-renders
const ButtonWithUseRef = () => {
let ref = useRef(0);
const [flag, setFlag] = useState(false);

const handleClick = () => {


ref.current = ref.current + 1;
console.log(ref);
};
console.log("ButtonWithUseRef rendering...");
return (
<div>
<h1>Count : {ref.current}</h1>
<button onClick={handleClick}>BUTTON WITH USEREF</button>
<br />
<br />
<button onClick={() => setFlag(!flag)}>{flag ? "TRUE" : "FALSE"}</button>
</div>
);
};
In this example, ref.current holds the count value. When you click the button, handleClick updates ref.current, but it
doesn't cause a re-render. This is useful when you want to keep track of a value without affecting the component's
performance.

useState useRef
Value persists through re-renders Value persists through re-renders
Changing the value triggers a re-render Changing the value does not trigger a re-render
Perfect for storing information that is required for UI Perfect for storing information that is not required directly
Example : Say you want to display count or some for UI Example : Maybe some intervalId you have to store .
data. Storing that data in useState makes more sense. or some subscriptionId or some other id you want to
Reason being when this value changes, the store. This value persists through re-renders and you
component re-renders and in browser you’ll the might be needing to cleanup stuff during
latest value being updated unmount/updates.
Syntax : Initial Declaration :let someRef = Syntax : Initial Declaration :let someState =
useRef( initialValue ) Return value someRef : useState( initialValue ) Return value someState : [ state,
{ current: initialValue }. It returns an object with key setState ] It returns an array with two values. state whose
“current” and value will be the initialValue that you value will be the initalValue and setState which is a
passed inside ref function which updates state value
Immutable - one must use the state setting function Mutable : you can modify the current property manually
to modify state variable
Accessing DOM Elements

useRef can be used to focus an input element on the initial render of a component. For instance:
import { useRef, useEffect } from "react";

function TextInputWithFocus() {
const inputEl = useRef(null);

useEffect(() => {
// Automatically focus the input using the useRef hook
inputEl.current.focus();
}, []);

return <input ref={inputEl} type="text" />;


}
This code snippet demonstrates how to utilize useRef to obtain a reference to an <input> element and then focus on
it as soon as the component mounts.

Storing and Using Values

useRef is also handy for keeping any mutable value around for the lifetime of the component. For example, tracking
the number of times a component has rendered:

import { useRef, useEffect } from "react";

function RenderCounter() {
const renderCount = useRef(0);
useEffect(() => {
// Increment the render count on each render
renderCount.current++;
});
return <h5>Render Count: {renderCount.current}</h5>;

Storing Instance Variables :

Example 1 It can be super helpful if we need to store id of Timer ( Something which we have built previously ). It can
be done this way ( Since the value of ref persists across re-renders )

function startTimer() {
ref.current = setInterval(() => {
// do something
});
}
function stopTimer() {
clearInterval(ref.current);
ref.current = null;
}
Example 2
import { useEffect, useState, useRef } from "react";

function Timer() {
const [count, setCount] = useState(10);
const intervalRef = useRef(null);

useEffect(() => {
const cleanup = () => {
stopTimer();
};
return cleanup;
}, []);

const startTimer = () => {


if (intervalRef.current !== null) {
console.log(`timer is already running`);
return;
}
intervalRef.current = setInterval(() => {
console.log(`timer running`, Date.now());
setCount((prevCount) => {
if (prevCount <= 1) {
clearInterval(intervalRef.current);
}
return prevCount - 1;
});
}, 1000);
};
const stopTimer = () => {
console.log(`timer stopped`);
clearInterval(intervalRef.current);
intervalRef.current = null;
};

const resetTimer = () => {


stopTimer();
setCount(10);
};
return (
<div>
<h6>{count} </h6>
<button onClick={startTimer}>START</button>
<button onClick={stopTimer}>STOP</button>
<button onClick={resetTimer}>RESET</button>
</div>
);
}
useRef to access DOM elements - Some Additional Examples :

Example 1 :

1. useRef hook allows you to keep a mutable value in it’s .current property

2. Create an application wherein you add video element. You do know that can access DOM nodes
with useRef hook. So here in the application as well, please access video DOM notes using this
hook useReflike this

const videoRef = useRef(null)


<video ref={videoRef}></video>
this will set the .currentproperty of videoRefto video DOM node

3. Now you’ll create two buttons PLAY and PAUSE . clicking on PLAY button will call onPlay event handler.
Similarly clicking on PAUSE button will call onPause event handler. This event
handler onPlay and onPause will play and pause the video ( This you will do by accessing the video node and
then HTMLMediaElement: play() method and HTMLMediaElement: pause() method method )

import React from 'react'


import { useRef } from 'react'

const VideoPlay = () => {

const inputEle = useRef(null);

const handlePlay=()=>{
inputEle.current.play();
}
const handlePause=()=>{
inputEle.current.pause()
}

const handleReset=()=>{
inputEle.current.currentTime = 0;
inputEle.current.play();

return (
<div>

<video
ref={inputEle}
content='false'
style={{width: "600px" , border: "1px solid #ccc" }} >
<source
src="https://www.w3schools.com/html/mov_bbb.mp4"
type='video/mp4'/>

</video>

<div>
<button onClick={handlePlay} > Play </button>
<button onClick={handlePause} > Pause </button>
<button onClick={handleReset} > Reset </button>
</div>

</div>
)
}

export default VideoPlay

7. Key Differences Between JavaScript and React:##

React provides a structured way of building UIs compared to vanilla JavaScript, which often involves direct
manipulation of the DOM. React uses a Virtual DOM to efficiently update only parts of the UI that have changed,
while JavaScript directly interacts with the actual DOM, which can be slower and more error-prone. React also
emphasizes declarative code, making it easier to reason about the state of the application.

1. Direct DOM Manipulation vs. Virtual DOM

- Javascript -

// Directly manipulates the DOM element and updates its text content

document.getElementById('myElement').innerText = 'Updated Text';


- React -

// React manages the DOM updates internally, rendering changes efficiently

function MyComponent() {
return <div>Updated Text</div>;
}
2. Handling Side Effects

- Javascript -

// Manages side effects like fetching data directly inside the function

function fetchData() {
// Directly call API and handle response
}
- React -

// useEffect is used to handle side effects in React components

useEffect(() => {
fetchData(); // Fetches data after the component renders
}, []); // Runs once on component mount

Side Effects in React:


Side effects are actions that affect something outside the scope of the function, such as interacting with APIs,
manipulating the DOM, or setting timers. These actions are considered side effects because they go beyond returning
values and influence the program's state or behavior externally. Proper management of side effects is crucial to
maintaining predictable component behavior in React.

- Fetching data from an API

- Setting up subscriptions or event listeners

- Updating the DOM manually

- Timers and intervals

Side effects are managed in React using the useEffect hook, which allows you to perform actions after the component
renders, ensuring side effects are kept separate from rendering logic.

5. Understanding the useEffect Hook:

useEffect is a React hook that lets you perform side effects in function components. It runs after the component
renders and can handle operations like fetching data, setting up subscriptions, and cleaning up resources. By
providing a dependencies array, you can control when the effect runs, ensuring that side effects are executed at the
appropriate times.

Ex

useEffect(() => {
// Side effect code here, e.g., fetching data or updating the DOM
return () => {
// Cleanup code here (optional), runs when the component unmounts or dependencies change
};
}, [dependencies]); // Dependencies array specifies when to re-run the effect

Lifecycle Phases:
React components go through various lifecycle phases, including mounting, updating, and unmounting.
Understanding these phases is crucial for managing component behavior, especially when dealing with side effects,
state changes, and cleanup operations. The useEffect hook allows functional components to mimic these lifecycle
methods, enabling efficient and predictable component management.

Mounting: When a component is being inserted into the DOM (e.g., componentDidMount in class components).

Updating: When a component's state or props change (e.g., componentDidUpdate).

Unmounting: When a component is being removed from the DOM (e.g., componentWillUnmount).

Ex -
import React, { useEffect } from 'react';
function MyComponent() {
useEffect(() => {
console.log('Component did mount'); // Runs once when the component mounts
return () => {
console.log('Component will unmount'); // Runs when the component is about to unmount
};
}, []); // Empty dependencies array ensures it runs only once on mount
return <div>Hello</div>;
}

useEffect and Unmount Phase


Introduction

In React development, effectively managing the lifecycle of components is crucial for optimizing application
performance and preventing memory leaks. This lesson focuses on the unmount phase of component lifecycle and
demonstrates how to use the useEffect hook for cleanup, particularly important for releasing resources and stopping
background activities when components are removed from the UI.

Detailed Explanation

Understanding the Unmount Phase

The unmount phase occurs when a component is removed from the DOM. Similar to turning off unnecessary
appliances when leaving a room, this phase is critical for cleaning up resources allocated by the component, such as
timers, event listeners, or subscriptions.

The Importance of Cleanup in useEffect

React's useEffect hook not only allows us to perform side effects after rendering but also provides a mechanism for
cleanup via a return function. This cleanup function is executed when the component is unmounted, making it an
ideal place to release resources and prevent memory leaks.

Code Implementation | Examples

Example: Timer Component

Consider a countdown timer component that starts counting down from 10 to 0 upon mounting. Without proper
cleanup, the interval set to update the countdown can continue running even after the component is unmounted,
leading to a memory leak.

Initial Timer Component Without Cleanup

// Initial Timer component that leads to memory leak


function Timer() {
useEffect(() => {
setInterval(() => {
console.log(`This code runs every 1 second`, Date.now());
}, 1000);
}, []);
return <h1>Timer</h1>;
}
Observations

Without cleanup, the interval continues to run in the background even after the Timer component is unmounted,
consuming resources unnecessarily and potentially leading to application performance issues.

Implementing Cleanup

To prevent this, we can use a cleanup function in useEffect to clear the interval when the component unmounts:

function Timer() {
useEffect(() => {
const intervalId = setInterval(() => {
console.log(`This code runs every 1 second`, Date.now());
}, 1000);
// Cleanup function
return () => {
clearInterval(intervalId);
};
}, []);
return <h1>Timer</h1>;
}
Why Use Callback Function with setState

Using a callback function with setState (setCount(prevCount => prevCount - 1)) ensures that we always have the
most current state value. This approach helps avoid issues related to stale state, especially in asynchronous
operations like intervals or fetch requests.

Activity: Extending the Timer with Cleanup

In the improved Timer component example, the countdown stops when it reaches 0, and the interval is cleared:

function Timer() {
const [count, setCount] = useState(10);

useEffect(() => {
const intervalId = setInterval(() => {
setCount((prevCount) => {
if (prevCount === 1) {
clearInterval(intervalId);
return prevCount - 1;
}
return prevCount - 1;
});
}, 1000);

return () => clearInterval(intervalId);


}, []);

return (
<div>
<h3>Count: {count}</h3>
</div>
);

Using React and the useEffect hook, create a functional component that fetches and displays a random
joke from an external API (e.g., https://official-joke-api.appspot.com/random_joke).
1. Display the joke in a card format.
2. Add a button labeled "Get Another Joke" that, when clicked, fetches a new joke.
3. Ensure the API call is handled inside useEffect.

import React, { useEffect } from 'react'


import { useState } from 'react'

const RandomJoke = () => {


const [joke,setJoke] = useState(0);
const [FetchJoke, setFetchJoke] = useState([])

const fetchJoke= async()=>{


try {
const res = await fetch("https://official-joke-api.appspot.com/random_joke");
const data = await res.json()
setJoke(data)
} catch (error) {
console.error('Error fetching the joke:', error);
}

useEffect(()=>{
fetchJoke();
},[FetchJoke])

return (
<div className='Container'>
<div className='Container-card'>
{ joke ? (
<>
<h1 className='title'> Random Joke</h1>
<p className='text'><strong>Setup: </strong>{joke.setup}</p>
<p className='text'> <strong> Punchline: </strong> {joke.punchline}</p>
</>
):(
<p> ... Loading</p>
)
}
</div>
<button onClick={()=> setFetchJoke(!FetchJoke)}>Get Another Joke</button>

</div>
)
}

export default RandomJoke

Props Drilling in React


Introduction

In React development, managing state across multiple components is a common challenge. Props drilling and Context
API are two approaches to tackle this issue. This lesson explores these concepts, their relevance, and importance in
efficient React app development.

Detailed Explanation

What is Props Drilling?

Props drilling occurs when you need to pass data from a parent component down to deeply nested child
components, potentially through multiple levels of components that do not need the data themselves. It's like
passing a message down a line of people where only the last person needs to hear it. This approach can quickly
become cumbersome and lead to tightly coupled code that is difficult to maintain.

Why is it a problem?

 Reduces Component Reusability: Components become less generic and harder to reuse in other contexts
because they rely on props passed down from their parents.

 Risk of Missing Props: It's easy to forget to pass props through every level of the component tree, leading to
runtime errors and bugs.

What is Context API?

The Context API provides a way to share values like these between components without having to explicitly pass a
prop through every level of the tree. With Context, you can store "global" data that can be accessed by any
component in the component tree, regardless of how deeply nested it is.
Why is it useful?

 Improves Code Maintainability: By avoiding props drilling, Context API makes your code more maintainable
and the component tree cleaner.

 Enhances Component Reusability: Components can consume context data directly without relying on props
passed from parent components, making them more reusable across different parts of your application.

Code Implementation | Examples

Demonstrating Props Drilling

Imagine a simple component hierarchy where App passes its state down to a BottomMainRight component.

Project Structure :

└── 📁src
└── App.css
└── App.jsx
└── 📁components
└── BottomMain.jsx
└── BottomMainLeft.jsx
└── BottomMainRight.jsx
└── Footer.jsx
└── Main.jsx
└── Navbar.jsx
└── TopMain.jsx
└── index.css
└── main.jsx
Code Implementation :

// App.jsx
import { useState } from "react";
import Navbar from "./components/Navbar";
import Main from "./components/Main";
import Footer from "./components/Footer";
import "./App.css";

function App() {
const isLoggedIn = useState(true);

return (
<>
<Navbar />
<Main isLoggedIn={isLoggedIn} />
<Footer />
</>
);
}

export default App;


// components/Navbar.jsx
function Navbar() {
return <div>Navbar</div>;
}

export default Navbar;


// components/Main.jsx
import TopMain from "./TopMain";
import BottomMain from "./BottomMain";

function Main({ isLoggedIn }) {


return (
<div>
<TopMain />
<BottomMain />
</div>
);
}

export default Main;


// components/TopMain.jsx
function TopMain() {
return <div>TopMain content </div>;
}

export default TopMain;


// components/BottomMain.jsx
import BottomMainLeft from "./BottomMainLeft";
import BottomMainRight from "./BottomMainRight";

function BottomMain() {
return (
<div>
BottomMain
<BottomMainLeft />
<BottomMainRight />
</div>
);
}

export default BottomMain;


// components/BottomMainLeft.jsx
function BottomMainLeft() {
return <div>BottomMainLeft content here </div>;
}

export default BottomMainLeft;


// components/BottomMainRight.jsx
function BottomMainRight() {
return <div>BottomMainRight content here</div>;
}

export default BottomMainRight;


// components/Footer.jsx
function Footer() {
return <div>Footer</div>;
}

export default Footer;


Resources - Official Documentation and Other Resources

 Props Drilling

Exploring these resources will deepen your understanding of props, context, and their roles in React development.

Context API
Introduction

In modern web development, especially with React, managing state and data flow across components can become
complex as applications scale. The Context API in React offers a powerful solution to share data efficiently throughout
the component tree, without resorting to props drilling. This lesson will guide you through setting up and using the
Context API with a focus on managing login states across components.

Detailed Explanation

What is the Context API?

The Context API is a React feature that enables components to share some global data without having to pass props
down manually through every level of the component tree. This approach significantly simplifies data flow and
component structure, especially in large applications.

Why is it useful?

 Simplified Data Flow: By avoiding props drilling, the Context API makes data sharing across components
easier and more direct.

 Enhanced Component Reusability: It decouples components from their parents, making them more modular
and reusable.
 Better Code Maintenance: It makes the codebase cleaner and the data flow within the app more
understandable and easier to debug.

Real-world Examples

 User Authentication State: Managing whether a user is logged in and sharing this state across components
that need to know the user's authentication status.

 Theme Management: Storing the current UI theme settings (e.g., light or dark mode) and applying it across
the entire application.

 Library Integration: Tools like react-router-dom use Context API under the hood to manage routing
information across components.

Benefits

1. Simplified Data Flow: The need for passing props through every level is eliminated, streamlining the process
of data sharing.

2. Enhanced Reusability: Components can be designed to be more generic, fostering reuse.

3. Improved Code Maintenance: The straightforward data flow enhances code readability and ease of
maintenance.

4. Code Implementation | Examples

CPC Methodology: Create - Provide - Consume

Step 1: Create Context

Purpose: To initialize a React Context that will store the global data you want to share.

export const AuthContext = React.createContext();


Step 2: Provide

Purpose: To make the created context available throughout the component tree.

export function AuthContextProvider({ children }) {


const [isLoggedIn, setIsLoggedIn] = React.useState(false);
return (
<AuthContext.Provider value={{ isLoggedIn }}>
{children}
</AuthContext.Provider>
);
}

// In your main entry file (e.g., main.jsx)


import ReactDOM from "react-dom/client";
import App from "./App";
import { AuthContextProvider } from "./context/AuthContextProvider";

ReactDOM.createRoot(document.getElementById("root")).render(
<AuthContextProvider>
<App />
</AuthContextProvider>
);
Step 3: Consume

Purpose: To access and utilize the context data in any component within the provided tree.

function BottomMainLeft() {
const { isLoggedIn } = React.useContext(AuthContext);
// Additional component code
}
Visualizing Data Flow with Context API
The included diagram illustrates how data is seamlessly shared across components using the Context API, bypassing
the constraints of props drilling.

Student Activities

 Implement Theme Context: Create a simple application with the Context API to toggle between light and
dark themes across all components.

 User Authentication Practice: Build a small app that uses the Context API to manage user authentication
state, displaying different UI elements based on the user's login status.

Conclusion

The Context API represents a significant leap forward in React development, offering a streamlined approach to state
management and data sharing. By following the CPC methodology, developers can enhance their applications'
scalability, maintainability, and overall architecture. Engaging with real-world examples and hands-on activities
further solidifies the understanding and application of this powerful API.

Resources

 useContext

 Create Context

These resources offer in-depth knowledge and additional patterns for effectively utilizing the Context API in your
React projects.

Working with Multiple Contexts in React

Introduction

When building complex applications, you might find yourself needing to manage different types of global states, such
as authentication status and UI themes. This lesson covers how to effectively use multiple contexts within a single
React application, using AuthContext for authentication and ThemeContext for theme management as examples.

Detailed Explanation

Step 1: Creating Contexts

1. AuthContext: Manages user authentication status.

 In AuthContextProvider.jsx, create a context using React.createContext().

 Define state to track user authentication status.

2. ThemeContext: Manages the application's theme.

 Similar to AuthContextProvider, create a ThemeContext in ThemeContextProvider.jsx.

 Include state for theme data (like dark or light mode).

Step 2: Providing Contexts

 In App.jsx, wrap your component tree with both AuthContextProvider and ThemeContextProvider.

<AuthContextProvider>
<ThemeContextProvider>
{/* Rest of your app components */}
</ThemeContextProvider>
</AuthContextProvider>
Step 3: Consuming Contexts in Components

 To use contexts in components like Navbar, Main, or Footer:


 Import the contexts.

 Use the useContext hook to access the context values.

 For example, in Navbar.jsx, to access the theme, const theme = useContext(ThemeContext).

Step 4: Updating Context Values

 Context values can be updated using setters provided in the respective context providers.

 For instance, if you want to change the theme in BottomMainRight.jsx:

 Access the setter function from ThemeContext.

 Update the theme on a specific action like a button click.

Student Activities

 Implement a Language Context: Add a third context to manage the language settings of your application.
Allow components to switch between languages, demonstrating the application's internationalization
capability.

 Theme Customization Feature: Extend the ThemeContext to allow users to customize and save their theme
preferences, such as primary colors and font sizes.

Conclusion

Using multiple contexts in a React application enables the efficient management of different global states, such as
user authentication and theme settings. This structured approach not only enhances the application's scalability and
maintainability but also improves overall code readability and component reusability. Following best practices such
as minimizing context values and optimizing through useMemo or useCallback ensures that your application remains
performant.

Resources

 React Official Documentation - Context

 Using Context API in React (Practical Guide)

These resources provide deeper insights into React's Context API and offer practical examples and patterns for
effectively managing global state in large applications.

Chakra UI: A Guide to Installation, Style Props, and Key Components


Introduction

Chakra UI is a popular, modular, and accessible component library for React applications that simplifies the process of
building beautiful and responsive UIs. It provides a set of out-of-the-box components that are both easy to use and
customize, enabling developers to build their applications faster and more efficiently. In this lesson, we'll explore how
to install Chakra UI, utilize its style props for styling components directly, and delve into some of its fundamental
layout components.

Detailed Explanation

What is Chakra UI?

Chakra UI is a front-end framework that offers a collection of simple, modular, and accessible React components.
Designed with ease of use and flexibility in mind, it allows developers to create engaging user interfaces with minimal
effort.

Why is it useful?
Chakra UI is built with accessibility in mind, ensuring that applications are accessible to as many people as possible.
Its style props system enables developers to style components directly with props, streamlining the development
process. Furthermore, its component library covers a wide range of UI needs, from simple layout components to
complex interactive elements, making it a versatile tool for developers.

Real-world examples or analogies

Think of Chakra UI as the Lego set of the React world. Just as Legos allow you to build complex structures with
simple, interlocking pieces, Chakra UI provides the building blocks for creating complex UIs with simple, composable
components.

Code Implementation | Examples

Installation and Setup

1. Installation: Start by adding Chakra UI to your React project with npm or yarn:

npm install @chakra-ui/react @emotion/react @emotion/styled framer-motion

# or

yarn add @chakra-ui/react @emotion/react @emotion/styled framer-motion

2. Setup: Wrap your application with the ChakraProvider at the root level to enable Chakra UI throughout your
app.

import { ChakraProvider } from "@chakra-ui/react";


import App from "./App";

const Root = () => (


<ChakraProvider>
<App />
</ChakraProvider>
);
export default Root;
Reference : https://chakra-ui.com/getting-started

Some Important Components

Layout Components :

These components simplify the process of building responsive layouts in React applications. They leverage the power
of Flexbox and CSS Grid with an easy-to-use API, enabling developers to quickly create complex layouts that are both
responsive and accessible. By abstracting away the traditional complexities of CSS, Chakra UI's layout components
allow developers to focus more on functionality rather than styling.

Box

Box: The foundation of all Chakra UI layout components, acting as a div with access to style props. It's used for
wrapping elements and applying basic styles like padding, margin, colors, and more.

Box Component Example

A simple Box to create a container with padding, background color, and text color:

<Box p="4" bg="gray.200" color="black">


This is a basic Box component.
</Box>
https://chakra-ui.com/docs/components/box/usage

Flex

Flex: A Box component with display: flex style applied. It's used for creating flexible layouts and aligning items both
horizontally and vertically, offering control over spacing, alignment, and distribution of child elements.
Flex Component Example

Creating a navbar layout using Flex to align items center and space them evenly:

<Flex align="center" justify="space-between" p="4" shadow="md" bg="purple.500">


<Text>Logo</Text>
<HStack spacing="24px">
<Button colorScheme="teal">Home</Button>
<Button colorScheme="teal">About</Button>
<Button colorScheme="teal">Contact</Button>
</HStack>
</Flex>
https://chakra-ui.com/docs/components/flex/usage

Grid

Grid: An extension of the Box component with display: grid. It allows for more complex layouts compared to Flex,
providing capabilities for defining grid columns, rows, gaps, and areas.

Grid Component Example

Constructing a product grid layout:


<Grid templateColumns="repeat(3, 1fr)" gap={6}> {products.map((product) => (
<Box w="100%" h="10" bg="blue.500"> {product.name}
</Box> ))}
</Grid>

</Grid>

https://chakra-ui.com/docs/components/grid/usage

Stack
Stack: A higher-level component built on top of the Flex component. It's designed to make it easier to stack elements
vertically or horizontally with consistent spacing, without needing to manually manage margins or paddings.

Stack Component Example

Creating a form layout with evenly spaced fields:

<Stack spacing={4}>
<Input placeholder="Your Name" />
<Input placeholder="Your Email" />
<Button colorScheme="blue">Submit</Button>
</Stack>
https://chakra-ui.com/docs/components/stack/usage

Form Components

These form components are designed with usability and accessibility in mind, ensuring that form elements are easy
for users to interact with, regardless of their device or assistive technologies they may use. By utilizing Chakra UI's
form components, developers can quickly implement forms that are both functional and aesthetically pleasing, with
minimal effort required for customization and styling.

Overview of Form Components

Why are They Useful?

These form components are designed with usability and accessibility in mind, ensuring that form elements are easy
for users to interact with, regardless of their device or assistive technologies they may use. By utilizing Chakra UI's
form components, developers can quickly implement forms that are both functional and aesthetically pleasing, with
minimal effort required for customization and styling.

Input Component Example


 Input: Used for text input fields. Chakra UI's Input component is versatile, supporting various types such as
text, password, email, and more.

Creating a simple text input field:

<Input placeholder="Enter your name" size="md" />

https://chakra-ui.com/docs/components/input/usage

Button Component Example

 Button: A crucial component for submitting forms or triggering actions. Chakra UI buttons can be customized
in terms of size, color, and functionality.

A submit button with custom color scheme:

<Button colorScheme="blue" size="lg" onClick={handleSubmit}>


Submit
</Button>
https://chakra-ui.com/docs/components/button/usage

Select Component Example

 Select: Allows users to choose from a dropdown list of options. This component is essential for forms where
users must select from predefined options.

Dropdown select for choosing a favorite color:


<Select placeholder="Select your favorite color">
<option value="red">Red</option>
<option value="green">Green</option>
<option value="blue">Blue</option>
</Select>
https://chakra-ui.com/docs/components/select/usage

Radio Component Example

 Radio: Enables selection among a group of options. Only one option can be selected at a time, making it ideal
for mutually exclusive choices.

Group of radio buttons for selecting a payment method:

function RadioExample() {
const [value, setValue] = React.useState("1");
return (
<RadioGroup onChange={setValue} value={value}>
<Stack direction="row">
<Radio value="1">First</Radio>
<Radio value="2">Second</Radio>
<Radio value="3">Third</Radio>
</Stack>
</RadioGroup>
);
}
https://chakra-ui.com/docs/components/radio/usage

Checkbox Component Example

 Checkbox: Used for selections where multiple choices are allowed. Checkboxes are perfect for options that
can be combined or applied independently.

Checkboxes for selecting interests:

<Checkbox defaultChecked>Checkbox</Checkbox>
https://chakra-ui.com/docs/components/checkbox/usage
Overlay Components

Modal

A modal is a dialog that focuses the user's attention exclusively on an information via a window that is overlaid on
primary content.

function BasicUsage() {
const { isOpen, onOpen, onClose } = useDisclosure();
return (
<>
<Button onClick={onOpen}>Open Modal</Button>

<Modal isOpen={isOpen} onClose={onClose}>


<ModalOverlay />
<ModalContent>
<ModalHeader>Modal Title</ModalHeader>
<ModalCloseButton />
<ModalBody>
<Lorem count={2} />
</ModalBody>

<ModalFooter>
<Button colorScheme="blue" mr={3} onClick={onClose}>
Close
</Button>
<Button variant="ghost">Secondary Action</Button>
</ModalFooter>
</ModalContent>
</Modal>
</>
);
}
Reference : https://chakra-ui.com/docs/components/modal/usage

useReducer
What is useReducer?

useReducer is a React Hook used to manage complex state logic by reducing state updates to a predictable flow using
a reducer function.

Key Components

1. State: The current state value.

2. Reducer Function: A function that takes the current state and an action, and returns the new state.

3. Dispatch: A function to trigger state updates by dispatching actions.

Syntax

const [state, dispatch] = useReducer(reducer, initialState);


 reducer: A pure function that determines the next state.

 initialState: The starting state.

Example: Counter Application

function reducer(state, action) {


switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
throw new Error(`Unknown action type: ${action.type}`);
}
}

function Counter() {
const [state, dispatch] = useReducer(reducer, { count: 0 });

return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
<button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>
</div>
);
}

What is an Action?

An action is a plain JavaScript object that describes what should be done to update the state.

Structure of an Action

const action = {
type: 'ACTION_TYPE',
payload: { /* additional data */ }
};
 type (required): A string describing the action.

 payload (optional): Additional data required for the update.

Example: Adding a To-Do

const action = {
type: 'add_todo',
payload: { id: 1, text: 'Learn React' },
};

What is dispatch?

The dispatch function is used to send an action to the reducer function. It triggers a state update by invoking the
reducer.

How dispatch Works

1. Sends an action to the reducer.

2. The reducer processes the action and returns the updated state.

3. React re-renders the component with the new state.

Syntax

dispatch(action);

Example: Counter

<button onClick={() => dispatch({ type: 'increment' })}>Increment</button>


<button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>

What is a Reducer?

A reducer is a pure function that determines the next state based on the current state and an action.

Key Characteristics
 It must not mutate the state.

 Always return a new state.

Structure

function reducer(state, action) {


switch (action.type) {
case 'ACTION_TYPE_1':
return /* updated state */;
case 'ACTION_TYPE_2':
return /* updated state */;
default:
throw new Error(`Unknown action type: ${action.type}`);
}
}
Actions with Payload

Purpose of payload

 The payload contains additional data required to process the action.

 Example: Adding or removing an item from a list.

To-Do Example

function reducer(state, action) {


switch (action.type) {
case 'add_todo':
return [...state, action.payload];
case 'remove_todo':
return state.filter(todo => todo.id !== action.payload);
default:
throw new Error(`Unknown action type: ${action.type}`);
}
}
Dispatching Actions
dispatch({ type: 'add_todo', payload: { id: 1, text: 'Learn React' } });
dispatch({ type: 'remove_todo', payload: 1 });

useState vs useReducer

Feature useState useReducer


Complexity Simple state logic Complex state logic
State Update Direct setter function Dispatch actions through a reducer
Multiple State Multiple useState calls Single reducer manages all fields
Fields
Initialization Simple initial value Can use lazy initialization
Use-case & Benefits

 Complex State Logic: Optimal for situations demanding intricate state logic or multiple state dependencies.

 Predictable State Transitions: The dispatch-action framework ensures clear, predictable state updates.

 Scalable State Management: As application complexity increases, useReducer maintains orderly and
manageable state architecture.

Code Implementation | Examples

Example 1: Counter Application

The transition from using useState to useReducer in a Counter application serves as a prime example
of useReducer's structured state management capabilities.

Counter with useReducer:


import { useReducer } from "react";

const reducer = (state, action) => {


switch (action.type) {
case "INCREMENT_COUNT":
return state + 1;
case "DECREMENT_COUNT":
return state - 1;
default:
throw new Error(`Action type is invalid`);
}
};

function Counter2() {
const [state, dispatch] = useReducer(reducer, 0);

const handleIncrement = () => dispatch({ type: "INCREMENT_COUNT" });


const handleDecrement = () => dispatch({ type: "DECREMENT_COUNT" });

return (
<>
<h1>Counter: {state}</h1>
<button onClick={handleIncrement}>INCREMENT</button>
<button onClick={handleDecrement}>DECREMENT</button>
</>
);
}

export { Counter2 };

 The state is initialized as { count: 0 }.


 dispatch sends actions like { type: 'increment' } to the reducer.
 The reducer function updates the state based on the type of the action.

Example 2 : Implementing useReducer for API Fetching

Transforming a data-fetching operation from useState to useReducer exemplifies managing related state variables
(loading, data, err) more cohesively:

import { useEffect, useReducer } from "react";

const getData = async (url) => {


try {
let res = await fetch(url);
let data = await res.json();
return data;
} catch {
throw new Error(`Something went wrong while fetching data`);
}
};

const initState = {
loading: false,
data: [],
err: false,
};

const reducer = (state, action) => {


switch (action.type) {
case "FETCH_LOADING":
return { loading: true, err: false, data: [] };
case "FETCH_SUCCESS":
return { loading: false, data: action.payload, err: false };
case "FETCH_ERROR":
return { loading: false, err: true, data: [] };
default:
throw new Error(`Action type is invalid`);
}
};

export default function App() {


const [state, dispatch] = useReducer(reducer, initState);

const fetchAndUpdateData = (url) => {


dispatch({ type: "FETCH_LOADING" });
getData(url)
.then((res) => dispatch({ type: "FETCH_SUCCESS", payload: res }))
.catch(() => dispatch({ type: "FETCH_ERROR" }));
};

useEffect(() => {
fetchAndUpdateData(`https://jsonplaceholder.typicode.com/posts?_limit=10`);
}, []);

const { loading, err, data } = state;

return loading ? (
<h1>Loading..</h1> ) : err ? (
<h1>Something went wrong</h1> ) : (
<div className="App">
{data.map((post) => (
<p key={post.id}>
{post.id} - {post.title}
</p> ))}
</div> );
}

You might also like