KEMBAR78
Unit 2 Fundamentals of React | PDF | Document Object Model | Computer Programming
0% found this document useful (0 votes)
50 views80 pages

Unit 2 Fundamentals of React

Unit 2 covers the fundamentals of React.js, including its concepts, class components, forms, and hooks. It highlights the benefits of using React, such as its component-based architecture and performance optimization through the virtual DOM. The unit also provides practical examples of creating components and organizing them within a React application.

Uploaded by

rushabhkansara16
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)
50 views80 pages

Unit 2 Fundamentals of React

Unit 2 covers the fundamentals of React.js, including its concepts, class components, forms, and hooks. It highlights the benefits of using React, such as its component-based architecture and performance optimization through the virtual DOM. The unit also provides practical examples of creating components and organizing them within a React application.

Uploaded by

rushabhkansara16
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/ 80

UNIT 2 : FUNDAMENTALS OF REACT.

JS

Unit 2: Fundamentals of React.js

2.1 Overview of React


2.1.1 Concepts of React.
2.1.2 Using React with HTML
2.1.3 React Interactive components: Components within components and Files
2.1.3 Passing data through Props
2.2 Class components
2.2.1 React class and class components
2.2.2 Conditional statements, Operators, Lists
2.2.3 React Events: Adding events, Passing arguments, Event objects
2.3 Forms: (Adding forms, Handling forms, Submitting forms)
2.3.1 event.target.name and event.Target.event, React Memo
2.3.2 Components (TextArea, Drop down list (SELECT))
2.4 Hooks: Concepts and Advantages
2.4.1 useState, useEffect, useContext
2.4.2 useRef, useReducer, useCallback, useMemo
2.4.3 Hook: Building custom hook, advantages and use
----------------------------------------------------------------------------------------------------------------

2.1 Overview of React :


React, also known as React.js or ReactJS, is a front-end JavaScript library developed by Facebook for
building dynamic and interactive user interfaces (UIs). It simplifies UI development by focusing on the
view layer and employing a component-based architecture.

React is an open source, JavaScript library for developing user interface (UI) in web application. React
is developed and released by Facebook. Facebook is continuously working on the React library and
enhancing it by fixing bugs and introducing new features.

ReactJS is a simple, feature rich, component based JavaScript UI library. It can be used to develop small
applications as well as big, complex applications. ReactJS provides minimal and solid feature set to
kick-start a web application. React community compliments React library by providing large set of
ready-made components to develop web application in a record time. React community also provides
advanced concept like state management, routing, etc., on top of the React library.

Features:
The salient features of React library are as follows −
• Solid base architecture
• Extensible architecture
• Component-based library
• JSX-based design architecture
• Declarative UI library

Benefits :
MS. ESHA VINAY PATEL 1
UNIT 2 : FUNDAMENTALS OF REACT.JS

A few benefits of using the React library are as follows −


• Easy to learn
• Easy to adapt to modern as well as legacy applications
• A faster way to code a functionality
• Availability of a large number of ready-made components
• Large and active community

Applications :
Few popular websites powered by React library are listed below –

• Facebook, popular social media application


• Instagram, popular photo sharing application
• Netflix, popular media streaming application
• Code Academy, popular online training application
• Reddit, popular content sharing application

Why learn ReactJS?


• Today, many JavaScript frameworks are available in the market(like angular, node), but still,
React came into the market and gained popularity amongst them. The previous frameworks
follow the traditional data flow structure, which uses the DOM (Document Object Model).
DOM is an object which is created by the browser each time a web page is loaded. It
dynamically adds or removes the data at the back end and when any modifications were done,
then each time a new DOM is created for the same page. This repeated creation of DOM makes
unnecessary memory wastage and reduces the performance of the application.
• Therefore, a new technology ReactJS framework invented which remove this drawback.
ReactJS allows you to divide your entire application into various components. ReactJS still
used the same traditional data flow, but it is not directly operating on the browser's Document
Object Model (DOM) immediately; instead, it operates on a virtual DOM. It means rather than
manipulating the document in a browser after changes to our data, it resolves changes on a
DOM built and run entirely in memory. After the virtual DOM has been updated, React
determines what changes made to the actual browser's DOM. The React Virtual DOM exists
entirely in memory and is a representation of the web browser's DOM. Due to this, when we
write a React component, we did not write directly to the DOM; instead, we are writing virtual
components that react will turn into the DOM.

MS. ESHA VINAY PATEL 2


UNIT 2 : FUNDAMENTALS OF REACT.JS

2.1.1 Concepts of React :

 Components: Components are reusable and independent UI building blocks, from


simple elements to complex forms. They create a modular and hierarchical structure in
React applications.

 JSX (JavaScript XML): JSX is a syntax extension that allows HTML-like code within
JavaScript for readability. React transforms JSX into JavaScript calls that create and
manage DOM elements.

 Virtual DOM: React uses a Virtual DOM, a lightweight copy of the real DOM, to
optimize rendering. Updates are first applied to the Virtual DOM. React efficiently
calculates and updates only the necessary parts of the actual DOM, improving
performance.

 Props: Props (properties) are read-only inputs passed from parent to child components
for data flow and reusability. This illustrates one-way data flow from parent to child.

 State: State is a mutable JavaScript object within a component that allows it to manage
and update its data. State updates trigger re-renders of the element.

 Lifecycle Methods (for Class Components): Class components have a lifecycle with
phases (Mounting, Updating, and Unmounting) where specific methods can be used to
perform actions.
 Hooks (for Functional Components): Introduced in React 16.8, Hooks allow functional
components to use state ( useState ) and side effects ( useEffect ) without being class
components, improving code readability.

2.1.2 Using React with HTML :

Simple React in an HTML File (Using CDN)


Here's an example HTML file where React renders content inside a <div>:

xml
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>React with HTML Example</title>
<!-- React and ReactDOM libraries from CDN -->
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<!-- Babel for JSX support -->
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>

MS. ESHA VINAY PATEL 3


UNIT 2 : FUNDAMENTALS OF REACT.JS

<body>
<!-- Container for React -->
<div id="root"></div>

<script type="text/babel">
// React component returning JSX (like HTML)
function App() {
return (
<div>
<h1>Hello from React!</h1>
<p>This paragraph is rendered by React inside an HTML page.</p>
</div>
);
}

const rootElement = document.getElementById('root');


ReactDOM.createRoot(rootElement).render(<App />);
</script>
</body>
</html>

 React renders the App component inside the #root div.


 This method is good for demos or adding React to existing HTML pages.

How to Start a React Project Using Create React App


For real projects, you typically want a better development setup than just CDN scripts.
The official and easy way is to use Create React App (CRA), a CLI tool that sets up
everything (build, bundling, live reload) for you.

Prerequisites
 Install Node.js (version 14 or higher) from nodejs.org.
 Node includes npm (node package manager) which you use to run commands.

Steps to Create a React Project


1. Open a terminal or command prompt.
2. Run the following command:

bash
npx create-react-app my-app

o npx lets you run the CRA tool without installing it globally.
o my-app is your project folder name (you can change it).
3. Navigate into the project directory:

bash
cd my-app

4. Start the development server with:

MS. ESHA VINAY PATEL 4


UNIT 2 : FUNDAMENTALS OF REACT.JS

bash
npm start

o This opens http://localhost:3000 in your browser.


o It reloads automatically as you edit files.

What Happens?
 CRA creates a folder with your project and installs dependencies.
 You get a working React application with a main component in src/App.js.
 You can modify src/App.js to change your app.

Example src/App.js:
jsx
import React from 'react';

function App() {
return (
<div>
<h1>Hello, React App!</h1>
<p>Welcome to your new React project.</p>
</div>
);
}

export default App;

EXAMPLE: “print “hello world” using class component


and functional component”

Step 1: Create a React Project Using Create React App


If you haven't already created your React project, run:

bash
npx create-react-app my-app
cd my-app
npm start

This will start the development server and open your app in the browser.

Step 2: Create Class and Functional Components

1. Functional Component Example


Create or edit src/FunctionalComponent.js:

MS. ESHA VINAY PATEL 5


UNIT 2 : FUNDAMENTALS OF REACT.JS

jsx
import React from 'react';

function FunctionalComponent() {
return (
<div>
<h1>Hello World from Functional Component!</h1>
<p>This is a functional React component.</p>
</div>
);
}

export default FunctionalComponent;

2. Class Component Example


Create or edit src/ClassComponent.js:

jsx
import React, { Component } from 'react';

class ClassComponent extends Component {


render() {
return (
<div>
<h1>Hello World from Class Component!</h1>
<p>This is a class-based React component.</p>
</div>
);
}
}

export default ClassComponent;

Step 3: Use the Components in App.js


Edit src/App.js like this to import and render both components:

jsx
import React from 'react';
import FunctionalComponent from './FunctionalComponent';
import ClassComponent from './ClassComponent';

function App() {
return (
<div>
<FunctionalComponent />
<ClassComponent />
</div>
);
}

export default App;

MS. ESHA VINAY PATEL 6


UNIT 2 : FUNDAMENTALS OF REACT.JS

Summary
Component Type Syntax Notes
Functional Simpler syntax, recommended in
Function returning JSX
Component modern React
Class extending React.Component with Older style, supports state &
Class Component
render() method lifecycle

Bonus: Running the Project


After adding these files and code:

 Run npm start in your project directory.


 Your browser will open and show both the Functional and Class component
messages.

Summary Table for React Usage Options


Setup Type Approach Suitable for
Add React & ReactDOM scripts + Babel in Quick demos, learning, legacy
CDN in HTML
HTML sites
Create React Full projects, modern
npx create-react-app my-app
App development

MS. ESHA VINAY PATEL 7


UNIT 2 : FUNDAMENTALS OF REACT.JS

2.1.3 React Interactive components:


Components within components and Files

1. What Are Nested Components in React?


Nested components (also called child components) are components rendered inside other
components. This is a core concept of component composition in React, allowing you to
build complex, modular, and maintainable user interfaces by assembling UI pieces like
building blocks.

 The parent component renders one or more child components inside its JSX.
 Child components can themselves contain further nested components, enabling
deep, hierarchical UI structures.
 React’s design encourages composition (combining components) rather than
inheritance.

2. Why Use Nested Components?


 Modularity: Break UI into reusable, isolated pieces.
 Code Reusability: Share and reuse components across the app.
 Separation of Concerns: Each component handles its own logic and rendering.
 Maintainability: Smaller components are easier to manage and test.
 Reusability with Customization: Pass props to children to customize behavior.

3. Basic Example of Nested Components


Child Component (Child.js):

jsx
import React from 'react';

function Child() {
return <div>This is the Child Component</div>;
}

export default Child;

Parent Component (Parent.js):

jsx
import React from 'react';
import Child from './Child'; // Import child component

function Parent() {
return (
<div>

MS. ESHA VINAY PATEL 8


UNIT 2 : FUNDAMENTALS OF REACT.JS

<h2>Parent Component</h2>
<Child /> {/* Use (render) Child inside Parent */}
</div>
);
}

export default Parent;

App Component (App.js):

jsx
import React from 'react';
import Parent from './Parent';

function App() {
return (
<div>
<h1>Nested Components Example</h1>
<Parent />
</div>
);
}

export default App;

In this setup:

 App renders Parent,


 Parent renders Child.

4. Passing Data Between Parent and Child Using Props


Props are how data and configuration flow down from parent to child.

In Parent.js:

jsx
function Parent() {
const message = "Hello from Parent!";

return (
<div>
<Child greeting={message} />
</div>
);
}

In Child.js:

jsx
function Child(props) {
return <div>Message from parent: {props.greeting}</div>;
}

MS. ESHA VINAY PATEL 9


UNIT 2 : FUNDAMENTALS OF REACT.JS

This demonstrates:

 Parent passes a string prop greeting to the child.


 Child renders the message using props.greeting.

5. Rendering Lists of Nested Components Dynamically


You can render multiple child components dynamically using JavaScript map() over an
array of data—a common and powerful pattern.

ListParent.js:

jsx
import React from 'react';
import ListItem from './ListItem';

const fruits = ["Apple", "Banana", "Cherry"];

function ListParent() {
return (
<ul>
{fruits.map((fruit, index) => (
<ListItem key={index} name={fruit} />
))}
</ul>
);
}

export default ListParent;

ListItem.js:

jsx
import React from 'react';

function ListItem({ name }) {


return <li>{name}</li>;
}

export default ListItem;

Key points here:

 Use key props on list items to help React track item identity for efficient updates.
 Child components receive relevant data via props dynamically.

6. Organizing Components in Multiple Files & Folders


As your React app grows, keep your components organized:

text
/src
/components

MS. ESHA VINAY PATEL 10


UNIT 2 : FUNDAMENTALS OF REACT.JS

Child.js
Parent.js
ListItem.js
ListParent.js
App.js
index.js

 Each file exports one component (default export recommended).


 Components import their dependencies relatively (import Child from './Child').
 Clear folder structure improves scalability and maintainability.

7. Advanced: Recursive or Deeply Nested Components


Sometimes data is nested recursively (e.g., tree menus). React components can render
themselves to handle nested data of arbitrary depth.

Example for recursive nested menu items:

jsx
function MenuItem({ item }) {
return (
<li>
{item.label}
{item.children && item.children.length > 0 && (
<ul>
{item.children.map((child) => (
<MenuItem key={child.label} item={child} />
))}
</ul>
)}
</li>
);
}

This allows a component to nest any number of children dynamically, recursively.

8. Interactivity: Managing State in Nested Components


Components can maintain their own state (using useState hook) and handle user events.

Example: Counter component

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

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

return (
<div>
<p>Clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click Me</button>
</div>

MS. ESHA VINAY PATEL 11


UNIT 2 : FUNDAMENTALS OF REACT.JS

);
}

You can use this inside a parent component naturally:

jsx
function Parent() {
return (
<div>
<Counter />
<Counter />
</div>
);
}

Each Counter maintains its own independent state.

9. Best Practices and Tips for Nested Components


 Keep components focused: Each component should have a single responsibility.
 Use props to communicate down, callbacks to communicate up: Pass functions
as props to allow children to communicate events.
 Don’t over-nest: Deep component trees are fine but avoid unnecessary
complexity.
 Use keys properly: Always add unique keys when rendering lists.
 Modularize your file structure: Group related components in folders.

10. Summary Table of React Nested Components


Concepts
Aspect Explanation Example/Notes
Nested Components Components inside other components Parent renders Child
Props Data/parameters passed from parent to child <Child greeting="Hi" />
Mapping fruits to <ListItem
Dynamic Lists Use .map() to render array of components
/>
Multi-file
Each component in its own file, imported /components/Child.js
Organization
Recursive Recursive MenuItem
Component rendering itself for tree-like data
Components example
Components can manage own state and handle
State & Events useState and onClick
events
Keys Unique keys in lists for React's reconciliation Use stable ID or index

MS. ESHA VINAY PATEL 12


UNIT 2 : FUNDAMENTALS OF REACT.JS

2.1.4 Passing data through Props

Understanding Props in React


 Props (short for properties) are used to pass data down from a parent
component to child components.
 Props are read-only inside the child components — they cannot be
modified there.
 Data flow is unidirectional: from parent → child.
 Props can be any data type: strings, numbers, arrays, objects, functions,
etc.
 Passing functions as props allows child components to trigger actions in
the parent (callback pattern).

Detailed Example Components


Functional Components with Props
 Functional components receive props as function parameters.
jsx
// ChildFunctional.js
import React from 'react';

function ChildFunctional(props) {
return (
<div>
<h3>Child Functional Component</h3>
<p>Greeting: {props.greeting}</p>
<p>Number: {props.number}</p>
<button onClick={props.onButtonClick}>Click Me (Functional)</button>
</div>
);
}

export default ChildFunctional;

Class Components with Props


 Class components access props via this.props.
jsx
// ChildClass.js
import React, { Component } from 'react';

class ChildClass extends Component {

MS. ESHA VINAY PATEL 13


UNIT 2 : FUNDAMENTALS OF REACT.JS

render() {
return (
<div>
<h3>Child Class Component</h3>
<p>Greeting: {this.props.greeting}</p>
<p>Number: {this.props.number}</p>
<button onClick={this.props.onButtonClick}>Click Me (Class)</button>
</div>
);
}
}

export default ChildClass;

Parent Component Passing Data & Functions to


Children
In this example, the parent will pass:
 A string greeting
 A number number
 A function onButtonClick that children can invoke on button click
jsx
// Parent.js
import React from 'react';
import ChildFunctional from './ChildFunctional';
import ChildClass from './ChildClass';

function Parent() {
const greetMessage = "Hello from Parent!";
const numberValue = 123;

const handleButtonClick = () => {


alert('Button clicked inside child!');
};

return (
<div>
<h2>Parent Component</h2>

{/* Passing props to functional child */}


<ChildFunctional
greeting={greetMessage}
number={numberValue}
onButtonClick={handleButtonClick}
/>

{/* Passing props to class child */}


<ChildClass
greeting={greetMessage}

MS. ESHA VINAY PATEL 14


UNIT 2 : FUNDAMENTALS OF REACT.JS

number={numberValue}
onButtonClick={handleButtonClick}
/>
</div>
);
}

export default Parent;

Full App.js File Using Create React App


This App.js file imports the Parent component and renders it. It is the entry
point for rendering your application UI.
jsx
// src/App.js
import React from 'react';
import Parent from './Parent';

function App() {
return (
<div className="App" style={{ padding: '20px', fontFamily: 'Arial, sans-serif' }}>
<h1>React Props Passing Example</h1>
<Parent />
</div>
);
}

export default App;

Folder Structure Recommendation


To keep things organized in your React project, structure your component
files like this inside src/:
text
src/
App.js
Parent.js
ChildFunctional.js
ChildClass.js
index.js
 is usually the ReactDOM render entry point.
index.js
 Each component is in its own file.
 Import statements use relative paths, e.g., import ChildClass from './ChildClass'

How to Run This in Create React App


1. Create a React app if you haven’t yet:

MS. ESHA VINAY PATEL 15


UNIT 2 : FUNDAMENTALS OF REACT.JS

bash
npx create-react-app my-app
cd my-app
2. Inside src/, create these files:
 App.js (replace the existing one with the above code)
 Parent.js (add the parent component code)
 ChildFunctional.js (add functional child code)
 ChildClass.js (add class child code)
3. Start the app in development mode:
bash
npm start
4. Open http://localhost:3000 in your browser to see the result:
 You will see the parent and both children rendered.
 Clicking either child's button will trigger an alert showing the passed
callback function is working correctly.

Summary of Key Points


Concept Functional Component Class Component Usage
Usage

Define component function Child(props) {...} class Child extends Component

Access props props.propName this.props.propName

Pass props from


parent <Child greeting="Hi" /> <Child greeting="Hi" />

Pass functions as
props <Child onButtonClick={func} /> <Child onButtonClick={func} />

Invoke callback in
child onClick={props.onButtonClick} onClick={this.props.onButtonClick}

MS. ESHA VINAY PATEL 16


UNIT 2 : FUNDAMENTALS OF REACT.JS

2.2 Class components

2.2.1 React class and class components :


Class components in React are one of the two main ways to define components (the other
being functional components). They are ES6 JavaScript classes that extend from
React.Component and provide built-in features like state management and lifecycle methods.
While functional components have become more popular due to React Hooks, class
components remain important, especially for understanding React’s history and some specific
use cases.

Here’s a detailed overview of React class components along with key features, syntax,
differences from functional components, and examples:

What Are React Class Components?


 Class components are JavaScript classes that extend React.Component.
 They must define a render() method that returns JSX (the UI structure).
 They can hold internal state using this.state and manage it with this.setState().
 They provide access to lifecycle methods such as componentDidMount(),
componentDidUpdate(), and componentWillUnmount().
 Props are accessed via this.props.

Basic Syntax of a Class Component


jsx
import React, { Component } from 'react';

class MyComponent extends Component {


constructor(props) {
super(props); // Required to access this.props

// Initialize state
this.state = {
count: 0,
};

// Bind event handlers if not using arrow functions


this.handleClick = this.handleClick.bind(this);
}

// Event handler
handleClick() {
this.setState({ count: this.state.count + 1 });
}

// Lifecycle method (optional)


componentDidMount() {
console.log('Component mounted!');
}

MS. ESHA VINAY PATEL 17


UNIT 2 : FUNDAMENTALS OF REACT.JS

// Render method required


render() {
return (
<div>
<h1>Class Component Example</h1>
<p>Count: {this.state.count}</p>
<button onClick={this.handleClick}>Increment</button>
</div>
);
}
}

export default MyComponent;

Key Points:
 constructor(props) initializes state and binds methods (necessary in older React or non-
arrow functions).
 render() returns the JSX UI.
 state is an object holding the component’s internal, mutable data.
 this.setState() updates state and triggers re-render.
 Lifecycle methods let you perform actions when the component mounts, updates, or
unmounts.

React Class Component Features


Feature Description
Internal component data that can change over time. Managed with this.state and
State
this.setState().

Lifecycle Hooks to run code at key stages: mounting, updating, unmounting. E.g.,
Methods componentDidMount(), componentDidUpdate(), componentWillUnmount().

Event
Methods written as class functions, need binding if not arrow functions.
Handling
Props Access Via this.props, read-only data passed from parent.
Render
A mandatory method returning JSX for UI display.
Method

Comparing Class Components and Functional


Components
Aspect Class Components Functional Components
Class extending React.Component with render()
Syntax Plain function returning JSX
method

MS. ESHA VINAY PATEL 18


UNIT 2 : FUNDAMENTALS OF REACT.JS

Aspect Class Components Functional Components


State
this.state and this.setState() Use React hooks like useState()
Management
Lifecycle
Methods like componentDidMount() Use useEffect() hook
Methods
Event Binding May require explicit binding Use arrow functions or hooks
Complexity More verbose and boilerplate Simpler, more concise
Typically preferred for modern
Performance Slightly less due to older React methods
React
Use Case Legacy codebases, certain patterns Modern React with hooks

Example: Class Component Printing "Hello World"


jsx
import React, { Component } from 'react';

class HelloWorldClass extends Component {


render() {
return <h1>Hello World from Class Component!</h1>;
}
}

export default HelloWorldClass;

Example: Class Component with Props and State


jsx
import React, { Component } from 'react';

class Counter extends Component {


state = { count: 0 };

increment = () => {
this.setState({ count: this.state.count + 1 });
};

render() {
return (
<div>
<h2>{this.props.title}</h2>
<p>Count: {this.state.count}</p>
<button onClick={this.increment}>Increment</button>
</div>
);
}
}

export default Counter;

MS. ESHA VINAY PATEL 19


UNIT 2 : FUNDAMENTALS OF REACT.JS

Using Class Components in Create React App


In a React app created with Create React App, your src/App.js can import and use class
components like this:

jsx
import React from 'react';
import HelloWorldClass from './HelloWorldClass';
import Counter from './Counter';

function App() {
return (
<div>
<HelloWorldClass />
<Counter title="Counter Example" />
</div>
);
}

export default App;

Summary
 Class components are ES6 classes extending React.Component.
 They must include a render method that returns JSX.
 Support state and lifecycle methods inherently.
 Use this.props for props and this.state for internal mutable data.
 Often more verbose but important for understanding React’s foundational model.
 Functional components with hooks have largely superseded class components in
modern React.

MS. ESHA VINAY PATEL 20


UNIT 2 : FUNDAMENTALS OF REACT.JS

2.2.2 Conditional statements, Operators, Lists:

1. Conditional Statements and Rendering in


React
React allows you to display or hide elements, choose between
components, or render different content based on conditions, just like you
do in regular JavaScript.

Ways to Write Conditional Rendering


1.1 if Statements
Use if outside or inside the render method (or functional return) to decide
what to render.

Example (Functional Component):


jsx
function Greeting(props) {
const isLoggedIn = props.isLoggedIn;

if (isLoggedIn) {
return <h1>Welcome back!</h1>;
} else {
return <h1>Please sign up.</h1>;
}
}

Example (Class Component):


jsx
class Greeting extends React.Component {
render() {
if (this.props.isLoggedIn) {
return <h1>Welcome back!</h1>;
} else {
return <h1>Please sign up.</h1>;
}
}
}

MS. ESHA VINAY PATEL 21


UNIT 2 : FUNDAMENTALS OF REACT.JS

1.2 Ternary Operator (condition ? exprIfTrue : exprIfFalse)


Inline and concise conditional rendering.

Example:
jsx
function Greeting(props) {
return (
<h1>
{props.isLoggedIn ? "Welcome back!" : "Please sign up."}
</h1>
);
}

Or inside a class component's render:


jsx
render() {
return (
<div>
{this.props.isLoggedIn
? <LogoutButton />
: <LoginButton />}
</div>
);
}

1.3 Logical AND Operator (&&)


Render part of JSX only if a condition is true. If the condition is false,
React ignores the expression.

Example:
jsx
function Mailbox(props) {
const unreadMessages = props.unreadMessages;
return (
<div>
<h1>Hello!</h1>
{unreadMessages.length > 0 &&
<h2>
You have {unreadMessages.length} unread messages.
</h2>
}
</div>
);
}

MS. ESHA VINAY PATEL 22


UNIT 2 : FUNDAMENTALS OF REACT.JS

If unreadMessages.length is 0, no message will be displayed.

2. Using JavaScript Operators in JSX


Inside JSX curly braces {}, you can use JavaScript expressions, including
arithmetic, logical operators, and ternary conditions.

Examples:

 Arithmetic:
jsx
const total = props.price * props.quantity;

return <p>Total Price: {total}</p>;

 Logical:
jsx
{isActive && <button>Deactivate</button>}

 Ternary inline:
jsx
{isActive ? "Active" : "Inactive"}

3. Rendering Lists Dynamically in React


Lists (arrays) can be rendered by mapping over data and returning
components or JSX elements for each item.

Important: Use a unique key prop in each list


item to help React identify items efficiently.
3.1 Example Rendering a List of Items
Functional Component Example:
jsx
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
<li key={number.toString()}>
{number}
</li>

MS. ESHA VINAY PATEL 23


UNIT 2 : FUNDAMENTALS OF REACT.JS

);
return (
<ul>{listItems}</ul>
);
}

Usage:
jsx
const numbers = [1, 2, 3, 4, 5];
<NumberList numbers={numbers} />

Class Component Example:


jsx
class NumberList extends React.Component {
render() {
const numbers = this.props.numbers;
const listItems = numbers.map((number) =>
<li key={number.toString()}>
{number}
</li>
);
return (
<ul>{listItems}</ul>
);
}
}

4. Full Combined Example


Here’s a simple app combining conditional rendering and list
rendering in both class and functional components.

Functional Component Example


jsx
import React from 'react';

function TaskList(props) {
const { tasks, showCompleted } = props;

return (
<div>
<h2>Tasks</h2>
<ul>
{tasks
.filter(task => showCompleted || !task.completed)
.map(task => (
<li key={task.id}>

MS. ESHA VINAY PATEL 24


UNIT 2 : FUNDAMENTALS OF REACT.JS

{task.name} {task.completed ? "(Completed)" : ""}


</li>
))}
</ul>
{tasks.length === 0 && <p>No tasks!</p>}
</div>
);
}

export default TaskList;

Class Component Example with Conditional


Rendering
jsx
import React, { Component } from 'react';

class WelcomeMessage extends Component {


render() {
const { isLoggedIn, username } = this.props;

return (
<div>
{isLoggedIn ? (
<h1>Welcome, {username}!</h1>
):(
<h1>Please log in.</h1>
)}
</div>
);
}
}

export default WelcomeMessage;

Summary Table: Common Conditional


Rendering Methods
Method Usage Example Snippet
Use inside render or function if (isLoggedIn) return <Welcome />; else
if-else
before JSX return <Login />;

Ternary {isLoggedIn ? <LogoutButton /> :


Inline in JSX
operator <LoginButton />}

Logical AND
Render only if condition true {hasNotifications && <Notification />}
(&&)

MS. ESHA VINAY PATEL 25


UNIT 2 : FUNDAMENTALS OF REACT.JS

Method Usage Example Snippet


Return null To render nothing if (!props.show) return null;

2.2.3 React Events: Adding events, Passing arguments, Event objects

1. Adding Events in React


React supports most DOM events (like onClick, onChange, onMouseOver) as
camelCase props.

Functional Component – Example


jsx
function ClickButton() {
function handleClick() {
alert("Button Clicked!");
}

return <button onClick={handleClick}>Click Me</button>;


}

Class Component – Example


jsx
import React, { Component } from 'react';

class ClickButtonClass extends Component {


handleClick() {
alert("Button Clicked from Class Component!");
}

render() {
return <button onClick={this.handleClick}>Click Me</button>;
}
}

Note: In class components, you should bind event handlers in the


constructor or use arrow functions to access this.

2. Passing Arguments to Event Handlers


You often need to pass values or data to your event handlers.

Functional Component: Passing arguments


MS. ESHA VINAY PATEL 26
UNIT 2 : FUNDAMENTALS OF REACT.JS

jsx
function GreetButton(props) {
function handleGreet(name) {
alert("Hello, " + name);
}

return (
<button onClick={() => handleGreet(props.name)}>
Greet {props.name}
</button>
);
}

 Here, we use an arrow function inside the event handler to pass


the prop name.

Class Component: Passing arguments


jsx
import React, { Component } from 'react';

class GreetButtonClass extends Component {


handleGreet = (name) => {
alert("Hello, " + name);
};

render() {
return (
<button onClick={() => this.handleGreet(this.props.name)}>
Greet {this.props.name}
</button>
);
}
}

 Using an arrow function inside onClick lets you pass custom


arguments.

Warning: Arrow functions in render create a new function on every


render—OK for simple cases, but can impact performance in large apps.

3. Using Event Objects


React passes a synthetic event object to your handler:

 It wraps the browser’s native event and has the same interface (for
cross-browser compatibility).

MS. ESHA VINAY PATEL 27


UNIT 2 : FUNDAMENTALS OF REACT.JS

Functional Component: Event Object


jsx
function InputLogger() {
function handleInput(event) {
// event.target is the HTML element
alert("Input changed: " + event.target.value);
}

return <input onChange={handleInput} />;


}

Class Component: Event Object


jsx
import React, { Component } from 'react';

class InputLoggerClass extends Component {


handleInput = (event) => {
alert("Input changed: " + event.target.value);
};

render() {
return <input onChange={this.handleInput} />;
}
}

4. Full Simple Example with Multiple Event


Types
jsx
import React, { useState } from 'react';

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

// Passing argument and using event object


function handleClick(event, incrementBy) {
setCount(count + incrementBy);
console.log("Event type:", event.type);
}

return (
<div>
<h3>Count: {count}</h3>
<button onClick={(e) => handleClick(e, 1)}>Increase</button>
<button onClick={(e) => handleClick(e, -1)}>Decrease</button>
</div>
);
}

MS. ESHA VINAY PATEL 28


UNIT 2 : FUNDAMENTALS OF REACT.JS

export default EventDemo;

Explanation:

 receives both the event object and a custom argument.


onClick
 You can pass 'e' (event) and any number of parameters you like.

5. Summary Table
Task Functional Component Class Component
Add event <button onClick={handler}> <button onClick={this.handler}>
Pass argument onClick={() => handler(arg)} onClick={() => this.handler(arg)}
Access event object handler(event) handler(event)
Access event target value event.target.value event.target.value

6. Common Events Supported in React


 onClick – Mouse click
 onChange – Input or select value change
 onSubmit – Form submit
 onMouseOver / onMouseEnter – Mouse hovers
 onKeyDown / onKeyUp – Keyboard events
 All use camelCase (not lowercase like plain HTML)

7. Advanced: Preventing Default Actions


To prevent (for example) a form from sending data and reloading:
jsx
function MyForm() {
function handleSubmit(event) {
event.preventDefault(); // Prevent page reload
alert("Form Submitted!");
}

return (
<form onSubmit={handleSubmit}>
<button type="submit">Submit</button>
</form>
);
}

MS. ESHA VINAY PATEL 29


UNIT 2 : FUNDAMENTALS OF REACT.JS

2.3 Forms: (Adding forms, Handling forms, Submitting forms)

Adding and Handling Forms in React


 A form in React is created using the <form> tag and controlled components (fields
whose values are tied to state).
 You typically manage form state (e.g., input values) using useState in functional
components or this.state in class components.
 You connect each input’s value to state, and update that state on each change via an
onChange handler.
 Submitting is intercepted by handling the form's onSubmit event, usually calling
event.preventDefault() to stop full page reload.

Basic Example (Functional Component):

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

function SimpleForm() {
const [name, setName] = useState('');

function handleChange(event) {
setName(event.target.value);
}

function handleSubmit(event) {
event.preventDefault();
alert(`Submitted name: ${name}`);
}

return (
<form onSubmit={handleSubmit}>
<input type="text" value={name} onChange={handleChange} />
<button type="submit">Submit</button>
</form>
);
}

 Here, the form input is controlled—React manages its value in state.

2.3.1 event.target.name and event.target.value, React.memo


event.target.name and event.target.value
 When you have multiple form fields, you can use a single handler to update state for
all, by using the name attribute.
 event.target.name gives the name of the input field. event.target.value gives its value.

Example (Multiple Fields):

MS. ESHA VINAY PATEL 30


UNIT 2 : FUNDAMENTALS OF REACT.JS

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

function MultiFieldForm() {
const [inputs, setInputs] = useState({ username: '', age: '' });

function handleChange(event) {
const { name, value } = event.target;
setInputs(inputs => ({ ...inputs, [name]: value }));
}

function handleSubmit(event) {
event.preventDefault();
alert(`Username: ${inputs.username}, Age: ${inputs.age}`);
}

return (
<form onSubmit={handleSubmit}>
<input type="text" name="username" value={inputs.username} onChange={handleChange} />
<input type="number" name="age" value={inputs.age} onChange={handleChange} />
<button type="submit">Submit</button>
</form>
);
}

 Setting the name attribute allows the generic handleChange to update the correct field.

React.memo
 React.memo is a higher-order component to optimize functional components—it
prevents unnecessary re-renders by memoizing the component output, only
updating when the props change.
 It’s useful in large forms with many child components that don’t always need to re-
render.

Example:

jsx
const OptimizedInput = React.memo(function OptimizedInput(props) {
return <input {...props} />;
});

 Use when performance is noticeably impacted by frequent, redundant renders.

MS. ESHA VINAY PATEL 31


UNIT 2 : FUNDAMENTALS OF REACT.JS

2.3.2 Components: TextArea, Drop Down List (SELECT)


TextArea
 Controlled textarea uses value and onChange, just like <input>.

jsx
<textarea
name="message"
value={inputs.message}
onChange={handleChange}
/>

 Handle updates just like other inputs in your state.

Drop Down List (SELECT)


 For a single-selection dropdown:

jsx
<select name="flavor" value={inputs.flavor} onChange={handleChange}>
<option value="apple">Apple</option>
<option value="banana">Banana</option>
<option value="cherry">Cherry</option>
</select>

 For multiple selection:

jsx
<select name="fruits" multiple value={inputs.fruits} onChange={handleChange}>
<option value="apple">Apple</option>
<option value="banana">Banana</option>
<option value="cherry">Cherry</option>
</select>

 Note: For multiple, event.target.value is an array of selected options.

Full Example in a Form:

jsx
function FullForm() {
const [inputs, setInputs] = useState({
name: '',
comment: '',
color: '',
});

function handleChange(event) {
const { name, value } = event.target;
setInputs(inputs => ({ ...inputs, [name]: value }));
}

function handleSubmit(event) {

MS. ESHA VINAY PATEL 32


UNIT 2 : FUNDAMENTALS OF REACT.JS

event.preventDefault();
alert(JSON.stringify(inputs));
}

return (
<form onSubmit={handleSubmit}>
<input type="text" name="name" value={inputs.name} onChange={handleChange} />
<textarea name="comment" value={inputs.comment} onChange={handleChange} />
<select name="color" value={inputs.color} onChange={handleChange}>
<option value="">Pick a color</option>
<option value="red">Red</option>
<option value="blue">Blue</option>
</select>
<button type="submit">Submit</button>
</form>
);
}

 Shows text input, textarea, and dropdown working together; all handled via name,
value, and one function.

Summary Table
Feature How to Use Example Code
Single Input Set value, use onChange/setState <input value={state} onChange={handler} />
Use name + event.target.name in
Multiple Fields <input name="x" onChange={handler} />
handler
Same as input, with value and
Textarea <textarea value={state} onChange={handler} />
onChange
Dropdown Controlled value, update <select value={state}
(Select) onChange onChange={handler}>...</select>
React.memo Optimize function components const Comp = React.memo(MyComp)
Identify input for handler, update
event.target.name const {name, value} = event.target
by name

MS. ESHA VINAY PATEL 33


UNIT 2 : FUNDAMENTALS OF REACT.JS

Example of Registration Form :


1 . RegistrationForm.jsx

import React, { useState } from "react";

const RegistrationForm = () => {


const [formData, setFormData] = useState({
fullName: "",
email: "",
password: "",
confirmPassword: "",
phone: "",
gender: "",
terms: false,
});

const [errors, setErrors] = useState({});

const handleChange = (e) => {


const { name, value, type, checked } = e.target;
setFormData((prev) => ({
...prev,
[name]: type === "checkbox" ? checked : value,
}));
};

const validate = () => {


let newErrors = {};

if (!formData.fullName.trim()) newErrors.fullName = "Full name is required";


if (!formData.email.match(/^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/))
newErrors.email = "Valid email is required";
if (formData.password.length < 6)
newErrors.password = "Password must be at least 6 characters";
if (formData.password !== formData.confirmPassword)
newErrors.confirmPassword = "Passwords do not match";
if (!formData.phone.match(/^\d{10}$/))
newErrors.phone = "Enter valid 10-digit phone number";
if (!formData.gender) newErrors.gender = "Select gender";
if (!formData.terms) newErrors.terms = "You must accept terms";

return newErrors;
};

const handleSubmit = (e) => {


e.preventDefault();
const validationErrors = validate();

MS. ESHA VINAY PATEL 34


UNIT 2 : FUNDAMENTALS OF REACT.JS

setErrors(validationErrors);

if (Object.keys(validationErrors).length === 0) {
alert("Registration successful!");
console.log(formData);
}
};

return (
<form onSubmit={handleSubmit} style={{ maxWidth: "400px", margin: "auto" }}>
<h2>Registration Form</h2>

<input
type="text"
name="fullName"
placeholder="Full Name"
value={formData.fullName}
onChange={handleChange}
/>
<div style={{ color: "red" }}>{errors.fullName}</div>

<input
type="email"
name="email"
placeholder="Email"
value={formData.email}
onChange={handleChange}
/>
<div style={{ color: "red" }}>{errors.email}</div>

<input
type="password"
name="password"
placeholder="Password"
value={formData.password}
onChange={handleChange}
/>
<div style={{ color: "red" }}>{errors.password}</div>

<input
type="password"
name="confirmPassword"
placeholder="Confirm Password"
value={formData.confirmPassword}
onChange={handleChange}
/>
<div style={{ color: "red" }}>{errors.confirmPassword}</div>

<input

MS. ESHA VINAY PATEL 35


UNIT 2 : FUNDAMENTALS OF REACT.JS

type="text"
name="phone"
placeholder="Phone Number"
value={formData.phone}
onChange={handleChange}
/>
<div style={{ color: "red" }}>{errors.phone}</div>

<div>
Gender:
<label>
<input
type="radio"
name="gender"
value="male"
checked={formData.gender === "male"}
onChange={handleChange}
/>
Male
</label>

<label>
<input
type="radio"
name="gender"
value="female"
checked={formData.gender === "female"}
onChange={handleChange}
/>
Female
</label>
</div>
<div style={{ color: "red" }}>{errors.gender}</div>

<label>
<input
type="checkbox"
name="terms"
checked={formData.terms}
onChange={handleChange}
/>
I accept the Terms & Conditions
</label>
<div style={{ color: "red" }}>{errors.terms}</div>

<button type="submit">Register</button>
</form>
);
};

MS. ESHA VINAY PATEL 36


UNIT 2 : FUNDAMENTALS OF REACT.JS

export default RegistrationForm;

2. app.js

import React from "react";


import RegistrationForm from "./RegistrationForm";

function App() {
return (
<div className="App">
<RegistrationForm />
</div>
);
}

export default App;

MS. ESHA VINAY PATEL 37


UNIT 2 : FUNDAMENTALS OF REACT.JS

2.4 Hooks: Concepts and Advantages

A hook in React is a special function that lets you "hook into" React features—such as state,
lifecycle, or context—directly from function components, without needing to write class
components.

Why is a hook used?


 Hooks allow function components to manage state and use other advanced React
features like side effects, context, and refs, which were previously only available in
class components.
 Hooks make React code simpler, easier to read, and less repetitive.
 They allow you to reuse stateful logic across multiple components by creating
custom hooks, improving code modularity and maintainability.

Key Examples
 useState: Enables a function component to have its own state.
 useEffect: Handles side effects (like data fetching or subscriptions) in function
components, replacing methods like componentDidMount in classes.
 Custom Hooks: Lets you extract and share logic between components.

Summary Table
Feature With Hooks Without Hooks

State in functions Yes (useState) No (only in class components)

Side effects in functions Yes (useEffect) No (only in class components)

Reusable logic Yes (custom hooks) Harder to share across components

2.4.1 useState, useEffect, useContext

What is useState?
 useStateis a React Hook that lets you add stateful logic to functional components.
 Before Hooks, only class components could have state; useState enables function
components to maintain and update state.
 It provides a pair of values:
o The current value of the state.

MS. ESHA VINAY PATEL 38


UNIT 2 : FUNDAMENTALS OF REACT.JS

o A function to update that state.

Syntax and Basic Usage


jsx
const [stateVariable, setStateFunction] = useState(initialValue);

 stateVariable: The current state value.


 setStateFunction: Function used to update the state.
 initialValue: The initial value you want your state to hold.

Example:

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

 Initializes the state variable count to 0.


 setCount lets you change count and triggers a component re-render with the new state.

How It Works Internally


1. Initialization — When the component first renders, useState(initialValue) sets the state
to initialValue.
2. Persistence — React preserves the current state across re-renders. This means if the
component re-renders, count will keep its latest value rather than reinitializing.
3. Updating State — Calling setCount(newValue) schedules React to update the state and
triggers a re-render of the component with the new value.
4. Batched Updates and Async Nature — State updates via setCount are asynchronous
and may be batched for performance.

Important Details
 Calling setCount does not immediately update the state variable in the current render
or synchronous code; the update will be reflected on the next render.
 useState can hold any data type:
o Primitive types like number, string, boolean.
o Complex types like arrays, objects.
 You can call useState multiple times in the same component to manage multiple
pieces of state separately.
 You can update state using the functional update form to safely work with the
previous state, especially in asynchronous scenarios:

jsx
setCount(prevCount => prevCount + 1);

Extended Examples
MS. ESHA VINAY PATEL 39
UNIT 2 : FUNDAMENTALS OF REACT.JS

1. Simple Counter Example (Basic)


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

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

const increment = () => {


setCount(count + 1); // schedules state update with new count
};

return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
</div>
);
}

 Every click updates count and causes a re-render of Counter with new value.

2. Functional Update Example (Safe Updates)


If your update depends on the previous state, use the callback form:

jsx
setCount(prevCount => prevCount + 1);

This avoids issues if multiple updates happen quickly:

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

const incrementTwice = () => {


setCount(prev => prev + 1);
setCount(prev => prev + 1);
};

return <button onClick={incrementTwice}>Increment Twice</button>;


}

Here, count increases by 2.

3. Managing Complex State (Objects)


jsx
const [user, setUser] = useState({ name: "", age: 0 });

function updateName(newName) {
setUser(prevUser => ({
...prevUser,
name: newName

MS. ESHA VINAY PATEL 40


UNIT 2 : FUNDAMENTALS OF REACT.JS

}));
}

 Use the spread operator ...prevUser to keep other properties unchanged when updating
one field.
 This is because useState does not merge state updates, unlike class component setState.

Best Practices
 Initialize state properly: If the initial state requires computation, pass a function to
useState so it runs only once:

jsx
const [value, setValue] = useState(() => computeInitialValue());

 Avoid state mutations: Always give a new value or object to the setter; do not
mutate existing state.
 Split state logically: Use multiple useState hooks for unrelated pieces of state rather
than a large object.
 Use functional updates when the new state depends on the previous state.
 Keep state minimal: Store only the necessary app data needed for rendering.

Summary Table of useState


Aspect Explanation Example
Purpose Manage state in function components const [count, setCount] = useState(0)
Returns State variable + setter function [value, setValue]
Initial State Passed in as argument useState(false), useState({})
Update causing re-render Call setter function with new value setCount(count + 1)
Functional update form Updates based on previous state setCount(prev => prev + 1)
Use multiple useState To handle multiple state variables useState() called multiple times

MS. ESHA VINAY PATEL 41


UNIT 2 : FUNDAMENTALS OF REACT.JS

What is useEffect?
 The useEffect hook lets you perform side effects in functional components.
 Side effects include:
 Data fetching from APIs
 Setting up subscriptions or timers
 Manually changing the DOM
 Logging, analytics, or any operations that interact outside React rendering
 It replaces lifecycle methods like componentDidMount, componentDidUpdate,
and componentWillUnmount in class components.

Syntax
jsx
useEffect(() => {
// Side effect code here

return () => {
// Optional cleanup code here
};
}, [dependencies]);
 The first argument is a function containing side-effect logic.
 The returned function, if any, is a cleanup function that runs before the effect is re-executed
or when the component unmounts.
 The second argument is an array of dependencies. The effect runs:
 After initial render
 Then any time a value in the dependencies array changes
 If the dependencies array is empty ([]), the effect runs only once after the component mounts.

How It Works
Example 1: Log every count update
jsx
import React, { useState, useEffect } from 'react';

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

useEffect(() => {
console.log(`Count changed to ${count}`);
}, [count]); // Runs this effect after count changes

return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Add 1</button>
</div>
);
}

MS. ESHA VINAY PATEL 42


UNIT 2 : FUNDAMENTALS OF REACT.JS

 Every time count updates, the effect executes, logging the new count.

Example 2: Run once on component mount


(like componentDidMount)
jsx
useEffect(() => {
console.log("Component mounted");

// You could fetch data or set up subscriptions here


}, []); // No dependencies → runs once

Example 3: Cleanup example with timer


jsx
import React, { useState, useEffect } from 'react';

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

useEffect(() => {
const intervalId = setInterval(() => {
setSeconds(prev => prev + 1);
}, 1000);

// Cleanup function to clear timer on unmount or before next effect


return () => {
clearInterval(intervalId);
console.log("Timer cleaned up");
};
}, []); // Empty dependencies - setup timer once

return <div>Seconds: {seconds}</div>;


}
 The cleanup function clears the timer when the component unmounts to avoid memory leaks.

Important Notes About useEffect


 Effects run after render and reconcile phases.
 Avoid putting expensive operations inside useEffect that block UI updates.
 If useEffect has no dependency array, it runs after every render.
 Returning a cleanup function is crucial for subscriptions, timers, or event listeners.
 React guarantees the cleanup runs before the next effect or on unmount.

MS. ESHA VINAY PATEL 43


UNIT 2 : FUNDAMENTALS OF REACT.JS

What is useContext?
 useContext allows functional components to consume context values directly.
 React Context is a way to pass data through component trees without manually passing props
down at every level.
 It solves prop drilling, where props are needlessly passed through intermediate components.
 You create a context object and provide it via <Context.Provider>.
 Any component (child, grandchild, etc.) can read the value via useContext.

Usage Steps
1. Create Context
jsx
import React from 'react';

const MyContext = React.createContext(defaultValue);


 defaultValue is used only when no matching Provider exists.

2. Provide Context Value


Wrap parts of your app with the Provider supplying a value:
jsx
<MyContext.Provider value={{ user: "Alice" }}>
<ChildComponent />
</MyContext.Provider>

3. Consume Context Value


In any descendant, use the useContext hook:
jsx
import React, { useContext } from 'react';

function ChildComponent() {
const contextValue = useContext(MyContext);
return <div>User: {contextValue.user}</div>;
}
This avoids passing user explicitly through props.

Simple Complete Example


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

const ThemeContext = createContext('light');

function ThemedText() {
const theme = useContext(ThemeContext);
const style = {

MS. ESHA VINAY PATEL 44


UNIT 2 : FUNDAMENTALS OF REACT.JS

backgroundColor: theme === 'dark' ? '#333' : '#eee',


color: theme === 'dark' ? '#eee' : '#333',
padding: '10px',
};
return <p style={style}>Current Theme: {theme}</p>;
}

function App() {
return (
<ThemeContext.Provider value="dark">
<ThemedText />
</ThemeContext.Provider>
);
}
 ThemedText accesses context value directly, no props required.
 Changing provider’s value changes all consumers automatically.

Tips for Using useContext


 Context is great for globally-needed data: themes, user/auth info, language, settings.
 Avoid overusing context for frequent updates as context changes cause all consumers to re-
render.
 Combine with useReducer or state for global app state management if needed.

Summary Table of Hooks


Hook Purpose Basic Usage Example

useState Add local component state const [count, setCount] = useState(0);

useEffect(() => { /* effect */ return () => {/* cleanup */} },


useEffect Run side effects & cleanup [deps]);

Access context value without


useContext props const val = useContext(MyContext);

MS. ESHA VINAY PATEL 45


UNIT 2 : FUNDAMENTALS OF REACT.JS

Full Working Example: React Hooks useState,


useEffect, and useContext in One Project

This example demonstrates:

 useState: for local component state (counter),


 useEffect: for side effects (logging and timer),
 useContext: for shared theme and user information across components.

Project Structure (all files under src/)


text
src/
App.js
ThemeContext.js
Counter.js
UserProfile.js
index.js

ThemeContext.js — Creating Context for Theme and User


jsx
import React from 'react';

export const ThemeContext = React.createContext({


theme: 'light',
toggleTheme: () => {},
user: { name: 'Guest' },
});

Counter.js — Using useState and useEffect


jsx
import React, { useState, useEffect } from 'react';

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

// Side effect: log count whenever it changes


useEffect(() => {
console.log(`Count updated: ${count}`);
}, [count]);

return (
<div style={{ margin: '1rem 0' }}>
<h3>Counter</h3>
<p>Current count: {count}</p>
<button onClick={() => setCount(count + 1)} style={{ marginRight: 8 }}>
Increase
</button>
<button onClick={() => setCount(count > 0 ? count - 1 : 0)}>

MS. ESHA VINAY PATEL 46


UNIT 2 : FUNDAMENTALS OF REACT.JS

Decrease
</button>
</div>
);
}

export default Counter;

UserProfile.js — Using useContext


jsx
import React, { useContext } from 'react';
import { ThemeContext } from './ThemeContext';

function UserProfile() {
const { user, theme } = useContext(ThemeContext);

const style = {
padding: '1rem',
border: '1px solid',
borderColor: theme === 'dark' ? '#aaa' : '#444',
backgroundColor: theme === 'dark' ? '#222' : '#f9f9f9',
color: theme === 'dark' ? '#eee' : '#111',
};

return (
<div style={style}>
<h3>User Profile</h3>
<p>User Name: <strong>{user.name}</strong></p>
<p>Current Theme: <strong>{theme}</strong></p>
</div>
);
}

export default UserProfile;

App.js — Putting It All Together with useState, useEffect, and useContext


jsx
import React, { useState, useEffect } from 'react';
import { ThemeContext } from './ThemeContext';
import Counter from './Counter';
import UserProfile from './UserProfile';

function App() {
const [theme, setTheme] = useState('light');
const [user, setUser] = useState({ name: 'Alice' });
const [time, setTime] = useState(new Date());

// useEffect runs once to set up a timer updating the current time every second
useEffect(() => {
const timerId = setInterval(() => {
setTime(new Date());
}, 1000);

return () => clearInterval(timerId); // cleanup timer on unmount


}, []);

MS. ESHA VINAY PATEL 47


UNIT 2 : FUNDAMENTALS OF REACT.JS

// Toggle theme light/dark


function toggleTheme() {
setTheme(prev => (prev === 'light' ? 'dark' : 'light'));
}

// Change user name on button click


function changeUserName() {
setUser(prev => ({
name: prev.name === 'Alice' ? 'Bob' : 'Alice',
}));
}

// Styles switch based on theme context


const appStyle = {
backgroundColor: theme === 'dark' ? '#121212' : '#fafafa',
color: theme === 'dark' ? '#eee' : '#222',
minHeight: '100vh',
padding: '2rem',
fontFamily: 'Arial, sans-serif',
};

return (
<ThemeContext.Provider value={{ theme, toggleTheme, user }}>
<div style={appStyle}>
<header>
<h1>React Hooks Combined Example</h1>
<p>Current time: {time.toLocaleTimeString()}</p>
</header>

<button onClick={toggleTheme} style={{ marginRight: '1rem' }}>


Toggle Theme
</button>
<button onClick={changeUserName}>
Change User Name
</button>

{/* Components consuming context and managing their own state/effects */}
<UserProfile />
<Counter />
</div>
</ThemeContext.Provider>
);
}

export default App;

index.js — Standard React App Entry Point


jsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';

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


root.render(
<React.StrictMode>
<App />

MS. ESHA VINAY PATEL 48


UNIT 2 : FUNDAMENTALS OF REACT.JS

</React.StrictMode>
);

How This Works


 The App component keeps theme and user info in state and provides them via
ThemeContext.Provider.
 useEffect in App starts a timer to update current time every second.
 UserProfile consumes ThemeContext using useContext to read theme and user and style
content accordingly.
 Counter has its own local state with useState and logs count changes via useEffect.
 Buttons in App toggle theme (light/dark) and swap between users "Alice" and "Bob".

Running This Project


1. Create a new React app with npx create-react-app your-app.
2. Replace the content of src/ with the above files.
3. Run npm start.
4. Open http://localhost:3000 to see the fully interactive app.

Summary Table
Hook Usage Example in Project Role
useState Manage theme, user, counter local state State management inside App and Counter
Update time every second, log counter Side effects and cleanup (timers and
useEffect
changes logging)
Share theme and user data to any Access global/shared state without prop
useContext
component drilling

MS. ESHA VINAY PATEL 49


UNIT 2 : FUNDAMENTALS OF REACT.JS

2.4.2 useRef, useReducer, useCallback, useMemo

What is useRef?
 useRef is a React Hook that returns a mutable ref object with a .current property.
 This ref object persists for the full lifetime of the component.
 Changing .current does not cause a component re-render, making it perfect for
storing mutable data that should survive between renders without triggering updates.
 Primarily used to:
o Access and manipulate DOM elements directly.
o Hold mutable values that don’t cause re-renders when changed.
o Keep values between renders (similar to instance variables in class
components).

When and Why Use useRef?


1. Accessing DOM Elements

Sometimes, you need to interact with the underlying DOM element (input, div, etc.) directly
— for example, focusing an input or reading its current value.

2. Storing Mutables Without Re-renders

You might want to keep track of some value that changes over time but should not trigger re-
render when updated (like timers, previous props, or mutable state).

3. Keeping Values Between Renders

useRef can hold any value, and that value will persist as long as the component is mounted.

Syntax
jsx
const refContainer = useRef(initialValue);

 refContainer is an object like { current: initialValue }.

Examples
1. Accessing a DOM element (e.g., focusing an input)
jsx
import React, { useRef } from 'react';

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

MS. ESHA VINAY PATEL 50


UNIT 2 : FUNDAMENTALS OF REACT.JS

const focusInput = () => {


// Access the native input element and call .focus()
inputRef.current.focus();
};

return (
<>
<input ref={inputRef} type="text" placeholder="Click button to focus me" />
<button onClick={focusInput}>Focus Input</button>
</>
);
}

 Here, useRef holds a ref object.


 Ref is attached to <input> via React's ref prop.
 Clicking the button calls focus() on the DOM element directly.

2. Storing a mutable value that does not cause renders


(e.g., keeping track of previous state)
jsx
import React, { useState, useEffect, useRef } from 'react';

function PreviousCountExample() {
const [count, setCount] = useState(0);
const prevCountRef = useRef();

useEffect(() => {
// Store current count in ref after each render
prevCountRef.current = count;
});

const prevCount = prevCountRef.current;

return (
<div>
<h2>Now: {count}</h2>
<h2>Before: {prevCount}</h2>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}

 The prevCountRef.current holds the previous value of count.


 It updates after every render without causing a re-render when changed.

3. Keeping a timer ID without triggering re-renders


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

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

MS. ESHA VINAY PATEL 51


UNIT 2 : FUNDAMENTALS OF REACT.JS

const timerIdRef = useRef(null);

useEffect(() => {
timerIdRef.current = setInterval(() => {
setSeconds(prev => prev + 1);
}, 1000);

// Cleanup timer on unmount


return () => clearInterval(timerIdRef.current);
}, []);

return <h3>Seconds elapsed: {seconds}</h3>;


}

 timerIdRef holds the ID returned by setInterval.


 Since changing .current doesn’t cause re-renders, it’s ideal here.
 You can clear the interval by accessing the .current value.

Summary Table for useRef


Use Case How to Use useRef Example Scenario
Assign ref with ref={myRef} to a JSX Focusing input, measuring size
Access DOM element
element or scroll
Previous state, timer ID, latest
Hold mutable variable Store mutable data in ref.current
value
Avoid re-render on Update ref.current without triggering Storing interval ID or mutable
change render counters

Important Notes
 Updating ref.current does not trigger re-render, so do not rely on it if UI update
is needed. For UI state, use useState.
 useRef is similar to instance variables in class components.
 Returning a ref from useRef ensures the same object persists across renders.

Full Example Using useRef


This example includes:
 Focusing an input using a button click.
 Tracking previous state value using useRef.
 Using useRef for storing a timer ID for a setInterval.

MS. ESHA VINAY PATEL 52


UNIT 2 : FUNDAMENTALS OF REACT.JS

Project Structure (inside src/):


 App.js — Main app component combining all examples.

App.js
jsx
import React, { useState, useEffect, useRef } from 'react';

function App() {
// State for counter
const [count, setCount] = useState(0);

// useRef for accessing DOM input element


const inputRef = useRef(null);

// useRef for storing previous count value


const prevCountRef = useRef();

// useRef for timer ID


const timerIdRef = useRef(null);

// Update prevCountRef.current after every render


useEffect(() => {
prevCountRef.current = count;
}, [count]);

// Set up a timer that increments count every 2 seconds


useEffect(() => {
timerIdRef.current = setInterval(() => {
setCount((c) => c + 1);
}, 2000);

// Cleanup timer on unmounting


return () => {
clearInterval(timerIdRef.current);
};
}, []);

// Function to focus input when button is clicked


const handleFocusInput = () => {
if (inputRef.current) {
inputRef.current.focus();
}
};

// Function to manually increment count via button


const incrementCount = () => {
setCount((c) => c + 1);
};

return (
<div style={{ padding: '20px', fontFamily: 'Arial, sans-serif' }}>
<h2>useRef Hook Example</h2>

MS. ESHA VINAY PATEL 53


UNIT 2 : FUNDAMENTALS OF REACT.JS

{/* Input with ref */}


<input
ref={inputRef}
type="text"
placeholder="Click button to focus me"
style={{ padding: '8px', width: 250 }}
/>
<button onClick={handleFocusInput} style={{ marginLeft: '10px' }}>
Focus Input
</button>

<hr style={{ margin: '20px 0' }} />

{/* Counter with previous value tracked via useRef */}


<div>
<p>Current Count: {count}</p>
<p>Previous Count: {prevCountRef.current ?? 'N/A'}</p>
<button onClick={incrementCount}>Increment Count</button>
<p style={{ marginTop: 10, fontStyle: 'italic' }}>
Count automatically increments every 2 seconds via timer
</p>
</div>
</div>
);
}

export default App;

How to Run
1. Create a new React app or use an existing one created by:
bash
npx create-react-app my-app
cd my-app
2. Replace the content of src/App.js with the above code.
3. Start the React app:
bash
npm start
4. Open http://localhost:3000

What Happens in This Example?


 The input box can be focused programmatically by clicking the "Focus
Input" button. This is achieved by assigning a ref with useRef and
calling .focus() on the DOM node.
 The count state increments automatically every 2 seconds using a timer ID stored
inside a ref (timerIdRef), so the timer ID is preserved across renders without causing
re-renders.
 The previous count value is stored in prevCountRef.current and updated on
every render via a useEffect, allowing you to see what the last rendered count was.

MS. ESHA VINAY PATEL 54


UNIT 2 : FUNDAMENTALS OF REACT.JS

 The manual increment button also updates the count immediately.


 Note that updating anything in these refs does not cause re-renders; the component
only re-renders when state (count) changes.

Summary: Key useRef Uses in This Example

Use Case Implementation

Access/Manipulate DOM const inputRef = useRef(null); + ref={inputRef} on input,


node then inputRef.current.focus()

Store timer ID without re-


render timerIdRef = useRef(null) to hold interval ID for cleanup

Track previous state value Update prevCountRef.current = count in useEffect after render

What is useReducer?
 useReducer is a React Hook that lets you manage complex state logic in function
components.
 It is an alternative to useState and is preferred when:
o State depends on previous state values,
o You have multiple related state variables,
o Your state updates involve multiple sub-values or complex updates,
o You want to centralize state update logic in a single function.
 It implements the Reducer pattern popular in Redux and functional programming: a
reducer function takes a current state and an action, and returns a new state.

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

 reducer: A function (state, action) => newState that updates state based on an
action.
 initialState: Initial value of the state.
 state: Current state value.
 dispatch: A function to send actions to the reducer.

How the Reducer Works


1. You define a reducer function that receives the current state and an action object.
2. Based on the action.type, the reducer returns a new state.
3. dispatch is called with an action to trigger the state update.

MS. ESHA VINAY PATEL 55


UNIT 2 : FUNDAMENTALS OF REACT.JS

Example: Counter Using useReducer


jsx
import React, { useReducer } from 'react';

const initialState = { count: 0 };

// Reducer function to handle actions


function reducer(state, action) {
switch(action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
case 'reset':
return initialState;
default:
throw new Error('Unknown action type');
}
}

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

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

export default Counter;

Why Use useReducer Instead of useState?


Aspect useState useReducer

Complex state logic with multiple


State structure Usually simple values or objects
sub-values
Centralized in a reducer function
State update logic Declarative, often inline
(pure function)
Better for complex, multi-step
Easier to debug Simpler for straightforward cases
updates
Use with multiple Less organized with multiple Dispatch multiple action types
dispatches setState calls cleanly

When to Prefer useReducer

MS. ESHA VINAY PATEL 56


UNIT 2 : FUNDAMENTALS OF REACT.JS

 Managing form states with multiple fields.


 Handling complex objects or nested states.
 When updates depend on previous state.
 Better traceability of state changes via action objects.
 When you want to keep your state update logic decoupled from UI components.

Extended Example: Form State Management


jsx
import React, { useReducer } from 'react';

const initialState = {
username: '',
email: '',
password: '',
};

function reducer(state, action) {


switch (action.type) {
case 'field':
return {
...state,
[action.field]: action.value,
};
case 'reset':
return initialState;
default:
return state;
}
}

function SignupForm() {
const [state, dispatch] = useReducer(reducer, initialState);
const { username, email, password } = state;

function handleSubmit(e) {
e.preventDefault();
alert(`Signup info:\n${JSON.stringify(state, null, 2)}`);
dispatch({ type: 'reset' });
}

function handleChange(e) {
dispatch({
type: 'field',
field: e.target.name,
value: e.target.value,
});
}

return (
<form onSubmit={handleSubmit}>
<input name="username" value={username} onChange={handleChange} placeholder="Username" />
<input name="email" value={email} onChange={handleChange} placeholder="Email" />
<input name="password" type="password" value={password} onChange={handleChange}
placeholder="Password" />
<button type="submit">Sign Up</button>
</form>

MS. ESHA VINAY PATEL 57


UNIT 2 : FUNDAMENTALS OF REACT.JS

);
}

export default SignupForm;

Summary Table for useReducer


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

Reducer
(state, action) => newState
function
Dispatch action dispatch({ type: 'increment' })

Benefits Centralized state logic, better for complex state

Full Create React App Example Using


useReducer

This example manages a simple counter with increment, decrement, and reset actions using
useReducer.

1. Set up the project


bash
npx create-react-app useReducer-example
cd useReducer-example

2. Replace the content of src/App.js with the following code:


jsx
import React, { useReducer } from 'react';

// Initial state
const initialState = { count: 0 };

// Reducer function updates state based on action type


function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };

case 'decrement':
return { count: state.count - 1 };

case 'reset':
return initialState;

default:

MS. ESHA VINAY PATEL 58


UNIT 2 : FUNDAMENTALS OF REACT.JS

throw new Error(`Unknown action: ${action.type}`);


}
}

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

return (
<div style={{ textAlign: 'center', marginTop: 50, fontFamily: 'Arial, sans-serif' }}>
<h1>Counter with useReducer</h1>
<p style={{ fontSize: 48 }}>{state.count}</p>
<button onClick={() => dispatch({ type: 'decrement' })}
style={{ padding: '10px 20px', fontSize: 20, marginRight: 10 }}>
-
</button>
<button onClick={() => dispatch({ type: 'increment' })}
style={{ padding: '10px 20px', fontSize: 20, marginRight: 10 }}>
+
</button>
<button onClick={() => dispatch({ type: 'reset' })}
style={{ padding: '10px 20px', fontSize: 20 }}>
Reset
</button>
</div>
);
}

export default App;

3. Run the app


bash
npm start

You will see a counter initialized at 0, with three buttons: decrement (-), increment (+), and
reset. Clicking these buttons dispatches actions that update the state using the reducer
function.

Comparison: useState vs useReducer with Examples


Aspect useState useReducer

Manages simple state (usually single Manages complex state logic, multiple
Purpose
values or simple objects) actions, or deeply nested updates
State update Central reducer function handles all
Setters passed inline or with callbacks
logic updates based on action types
When to Complex state transitions, related state
Simple/independent state variables
prefer variables depending on each other
Example To track counter with multiple actions
To track a single counter value
usage (increment, decrement, reset)

MS. ESHA VINAY PATEL 59


UNIT 2 : FUNDAMENTALS OF REACT.JS

Aspect useState useReducer

Code More structured, easier to extend for


Less boilerplate for simple updates
simplicity complex cases

Example: Counter with useState


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

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

return (
<div style={{ textAlign: 'center', marginTop: 50 }}>
<h1>Counter with useState</h1>
<p style={{ fontSize: 48 }}>{count}</p>
<button onClick={() => setCount(count - 1)}>-</button>
<button onClick={() => setCount(count + 1)}>+</button>
<button onClick={() => setCount(0)}>Reset</button>
</div>
);
}

Example: Counter with useReducer


(Refer to the full useReducer example above.)

Summary
 Use useState for simple and independent state variables.
 Use useReducer when state logic is complex with multiple sub-values, complicated
updates, or when you want to centralize logic.
 useReducer resembles Redux reducers but can be used locally in components without
external libraries.
 useReducer makes it easier to handle multiple related state updates in one place and
improves maintainability.

What is useCallback?
The React useCallback hook is a built-in hook that returns a memoized callback
function. It helps optimize performance by preventing unnecessary re-creation of
functions on every render. This is especially useful when passing functions as props
to child components that rely on reference equality (like when these children are
wrapped in React.memo to avoid unnecessary re-renders).

MS. ESHA VINAY PATEL 60


UNIT 2 : FUNDAMENTALS OF REACT.JS

 It memoizes a function definition, so React returns the same function instance


between renders unless the dependencies change.
 Without useCallback, a new function is created on every render, which might trigger
unnecessary renders or effect executions in child components.
 You provide a callback function and a dependency array, similar to useEffect or
useMemo. The memoized function only changes when dependencies change.

Syntax
jsx
const memoizedCallback = useCallback(() => {
// Your function logic
}, [dependency1, dependency2]);

 memoizedCallback is the cached function that only changes if any dependency


changes.
 The dependencies ensure the function is updated correctly when needed.

Why Use it?


 To avoid unnecessary re-renders of child components that receive functions as
props, by giving them stable function references.
 To optimize performance in large or complex apps with expensive renders.
 When you want to avoid recreating functions unless necessary.

Simple Example
jsx
import React, { useState, useCallback } from 'react';

const Button = React.memo(({ onClick, children }) => {


console.log("Button re-rendered");
return <button onClick={onClick}>{children}</button>;
});

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

// Memoized callback - function identity stable unless dependencies (empty here) change
const increment = useCallback(() => {
setCount(c => c + 1);
}, []);

return (
<div>
<p>Count: {count}</p>
<Button onClick={increment}>Increment</Button>
</div>
);

MS. ESHA VINAY PATEL 61


UNIT 2 : FUNDAMENTALS OF REACT.JS

export default App;

Explanation:

 Button is wrapped in React.memo to prevent re-renders if props do not change.


 Without useCallback, the increment function would be recreated every render,
causing Button to re-render.
 With useCallback, the function stays the same across renders, so Button only re-
renders when the count changes.

Key Points
Aspect Description

What it does Memoizes a function to keep the same reference between renders

When to use Passing callbacks to child components to avoid unnecessary renders

Dependencies Functions recreate only if dependencies change

Main benefit Performance optimization by reducing prop changes triggering renders

Works with React.memo and other memoization strategies

Complete useCallback with React.memo Example in


Create React App
1. App.js
jsx
import React, { useState, useCallback } from "react";

// Child button component wrapped with React.memo to avoid unnecessary re-renders


const Button = React.memo(({ onClick, children }) => {
console.log(`Button "${children}" rendered`);
return <button onClick={onClick} style={{ marginRight: 10 }}>{children}</button>;
});

function App() {
const [count, setCount] = useState(0);
const [text, setText] = useState("");

// useCallback memoizes increment function so it does not change on every render


const increment = useCallback(() => {

MS. ESHA VINAY PATEL 62


UNIT 2 : FUNDAMENTALS OF REACT.JS

setCount((c) => c + 1);


}, []); // No dependencies, so stable across renders

// This changeText handler is NOT memoized, so it will change on every render


const changeText = (e) => {
setText(e.target.value);
};

return (
<div style={{ padding: 20, fontFamily: "Arial, sans-serif" }}>
<h1>useCallback with React.memo Demo</h1>

<div>
<p>Count: {count}</p>
<Button onClick={increment}>Increment</Button>
</div>

<div style={{ marginTop: 20 }}>


<input
type="text"
value={text}
onChange={changeText}
placeholder="Type something..."
style={{ padding: 5, width: 300 }}
/>
<p>Typed Text: {text}</p>
</div>
</div>
);
}

export default App;

2. How This Works


 The Button component is wrapped with React.memo, so it only re-renders if its
props change.
 The increment function is wrapped with useCallback and has an empty
dependencies array, so its identity remains the same across renders.
 When you type text in the input box, the parent App re-renders, but the Button does
NOT re-render because increment function reference is stable.
 If you remove useCallback and define increment inline without memoization, the
Button re-renders on every keystroke because a new function is created each render.
 This optimization is beneficial in large trees or expensive components.

3. Console Output Behavior


 On initial render, you see:

text
Button "Increment" rendered

MS. ESHA VINAY PATEL 63


UNIT 2 : FUNDAMENTALS OF REACT.JS

 When you type in the text input, since increment is memoized, the button does not
re-render (no log shown).
 When you click the increment button, count changes and app re-renders—but Button
also doesn't re-render unnecessarily due to stable function prop.

4. Running This Example


 Create a new React app or use an existing one.
 Replace the contents of src/App.js with above code.
 Run with npm start or yarn start.
 Open browser console to observe render logs.

5. Summary Table
Concept With useCallback Without useCallback
New function created each
Function prop identity Stable, same function instance
render
Child re-render with
Prevented if props unchanged Triggered on every parent render
React.memo

Performance impact Avoids unnecessary renders May cause extra renders


Passing callbacks down to Not needed for inline usage or
Usage scenario
memoized children simple cases

What is useMemo?
The React useMemo hook is used to memoize the result of an expensive function or
calculation so that it only recomputes when its dependencies change. This optimization helps
avoid costly recalculations on every render and can improve performance, especially in
components with heavy computations or when passing computed values to pure components.

 It remembers (caches) the output of a function between renders.


 Runs the function only when specified dependencies change.
 Returns the memoized value.
 Useful for expensive calculations or to maintain stable references (like arrays or
objects) to prevent unnecessary re-renders in children.

Syntax
jsx
const memoizedValue = useMemo(() => {
// expensive calculation here
return computeValue;
}, [dependency1, dependency2]);

MS. ESHA VINAY PATEL 64


UNIT 2 : FUNDAMENTALS OF REACT.JS

 The function inside useMemo runs on first render and when any dependency changes.
 Otherwise, it returns the cached value from the previous render.

Example of useMemo (Expensive Calculation)


jsx
import React, { useState, useMemo } from 'react';

function isPrime(num) {
for (let i = 2; i <= Math.sqrt(num); i++) {
if (num % i === 0) return false;
}
return num > 1;
}

function PrimeCalculator() {
const [number, setNumber] = useState(100000);
const [inc, setInc] = useState(0);

// Expensive calculation: find primes up to 'number'


const primes = useMemo(() => {
console.log('Calculating primes...');
let primesList = [];
for (let i = 2; i <= number; i++) {
if (isPrime(i)) {
primesList.push(i);
}
}
return primesList;
}, [number]);

return (
<div>
<input
type="number"
value={number}
onChange={e => setNumber(Number(e.target.value))}
/>
<p>Primes up to {number} calculated: {primes.length}</p>
<button onClick={() => setInc(inc + 1)}>Re-render {inc}</button>
</div>
);
}

 The prime calculation runs only when number changes.


 Clicking the re-render button does not compute primes again.

Combining useCallback with useMemo


While useMemo memoizes values, useCallback memoizes functions. Combining both can
optimize performance by:

 Keeping function references stable when passing them as props to child components
wrapped with React.memo, preventing unnecessary re-renders.

MS. ESHA VINAY PATEL 65


UNIT 2 : FUNDAMENTALS OF REACT.JS

 Memoizing calculated data that the component or children rely on.

Combined Example: useCallback with useMemo


jsx
import React, { useState, useMemo, useCallback } from 'react';

const List = React.memo(({ items, onAdd }) => {


console.log('List rendered');
return (
<div>
<ul>
{items.map(item => (
<li key={item}>{item}</li>
))}
</ul>
<button onClick={() => onAdd('Item ' + (items.length + 1))}>Add Item</button>
</div>
);
});

function App() {
const [items, setItems] = useState(['Item 1', 'Item 2']);
const [multiplier, setMultiplier] = useState(1);

// Memoize transformed list to avoid recalculations


const multipliedItems = useMemo(() => {
console.log('Calculating multiplied items');
return items.map(item => item + ' x' + multiplier);
}, [items, multiplier]);

// Memoize callback to prevent passing new function on every render


const handleAdd = useCallback((newItem) => {
setItems(prevItems => [...prevItems, newItem]);
}, []);

return (
<div>
<h3>useCallback & useMemo Example</h3>

<label>
Multiplier:
<input
type="number"
value={multiplier}
onChange={(e) => setMultiplier(Number(e.target.value))}
/>
</label>

{/* Pass memoized values and callback to memoized child */}


<List items={multipliedItems} onAdd={handleAdd} />
</div>
);
}

export default App;

MS. ESHA VINAY PATEL 66


UNIT 2 : FUNDAMENTALS OF REACT.JS

 multipliedItems is memoized with useMemo and recalculates only when items or


multiplier change.
 handleAdd callback is memoized with useCallback to keep the function identity
stable.
 List is wrapped with React.memo and only re-renders when items or onAdd change.
 Typing in the multiplier input triggers recalculation of displayed items without
unnecessary re-renders.
 Adding an item updates the list and re-renders appropriately.

Summary Table
Hook Purpose Memoizes

useMemo Memoize value or result of calculation Expensive computed values

useCallback Memoize function reference Functions passed as props or dependencies

Full Create React App Example: useMemo with


useCallback

1. App.js
jsx
import React, { useState, useMemo, useCallback } from 'react';

// Memoized child component using React.memo


const List = React.memo(({ items, onAdd }) => {
console.log('List component rendered');
return (
<div>
<ul>
{items.map((item) => (
<li key={item}>{item}</li>
))}
</ul>
<button onClick={() => onAdd('Item ' + (items.length + 1))}>
Add Item
</button>
</div>
);
});

function App() {
const [items, setItems] = useState(['Item 1', 'Item 2']);
const [multiplier, setMultiplier] = useState(1);

// Memoize multipliedItems to avoid recalculating on unrelated renders


const multipliedItems = useMemo(() => {
console.log('Calculating multiplied items...');
return items.map((item) => item + ' x' + multiplier);

MS. ESHA VINAY PATEL 67


UNIT 2 : FUNDAMENTALS OF REACT.JS

}, [items, multiplier]);

// Memoize onAdd callback to prevent changing function reference on every render


const handleAdd = useCallback(
(newItem) => {
setItems((prevItems) => [...prevItems, newItem]);
},
[] // no dependencies: handleAdd identity stable
);

return (
<div style={{ padding: 20, fontFamily: 'Arial, sans-serif' }}>
<h1>useMemo & useCallback Example</h1>

<label style={{ display: 'block', marginBottom: 10 }}>


Multiplier:{' '}
<input
type="number"
value={multiplier}
onChange={(e) => setMultiplier(Number(e.target.value))}
style={{ width: 60, marginLeft: 10 }}
min="1"
/>
</label>

{/* Pass memoized items and callback to memoized List component */}
<List items={multipliedItems} onAdd={handleAdd} />
</div>
);
}

export default App;

2. How to Run
1. Create a new React project (if you don't have one):

bash
npx create-react-app memo-callback-demo
cd memo-callback-demo

2. Replace the contents of src/App.js with the code above.


3. Start the app:

bash
npm start

4. Open http://localhost:3000 in your browser.

3. What You’ll See and Behavior


 On initial load, the console prints:

text

MS. ESHA VINAY PATEL 68


UNIT 2 : FUNDAMENTALS OF REACT.JS

Calculating multiplied items...


List component rendered

 The list shows two items: Item 1 x1 and Item 2 x1.


 Changing the Multiplier input recalculates multipliedItems (console logs again),
and the list updates accordingly.
 Clicking the Add Item button appends a new item to the list.
 When you type in the multiplier input, the List component only re-renders if
multipliedItems changes since both the array and the onAdd function are
memoized.
 Because the handleAdd function is wrapped in useCallback, its reference stays the
same across renders, preventing unnecessary rerenders of List.

4. Key Takeaways
Concept Benefit in Example
Memoizes the calculated list so it only recalculates when dependencies change,
useMemo
optimizing rendering.
Memoizes the onAdd callback function so it has stable identity, preventing
useCallback
unnecessary child component renders.
React.memo Memoizes the List component to avoid re-rendering on unchanged props.

MS. ESHA VINAY PATEL 69


UNIT 2 : FUNDAMENTALS OF REACT.JS

2.4.3 Hook: Building custom hook, advantages and use

A custom hook in React is a JavaScript function whose name starts with use and which
allows you to extract and reuse stateful logic across multiple components. Custom hooks
enable you to share behavior without repeating code, making your components cleaner, more
modular, and easier to maintain.

How to Build a Custom Hook


1. Name it starting with use so React can apply the rules of hooks correctly (e.g.,
useFetch, useCounter).
2. Use built-in hooks like useState, useEffect, etc. inside your custom hook to
manage state, side effects, etc.
3. Encapsulate reusable logic that is needed in multiple components.
4. Return values or functions from your custom hook to be used in components.

Example: Building a Custom Hook useFetch


Instead of duplicating data fetching logic in multiple components, you create a hook like this:

jsx
import { useState, useEffect } from 'react';

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

useEffect(() => {
setLoading(true);
setError(null);

fetch(url)
.then((res) => {
if (!res.ok) {
throw new Error('Network response was not ok');
}
return res.json();
})
.then((data) => {
setData(data);
setLoading(false);
})
.catch((error) => {
setError(error.message);
setLoading(false);
});
}, [url]);

return { data, loading, error };


}

MS. ESHA VINAY PATEL 70


UNIT 2 : FUNDAMENTALS OF REACT.JS

export default useFetch;

Usage in a component:

jsx
import React from 'react';
import useFetch from './useFetch';

function Todos() {
const { data, loading, error } = useFetch('https://jsonplaceholder.typicode.com/todos');

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


if (error) return <p>Error: {error}</p>;

return (
<ul>
{data.map(todo => <li key={todo.id}>{todo.title}</li>)}
</ul>
);
}

Advantages of Custom Hooks


 Reusability: Share logic easily across multiple components.
 Separation of Concerns: Keep component code clean by moving complex logic into
hooks.
 Testability: You can test the custom hook separately from UI.
 Maintainability: Changes to shared logic happen in one place.
 Abstraction: Encapsulate implementation details; components just use the hook
interface.

When to Use Custom Hooks


 When multiple components share the same stateful or effectful logic (e.g., data
fetching, subscriptions, form handling).
 To avoid repeating code for common functionality.
 To abstract complex logic into readable and reusable APIs.

Summary Table
Aspect Description

What is a custom hook? A reusable function that contains hook logic

Naming convention Starts with use

Use cases Shared state management, side effects, utilities

MS. ESHA VINAY PATEL 71


UNIT 2 : FUNDAMENTALS OF REACT.JS

Aspect Description

Benefits Reusability, abstraction, cleaner components

Example hooks useFetch, useLocalStorage, useCounter

Complete Create React App Example:


Custom Hooks
Project Structure (in src/):
text
src/
App.js
useFetch.js
useCounter.js
useLocalStorage.js
index.js

1. useFetch.js — Custom Hook for Data Fetching


jsx
import { useState, useEffect } from 'react';

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

useEffect(() => {
if (!url) return;

setLoading(true);
setError(null);

fetch(url)
.then((response) => {
if (!response.ok) throw new Error('Network response was not ok');
return response.json();
})
.then((json) => {
setData(json);
setLoading(false);
})
.catch((err) => {
setError(err.message);
setLoading(false);
});

MS. ESHA VINAY PATEL 72


UNIT 2 : FUNDAMENTALS OF REACT.JS

}, [url]);

return { data, loading, error };


}

export default useFetch;

2. useCounter.js — Custom Hook for Counter Logic


jsx
import { useState } from 'react';

function useCounter(initialValue = 0) {
const [count, setCount] = useState(initialValue);

const increment = () => setCount(c => c + 1);


const decrement = () => setCount(c => c - 1);
const reset = () => setCount(initialValue);

return { count, increment, decrement, reset };


}

export default useCounter;

3. useLocalStorage.js — Custom Hook for Local Storage Sync


jsx
import { useState, useEffect } from 'react';

function useLocalStorage(key, initialValue) {


const [storedValue, setStoredValue] = useState(() => {
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch {
return initialValue;
}
});

useEffect(() => {
try {
window.localStorage.setItem(key, JSON.stringify(storedValue));
} catch {
// Ignore write errors
}
}, [key, storedValue]);

return [storedValue, setStoredValue];


}

export default useLocalStorage;

4. App.js — Using All Custom Hooks in a Single Component


jsx

MS. ESHA VINAY PATEL 73


UNIT 2 : FUNDAMENTALS OF REACT.JS

import React from 'react';


import useFetch from './useFetch';
import useCounter from './useCounter';
import useLocalStorage from './useLocalStorage';

function App() {
// Using useFetch to get todo items
const { data: todos, loading, error } = useFetch('https://jsonplaceholder.typicode.com/todos?_limit=5');

// Using useCounter to manage count


const { count, increment, decrement, reset } = useCounter(10);

// Using useLocalStorage to persist a name


const [name, setName] = useLocalStorage('name', '');

return (
<div style={{ fontFamily: 'Arial, sans-serif', padding: 20 }}>
<h1>Custom Hooks Demo</h1>

{/* useFetch Example */}


<section>
<h2>Todos (fetched with useFetch)</h2>
{loading && <p>Loading todos...</p>}
{error && <p style={{ color: 'red' }}>Error: {error}</p>}
{todos && (
<ul>
{todos.map(todo => (
<li key={todo.id}>
{todo.title} {todo.completed ? "(Done)" : "(Pending)"}
</li>
))}
</ul>
)}
</section>

<hr />

{/* useCounter Example */}


<section>
<h2>Counter (managed with useCounter)</h2>
<p>Count: {count}</p>
<button onClick={increment} style={{ marginRight: 8 }}>Increment</button>
<button onClick={decrement} style={{ marginRight: 8 }}>Decrement</button>
<button onClick={reset}>Reset</button>
</section>

<hr />

{/* useLocalStorage Example */}


<section>
<h2>Local Storage (managed with useLocalStorage)</h2>
<label>
Name:{" "}
<input
type="text"
value={name}
onChange={e => setName(e.target.value)}
placeholder="Enter your name"
style={{ padding: 4, width: 200 }}

MS. ESHA VINAY PATEL 74


UNIT 2 : FUNDAMENTALS OF REACT.JS

/>
</label>
{name && <p>Hello, {name}!</p>}
</section>
</div>
);
}

export default App;

5. index.js — React App Entry Point


jsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';

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


root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);

Explanation and Benefits


 useFetch encapsulates all logic related to fetching async data, managing loading and
error states.
 useCounter bundles common counter state and update functions into reusable logic.
 useLocalStorage syncs React state with localStorage automatically, managing
persistence.
 Each hook is independent, reusable, and encapsulates its own logic.
 Components using these hooks stay clean, concise, and focused on UI.
 Improves maintainability, testability, and code reuse.

MS. ESHA VINAY PATEL 75


UNIT 2 : FUNDAMENTALS OF REACT.JS

Complete Create React App Sample


1. Project Structure
text
src/
App.js
ThemeContext.js
Counter.js
UserProfile.js
useCustomFetch.js
index.js

2. ThemeContext.js (Context for Theme and User)


jsx
import React from 'react';

export const ThemeContext = React.createContext({


theme: 'light',
toggleTheme: () => {},
user: { name: 'Guest' },
});

3. useCustomFetch.js (Sample Custom Hook for Fetching Data)


jsx
import { useState, useEffect } from 'react';

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

useEffect(() => {
if (!url) return;

setLoading(true);
setError(null);
fetch(url)
.then(res => {
if (!res.ok) throw new Error('Fetch error');
return res.json();
})
.then(json => {
setData(json);
setLoading(false);
})
.catch(err => {
setError(err.message);
setLoading(false);
});

MS. ESHA VINAY PATEL 76


UNIT 2 : FUNDAMENTALS OF REACT.JS

}, [url]);

return { data, loading, error };


}

export default useCustomFetch;

4. Counter.js (useState, useEffect, useRef, useReducer)


jsx
import React, { useState, useEffect, useRef, useReducer } from 'react';

const initialState = { count: 0 };

function reducer(state, action) {


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

function Counter() {
const [count, setCount] = useState(0);
const [state, dispatch] = useReducer(reducer, initialState);
const prevCountRef = useRef();

useEffect(() => {
prevCountRef.current = count; // Track previous count
}, [count]);

useEffect(() => {
console.log(`useReducer count changed: ${state.count}`);
}, [state.count]);

return (
<div>
<h2>useState Count: {count}</h2>
<button onClick={() => setCount(c => c + 1)}>Increment useState</button>
<p>Previous useState Count: {prevCountRef.current || 0}</p>

<h2>useReducer Count: {state.count}</h2>


<button onClick={() => dispatch({ type: 'increment' })}>Increment useReducer</button>
<button onClick={() => dispatch({ type: 'decrement' })}>Decrement useReducer</button>
<button onClick={() => dispatch({ type: 'reset' })}>Reset useReducer</button>
</div>
);
}

export default Counter;

5. UserProfile.js (useContext)
jsx
import React, { useContext } from 'react';
import { ThemeContext } from './ThemeContext';

MS. ESHA VINAY PATEL 77


UNIT 2 : FUNDAMENTALS OF REACT.JS

function UserProfile() {
const { user, theme, toggleTheme } = useContext(ThemeContext);

return (
<div style={{
padding: '1rem',
backgroundColor: theme === 'dark' ? '#222' : '#eee',
color: theme === 'dark' ? '#eee' : '#111',
borderRadius: 4,
marginBottom: 20,
}}>
<h3>User Profile</h3>
<p>Name: {user.name}</p>
<p>Theme: {theme}</p>
<button onClick={toggleTheme}>Toggle Theme</button>
</div>
);
}

export default UserProfile;

6. App.js (Combining all hooks, memo, callback, custom


hook)
jsx
import React, { useState, useCallback, useMemo } from 'react';
import { ThemeContext } from './ThemeContext';
import Counter from './Counter';
import UserProfile from './UserProfile';
import useCustomFetch from './useCustomFetch';

// Memoized Button with useCallback


const Button = React.memo(({ onClick, children }) => {
console.log(`Button "${children}" rendered`);
return <button onClick={onClick} style={{ marginRight: 8 }}>{children}</button>;
});

function App() {
const [theme, setTheme] = useState('light');
const [user, setUser] = useState({ name: 'Alice' });
const { data, loading, error } = useCustomFetch('https://jsonplaceholder.typicode.com/todos?_limit=3');
const [multiplier, setMultiplier] = useState(1);
const [items, setItems] = useState(['Item 1', 'Item 2']);

// Toggle theme callback


const toggleTheme = useCallback(() => {
setTheme(t => (t === 'light' ? 'dark' : 'light'));
}, []);

// Memoize multiplied items list


const multipliedItems = useMemo(() => {
console.log('Calculating multiplied items');
return items.map(item => `${item} x${multiplier}`);
}, [items, multiplier]);

// Memoized handler

MS. ESHA VINAY PATEL 78


UNIT 2 : FUNDAMENTALS OF REACT.JS

const addItem = useCallback(() => {


setItems(prev => [...prev, `Item ${prev.length + 1}`]);
}, []);

const appStyle = {
padding: 20,
backgroundColor: theme === 'dark' ? '#121212' : '#fafafa',
color: theme === 'dark' ? '#eee' : '#222',
minHeight: '100vh',
fontFamily: 'Arial, sans-serif',
};

return (
<ThemeContext.Provider value={{ theme, toggleTheme, user }}>
<div style={appStyle}>
<h1>React.js Fundamentals Combined Example</h1>

{/* UserProfile uses useContext */}


<UserProfile />

{/* Counter uses useState, useReducer, useRef, useEffect */}


<Counter />

<hr />

{/* Fetch with custom hook */}


<section>
<h2>Todos fetched with Custom Hook</h2>
{loading && <p>Loading todos...</p>}
{error && <p style={{ color: 'red' }}>{error}</p>}
{data && <ul>{data.map(todo => <li key={todo.id}>{todo.title}</li>)}</ul>}
</section>

<hr />

{/* Memo & Callback Example */}


<section>
<h2>useMemo & useCallback Example</h2>
<label>
Multiplier:{' '}
<input
type="number"
value={multiplier}
onChange={(e) => setMultiplier(Number(e.target.value) || 1)}
min="1"
style={{ width: 60 }}
/>
</label>
<ul>
{multipliedItems.map((item, i) => (
<li key={i}>{item}</li>
))}
</ul>
<Button onClick={addItem}>Add Item</Button>
</section>
</div>
</ThemeContext.Provider>
);
}

MS. ESHA VINAY PATEL 79


UNIT 2 : FUNDAMENTALS OF REACT.JS

export default App;

7. index.js
jsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';

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


root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);

Explanation and Output


 The App component integrates fundamental React concepts like state, context, side
effects, refs, reducers, memoization, and custom hooks.
 Counter demonstrates useState, useReducer, useRef, and useEffect.
 UserProfile uses useContext to consume theme and user data, toggling the theme.
 useCustomFetch hook fetches async data with loading and error UI.
 useMemo and useCallback optimize list recalculation and stable function references
preventing unnecessary re-renders.
 Output will show a theme toggle with live styling, a counter with two state
management approaches, fetched todos, and a dynamic multiplied list with add
button.

MS. ESHA VINAY PATEL 80

You might also like