0% found this document useful (0 votes)
34 views176 pages

Web Technology 512 Learner Guide

The document is a student guide for the Web Technology 512 module at Richfield Graduate Institute of Technology, detailing the curriculum and structure of the Information Technology programs. It covers advanced JavaScript concepts and the React.js framework, emphasizing practical skills for developing dynamic web applications. The guide outlines the qualifications offered, including the Higher Certificate, Diploma, and Bachelor of Science in IT, aimed at preparing students for various roles in the IT sector.

Uploaded by

b4wb5s6dy5
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)
34 views176 pages

Web Technology 512 Learner Guide

The document is a student guide for the Web Technology 512 module at Richfield Graduate Institute of Technology, detailing the curriculum and structure of the Information Technology programs. It covers advanced JavaScript concepts and the React.js framework, emphasizing practical skills for developing dynamic web applications. The guide outlines the qualifications offered, including the Higher Certificate, Diploma, and Bachelor of Science in IT, aimed at preparing students for various roles in the IT sector.

Uploaded by

b4wb5s6dy5
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

STUDENT GUIDE

FACULTY OF INFORMATION TECHNOLOGY

WEB TECHNOLOGY 512


Registered with the Department of Higher Education as a Private Higher Education Institution under the

Higher Education Act, 1997.

Registration Certificate No. 2000/HE07/008

FACULTY OF INFORMATION TECHNOLOGY

LEARNER GUIDE

MODULE: WEB TECHNOLOGY 512


(2nd SEMESTER)

PREPARED ON BEHALF OF
RICHFIELD GRADUATE INSTITUTE OF TECHNOLOGY (PTY) LTD

RICHFIELD GRADUATE INSTITUTE OF TECHNOLOGY (Pty) Ltd

Registration Number: 2000/000757/07

All rights reserved; no part of this publication may be reproduced in any form or by any means, including photocopying
machines, without the written permission of the Institution.
Naik, P.G. and Oza, K.S. (2023) Awesome
[Link]: unleash the power of modern UI
building. International Institute of Organized R

Banks, A. and Porcello, E. (2017) Learning


React: functional web development with React
and Redux. Sebastopol, CA: O'Reilly Media.
1 Fundamental JavaScript for React .............................................................................. 9

1.1 Introduction .................................................................................................................... 9

1.2 Evolution of JavaScript and ES6+ .................................................................................. 10

1.3 Variables and Scope in Modern JavaScript ................................................................... 11

1.4 Functions in JavaScript .................................................................................................. 14

1.5 De-structuring ............................................................................................................... 16

1.6 The Spread Operator and Rest Parameters .................................................................. 19

1.7 Template Literals .......................................................................................................... 22

1.8 JavaScript Type System ................................................................................................. 23

1.9 Array Methods for Functional Programming ................................................................ 27

1.10 JavaScript Modules ....................................................................................................... 29

1.11 Asynchronous JavaScript Concepts............................................................................... 31

1.12 Best Practices for React Development ......................................................................... 34

1.13 Summary ....................................................................................................................... 37

1.14 Review Questions ......................................................................................................... 38

2 Introduction to React JS ............................................................................................ 40

2.1 Introduction .................................................................................................................. 40

2.2 What is React? .............................................................................................................. 41

2.3 Setting Up the Development Environment .................................................................. 43

2.4 Understanding Components ......................................................................................... 45

2.5 Working with Props ...................................................................................................... 49

2.6 State and Interactivity................................................................................................... 53

2.7 Building Interactive Components ................................................................................. 61


2.8 Best Practices and Common Patterns........................................................................... 72

2.9 Summary ....................................................................................................................... 73

2.10 Review Questions ......................................................................................................... 74

3 The lifecycle of a component .................................................................................... 77

3.1 Introduction to a Component Lifecycle? ...................................................................... 77

3.2 Lifecycle Phases in Class Components .......................................................................... 79

3.3 Functional Components and Lifecycle Using Hooks ..................................................... 81

3.4 Key Lifecycle Use Cases ................................................................................................. 85

3.5 Topic summary .............................................................................................................. 87

3.6 Review questions .......................................................................................................... 88

4 React JSX ................................................................................................................... 93

4.1 Introduction to React JSX .............................................................................................. 93

4.2 JSX Syntax and Structure............................................................................................... 95

4.3 Conditional Rendering in JSX ........................................................................................ 99

4.4 Event Handling in JSX .................................................................................................. 101

4.5 Styling in JSX ................................................................................................................ 106

4.6 JSX Performance Considerations ................................................................................ 110

4.7 Accessibility in JSX ....................................................................................................... 113

4.8 Best Practices and Common Patterns......................................................................... 118

4.9 Chapter Summary ....................................................................................................... 120

5 Building Apps in ReactJS ......................................................................................... 122

5.1 Introduction to ReactJS ............................................................................................... 122

5.1.2 Primary Applications of React ................................................................................. 123

5.2 Essential Software for React Development ................................................................ 124


5.3 First Single Page application (Hello World) ................................................................ 128

5.4 React Components ...................................................................................................... 132

5.5 Event Handler in React................................................................................................ 138

5.6 Understanding Hooks ................................................................................................. 143

5.7 Working with Hooks.................................................................................................... 148

5.8 Lists and Keys in React JS ............................................................................................ 152

5.9 Building Forms in React .............................................................................................. 157

5.10 Gym Membership Sign up Form Example .................................................................. 162


The Information Technology (IT) qualification at Richfield College is a dynamic and future-focused
program designed to equip students with advanced technical, analytical, and problem-solving
skills. At the core of the qualification is a commitment to academic excellence, industry alignment,
and innovation, fostering graduates who are proficient in addressing modern technological
challenges. This qualification strategically integrates theoretical knowledge with practical
applications, preparing students for various roles in the IT sector. The IT program is structured to
address the growing complexity of the evolving technological landscape.

The Higher certificate in Information Technology (HCIT) program is a foundational stepping-stone


for students who wish to pursue further studies or enter the workforce. Graduates of this program
are well-prepared to articulate to the Diploma in IT (DIT) or the Bachelor of Science in IT (BSc IT)
qualifications, providing a seamless transition for those seeking to deepen their knowledge and
skills in specialized IT areas. Additionally, the program equips students with the essential
competencies for entry-level IT roles such as IT Support Technicians, Junior Web/ System
Developers, IT Administrators, etc.

The Diploma in Information Technology (DIT) is a comprehensive and practical program designed
to build a strong foundation in IT principles while equipping students with the hands-on skills
required to meet industry demands. Focused on both theoretical knowledge and applied
learning, this qualification prepares students for intermediate-level roles in IT and serves as a
stepping-stone for further academic progression or specialization. Graduates of this program are
well-prepared to articulate to the Bachelor of Science in IT (BSc IT) qualification. The curriculum
covers programming, networking, database management, system analysis etc., ensuring
graduates possess the competencies to solve real-world IT challenges effectively.

The Bachelor of Science in IT (BSc IT) program is structured to address the growing complexity of
the evolving technological landscape. Through carefully curated modules, students gain a deep
understanding of software development, database management, cloud computing,
cybersecurity, IT management, artificial intelligence, machine learning, networking etc.
Graduates of this program are well-prepared to articulate to the Bachelor of Science Honours in
IT qualification. The curriculum is designed to bridge the gap between academic learning and real-
world applications, thus fostering innovation and an entrepreneurial mindset. Students are
encouraged to participate in research and practical learning.

The programming focus within the IT qualification exemplifies academic innovation and
professional alignment. By integrating a diverse range of programming languages with practical
application, the curriculum prepares students to excel in the rapidly evolving tech industry. The
program aligns with industry courses from globally recognized leading tech giants, such as Oracle,
AWS, IBM, etc ensures that graduates possess the credentials to validate their expertise in
software development and cloud-based technologies. This blend of foundational knowledge,
practical experience, and industry-standard courses prepares students for immediate
employment and establishes a strong basis for long-term career advancement in software
development.

Web Technology 512 builds on foundational web development skills by introducing students to
advanced JavaScript concepts and the modern [Link] framework. Students learn to develop
dynamic, responsive, and component-based user interfaces while mastering key techniques such
as state management, event handling, and lifecycle methods. The module emphasizes practical,
real-world development practices, enabling students to build scalable single-page applications
(SPAs) using React. By the end of the course, students are equipped with the skills to create
interactive and efficient web applications, preparing them for advanced roles in frontend and full-
stack development.
1 Fundamental JavaScript for React

Learning Objective

By the end of this chapter, students will be able to:

• Understand the evolution of JavaScript and the importance of ES6+ features,


• Explain the concepts of variables, scope, and constants in modern JavaScript,
• Describe the differences between traditional functions and arrow functions,
• Understand de-structuring, spread operators, and their applications,
• Comprehend JavaScript's type system and data structures,
• Explain the module system and its importance in modern web development.

1.1 Introduction

JavaScript has evolved significantly since its creation in 1995. The introduction of ECMAScript
2015 (ES6) marked a major milestone in the language's evolution, bringing features that made
JavaScript more powerful and easier to work with. React, being a modern JavaScript library,
heavily relies on these ES6+ features. Understanding these fundamentals is crucial before
embarking on React development.

This chapter provides a theoretical foundation of JavaScript concepts that are essential for React
development. We will explore the language features, their purposes, and their significance in
modern web development. While the focus is on understanding concepts, we'll include practical
examples to illustrate how these features work in real code. The knowledge gained here will serve
as the building blocks for understanding React's component-based architecture in subsequent
chapters.
1.2 Evolution of JavaScript and ES6+

1.2.1 Historical Context

JavaScript was created by Brendan Eich in just 10 days in 1995. Originally named Mocha, then
LiveScript, and finally JavaScript, the language was designed to add interactivity to web pages.
Despite its humble beginnings and initial limitations, JavaScript has grown to become one of the
most widely used programming languages in the world. The ECMAScript specification, first
published in 1997, standardized the language and provided a foundation for its evolution.

The early years of JavaScript were marked by browser incompatibilities and limited features.
Developers often had to write different code for different browsers, and the language lacked
many features that programmers took for granted in other languages. This situation persisted for
many years, with only minor updates to the language specification.

1.2.2 The ES6 Revolution

ECMAScript 2015, commonly known as ES6, represented the most significant update to
JavaScript since its creation. This update addressed many of the language's historical pain points
and introduced features that made JavaScript more suitable for large-scale application
development. The introduction of block-scoped variables through let and const keywords solved
issues with variable scoping that had plagued developers for years. Arrow functions provided a
more concise function syntax while also solving problems with the this keyword binding. Classes
brought a more familiar syntax for object-oriented programming, even though they were
syntactic sugar over JavaScript's prototype-based inheritance.

The module system introduced in ES6 finally gave JavaScript a standardized way to organize code
across multiple files, addressing the global namespace pollution that had been a significant issue
in large applications. Promises provided a better way to handle asynchronous operations, moving
away from the callback-heavy patterns that often led to deeply nested and hard-to-read code.
Destructuring assignment made it easier to extract data from arrays and objects, while template
literals solved the cumbersome string concatenation problems that developers frequently
encountered.

1.3 Variables and Scope in Modern JavaScript

1.3.1 Understanding Scope

Scope is a fundamental concept in programming that determines where variables can be


accessed in your code. In JavaScript, understanding scope is particularly important because of
the language's unique scoping rules and the historical quirks that ES6 aimed to address. JavaScript
has three types of scope: global scope, function scope, and block scope.

Global scope refers to variables that are accessible throughout your entire program. These
variables are declared outside any function or block and can be accessed from anywhere in your
code. While global variables can be convenient, they should be used sparingly as they can lead
to naming conflicts and make code harder to maintain and debug.

Function scope encompasses variables declared inside a function. These variables are only
accessible within that function and any nested functions inside it. This has been a fundamental
feature of JavaScript since its inception and provides a way to encapsulate variables and prevent
them from polluting the global namespace.

Block scope, introduced with ES6, refers to variables that are only accessible within the block in
which they are declared. A block is defined by curly braces, such as those used in if statements,
for loops, and other control structures. This addition brought JavaScript in line with many other
programming languages and solved numerous scoping issues that developers had struggled with.

1.3.2 Variable Declarations: var, let, and const

The traditional var keyword, which was the only way to declare variables in JavaScript before ES6,
has several characteristics that can lead to confusion and bugs.
Consider this example:

function demonstrateVar() {
[Link](x); // undefined (not an error!)
var x = 5;
if (true) {
var y = 10;
}
[Link](y); // 10 (accessible outside the block)
}

Variables declared with var are function-scoped or globally-scoped, meaning they ignore block
boundaries. They can also be re-declared within the same scope without causing an error, which
can lead to accidentally overwriting variables. Perhaps most confusingly, var declarations are
subject to hoisting, which means they are conceptually moved to the top of their containing
function or global scope, though only the declaration is hoisted, not the initialization.

The let keyword, introduced in ES6, addresses many of the issues with var. Here's how let
behaves differently:

function demonstrateLet() {
// [Link](x); // ReferenceError: Cannot access 'x' before initialization
let x = 5;
if (true) {
let y = 10;
[Link](y); // 10
}
// [Link](y); // ReferenceError: y is not defined
}
Variables declared with let are block-scoped, meaning they respect the boundaries of blocks
defined by curly braces. They cannot be re-declared within the same scope, which helps prevent
accidental variable overwrites. While let declarations are technically hoisted, they remain in a
"temporal dead zone" from the start of the block until the declaration is encountered, meaning
accessing them before declaration results in a ReferenceError rather than undefined.

The const keyword shares the block-scoping behavior of let but adds an additional constraint:
const PI = 3.14159;
// PI = 3.14; // TypeError: Assignment to constant variable
const user = { name: 'John', age: 30 };
[Link] = 31; // This is allowed - the object is mutable
// user = { name: 'Jane' }; // TypeError: Assignment to constant variable

The immutability only applies to the binding itself. Variables declared with const must be
initialized at the time of declaration, and attempting to declare a const without an initial value
will result in a syntax error.

1.3.3 Hoisting

Hoisting is one of JavaScript's most misunderstood features. It refers to the behavior where
variable and function declarations are conceptually moved to the top of their containing scope
during the compilation phase. However, it's important to understand that only the declarations
are hoisted, not the initializations.

Function declarations are fully hoisted, meaning both the declaration and the function body are
available throughout their containing scope. This allows functions to be called before they appear
in the code, which can be convenient but can also lead to confusion about the order of execution.

Variable declarations with var are hoisted, but their initialization remains at the original location
in the code. This means that accessing a var variable before its initialization line will return
undefined rather than causing an error. This behavior has been the source of many subtle bugs
in JavaScript programs.

The temporal dead zone for let and const declarations represents a significant improvement in
JavaScript's hoisting behavior. While these declarations are technically hoisted, accessing them
before their declaration results in a ReferenceError. This makes the code more predictable and
helps catch errors earlier in the development process.

1.4 Functions in JavaScript

1.4.1 Function Declaration vs Function Expression

Functions are first-class citizens in JavaScript, meaning they can be assigned to variables, passed
as arguments to other functions, and returned from functions. This flexibility has made JavaScript
particularly well-suited for functional programming patterns and event-driven programming.

Function declarations use the function keyword followed by a name, parameters in parentheses,
and a function body in curly braces:

// Function declaration - hoisted


[Link](add(2, 3)); // 5 - works before declaration!
function add(a, b) {
return a + b;
}
// Function expression - not hoisted
// [Link](subtract(5, 2)); // TypeError: subtract is not a function
const subtract = function(a, b) {
return a - b;
};
[Link](subtract(5, 2)); // 3 - works after declaration
These declarations are fully hoisted, meaning they can be called anywhere in their containing
scope, even before the line where they are declared. Function expressions involve creating a
function and assigning it to a variable. Unlike function declarations, function expressions are not
hoisted, so they cannot be called before they are defined in the code.

The choice between function declarations and expressions often comes down to the specific use
case and coding style preferences. Function declarations are often preferred for main functions
that represent key behaviors in a module, while function expressions are commonly used for
callbacks, event handlers, and functions that are passed as arguments.

1.4.2 Arrow Functions

Arrow functions, introduced in ES6, represent more than just a syntactic shorthand for writing
functions. They fundamentally change how the this keyword behaves and remove several
features of traditional functions that were rarely used and often caused confusion. Here's a
comparison:

// Traditional function
const traditional = function(x) {
return x * 2;
};
// Arrow function - concise syntax
const arrow = x => x * 2;
// Arrow function with multiple parameters
const add = (a, b) => a + b;
// Arrow function with block body
const complexCalc = (x, y) => {
const sum = x + y;
const product = x * y;
return sum + product;
};
The most visible benefit of arrow functions is their concise syntax. For simple functions that
return a single expression, arrow functions allow you to omit the function keyword, the curly
braces, and the return statement. This conciseness is particularly valuable when writing callbacks
for array methods or event handlers.

However, the most significant feature of arrow functions is their lexical this binding. In traditional
functions, the value of this depends on how the function is called. Arrow functions, on the other
hand, inherit this from their enclosing scope:

const obj = {
name: 'MyObject',
traditionalMethod: function() {
setTimeout(function() {
[Link]([Link]); // undefined - 'this' refers to global/window
}, 1000);
},
arrowMethod: function() {
setTimeout(() => {
[Link]([Link]); // 'MyObject' - 'this' is inherited
}, 1000);
}
};

Arrow functions also lack their own arguments object, cannot be used as constructors with the
new keyword, and don't have a prototype property. These omissions might seem limiting, but
they actually encourage cleaner, more predictable code.

1.5 De-structuring

De-structuring is a powerful feature introduced in ES6 that allows you to extract values from
arrays or properties from objects and assign them to variables in a more concise and readable
way. This feature has become particularly important in React development, where it's commonly
used to extract props and state values.

1.5.1 The Concept of De-structuring

Before de-structuring, extracting multiple values from an object or array required multiple
statements, each accessing the structure and assigning to a variable. This approach was verbose
and became particularly cumbersome when dealing with nested structures. De-structuring solves
this problem by allowing you to unpack values using a syntax that mirrors the structure of the
data.

The power of de-structuring extends beyond simple convenience. It makes function parameters
more self-documenting by clearly showing what properties of an object argument are being used.
It also enables functions to effectively return multiple values by returning an object or array that
can be immediately de-structured by the caller.

1.5.2 Object De-structuring

Object de-structuring uses curly braces on the left side of an assignment to extract properties
from an object. Here's how it works in practice:

// Basic object destructuring


const person = {
firstName: 'John',
lastName: 'Doe',
age: 30,
email: 'john@[Link]'
};
// Without destructuring
const firstName = [Link];
const lastName = [Link];
// With destructuring
const { firstName, lastName } = person;
// Renaming variables
const { firstName: fName, lastName: lName } = person;
// Default values
const { country = 'USA' } = person; // country will be 'USA'
// Nested destructuring
const user = {
id: 1,
profile: {
name: 'Jane',
preferences: {
theme: 'dark'
}
}
};
const { profile: { name, preferences: { theme } } } = user;
[Link](name); // 'Jane'
[Link](theme); // 'dark'

One of the most useful features of object de-structuring is the ability to provide default values. If
a property doesn't exist in the object or its value is undefined, the default value will be used
instead. This feature helps make code more robust by gracefully handling missing data.

1.5.3 Array De-structuring

Array de-structuring works similarly to object de-structuring but uses square brackets instead of
curly braces:

// Basic array destructuring


const colors = ['red', 'green', 'blue', 'yellow'];
// Without destructuring
const firstColor = colors[0];
const secondColor = colors[1];
// With destructuring
const [first, second] = colors;
// Skipping elements
const [, , third] = colors; // third = 'blue'
// Rest operator with destructuring
const [primary, ...otherColors] = colors;
[Link](primary); // 'red'
[Link](otherColors); // ['green', 'blue', 'yellow']
// Default values
const [a, b, c = 'default'] = ['x', 'y'];
[Link](c); // 'default'
// Swapping variables
let x = 1, y = 2;
[x, y] = [y, x];
[Link](x); // 2
[Link](y); // 1

The key difference is that array de-structuring is based on position rather than property names.
The first variable gets the first element, the second variable gets the second element, and so on.
You can skip elements in an array by leaving empty spaces between commas.

1.6 The Spread Operator and Rest Parameters

1.6.1 Spread Operator (...)

The spread operator, denoted by three dots (...), is one of the most versatile features introduced
in ES6. When used with arrays, it expands the array into individual elements:

// Array spreading
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
// Combining arrays
const combined = [...arr1, ...arr2]; // [1, 2, 3, 4, 5, 6]
// Copying arrays (shallow copy)
const copy = [...arr1]; // [1, 2, 3]
// Adding elements
const withExtra = [0, ...arr1, 4]; // [0, 1, 2, 3, 4]
// Converting iterables to arrays
const letters = [..."hello"]; // ['h', 'e', 'l', 'l', 'o']

The spread operator also works with objects, though this feature was added in ES2018 rather
than ES6:
// Object spreading
const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };
// Merging objects
const merged = { ...obj1, ...obj2 }; // { a: 1, b: 2, c: 3, d: 4 }
// Copying objects (shallow copy)
const copy = { ...obj1 }; // { a: 1, b: 2 }
// Overriding properties
const updated = { ...obj1, b: 3 }; // { a: 1, b: 3 }
// Adding properties
const extended = { ...obj1, c: 3 }; // { a: 1, b: 2, c: 3 }

In function calls, the spread operator can expand an array into individual arguments:

const numbers = [1, 2, 3, 4, 5];


[Link]([Link](...numbers)); // 5
// Equivalent to:
// [Link]([Link](1, 2, 3, 4, 5));
1.6.2 Rest Parameters

Rest parameters use the same three-dot syntax as the spread operator but serve the opposite
purpose. While spread expands elements, rest parameters collect multiple elements into an
array:

// Rest parameters in functions


function sum(...numbers) {
return [Link]((total, num) => total + num, 0);
}
[Link](sum(1, 2, 3)); // 6
[Link](sum(1, 2, 3, 4, 5)); // 15
// Combining regular parameters with rest
function greet(greeting, ...names) {
return `${greeting} ${[Link](' and ')}!`;
}
[Link](greet('Hello', 'Alice', 'Bob')); // 'Hello Alice and Bob!'
// Rest in destructuring
const [first, ...rest] = [1, 2, 3, 4, 5];
[Link](first); // 1
[Link](rest); // [2, 3, 4, 5]

Rest parameters provide a cleaner alternative to the arguments object that has been available in
JavaScript functions since the beginning. Unlike arguments, which is an array-like object, rest
parameters create a real array with all array methods available.
1.7 Template Literals

Template literals, also called template strings, revolutionized string handling in JavaScript. Before
their introduction, creating strings with dynamic content required concatenation with the plus
operator, which quickly became unwieldy with complex strings.

1.7.1 Features of Template Literals

Template literals are enclosed in backticks rather than single or double quotes. This simple
change enables several powerful features:

// Basic string interpolation


const name = 'Alice';
const age = 25;
// Old way with concatenation
const message1 = 'Hello, my name is ' + name + ' and I am ' + age + ' years old.';
// Template literal
const message2 = `Hello, my name is ${name} and I am ${age} years old.`;
// Expressions in template literals
const price = 19.99;
const tax = 0.15;
const total = `Total: $${(price + price * tax).toFixed(2)}`; // 'Total: $22.99'
// Multi-line strings
const multiline = `
This is a multi-line string.
It preserves line breaks and indentation.
No need for escape characters or concatenation.
`;
// Function calls in template literals
const uppercase = str => [Link]();
const emphasized = `Important: ${uppercase('please read carefully')}`;
String interpolation allows you to embed expressions directly within the string using the
${expression} syntax. These expressions are evaluated and their results are converted to strings
and inserted at that position. Multi-line strings become trivial with template literals, as line
breaks in the source code are preserved in the resulting string.

1.7.2 Benefits in React Development

In React development, template literals are frequently used for creating dynamic class names
based on component state or props. They make it easy to conditionally include CSS classes or
build class strings from multiple sources. The readability improvement over concatenation is
particularly valuable in JSX, where clarity is essential.

Template literals also excel at constructing URLs with query parameters or path segments. The
ability to embed expressions directly makes it clear what parts of the URL are dynamic and
reduces the chance of errors from incorrect concatenation.

1.8 JavaScript Type System

1.8.1 Primitive Types

JavaScript's type system is often misunderstood, partly because it differs significantly from
statically typed languages. JavaScript has seven primitive types, each serving a specific purpose
in the language. Let's explore them with examples:

// Number - represents both integers and floating-point numbers


const integer = 42;
const float = 3.14159;
const negative = -100;
// String - immutable sequences of characters
const single = 'Hello';
const double = "World";
const template = `Hello, ${single} ${double}`;
// Boolean - true or false
const isActive = true;
const isComplete = false;
// Undefined - variable declared but not assigned
let unassigned;
[Link](unassigned); // undefined
// Null - intentional absence of value
const emptyValue = null;
// Symbol - unique identifiers (ES6)
const sym1 = Symbol('id');
const sym2 = Symbol('id');
[Link](sym1 === sym2); // false - each symbol is unique
// BigInt - large integers (ES2020)
const bigNumber = 123456789012345678901234567890n;

The Number type represents both integers and floating-point numbers using double-precision
64-bit format. This can sometimes lead to precision issues with decimal arithmetic, which is
important to understand when working with financial calculations or other precision-sensitive
operations.

Strings in JavaScript are immutable, meaning once created, a string cannot be modified.
Operations that appear to modify strings actually create new strings. This immutability has
performance implications and affects how you should think about string manipulation in your
programs.
1.8.2 Object Types

In JavaScript, everything that isn't a primitive is an object. This includes obvious objects like plain
objects created with curly braces, but also arrays, functions, dates, regular expressions, and
more:

// Plain object
const person = {
name: 'John',
age: 30,
greet() {
return `Hello, I'm ${[Link]}`;
}
};
// Array (special type of object)
const numbers = [1, 2, 3, 4, 5];
[Link](typeof numbers); // 'object'
[Link]([Link](numbers)); // true
// Function (also an object!)
function add(a, b) {
return a + b;
}
[Link] = 'Adds two numbers'; // Functions can have properties
[Link]([Link]); // 'Adds two numbers'
// Date object
const now = new Date();
// Map and Set (ES6 collections)
const map = new Map();
[Link]('key', 'value');
const set = new Set([1, 2, 3, 3, 3]); // Set stores unique values
[Link]([...set]); // [1, 2, 3]

Understanding that these are all objects helps explain why they share certain behaviors, like the
ability to have properties and methods. Arrays are ordered lists of values, but being objects, they
can also have non-numeric properties. However, using arrays as general objects is discouraged
as it can lead to confusing code.

1.8.3 Type Coercion

JavaScript's dynamic typing means that values are automatically converted between types as
needed. This type coercion can be either implicit or explicit:

// Implicit coercion
[Link]('5' + 3); // '53' (number coerced to string)
[Link]('5' - 3); // 2 (string coerced to number)
[Link](true + 1); // 2 (true coerced to 1)
// Explicit coercion
[Link](Number('5')); // 5
[Link](String(123)); // '123'
[Link](Boolean(0)); // false
// Truthy and falsy values
// Falsy values: false, 0, '', null, undefined, NaN
// Everything else is truthy
if ('') {
[Link]('This won\'t run'); // Empty string is falsy
}
if ('hello') {
[Link]('This will run'); // Non-empty string is truthy
}
// Common pattern using logical operators
const name = '' || 'Default Name'; // 'Default Name'
const count = 0 || 10; // 10 (might not be what you want!)
const actualCount = 0 ?? 10; // 0 (nullish coalescing - only null/undefined)

The concept of truthy and falsy values is central to JavaScript's type coercion. In boolean contexts,
values are coerced to either true or false. Only six values are falsy: false, 0, empty string, null,
undefined, and NaN. All other values, including empty arrays and objects, are truthy.

1.9 Array Methods for Functional Programming

1.9.1 The Functional Programming Paradigm

Functional programming treats computation as the evaluation of mathematical functions and


emphasizes immutability and the absence of side effects. JavaScript's first-class functions and
array methods make it well-suited for functional programming techniques, which have become
increasingly important in modern JavaScript development, particularly with React.

The principle of immutability means not modifying existing data but instead creating new data
structures with the desired changes. This approach makes programs more predictable and easier
to debug, as you don't have to track how data changes over time. React's emphasis on
immutability for state updates makes understanding these concepts essential.

1.9.2 Essential Array Methods

Let's explore the most important array methods with practical examples:

// map() - transform each element


const numbers = [1, 2, 3, 4, 5];
const doubled = [Link](n => n * 2);
[Link](doubled); // [2, 4, 6, 8, 10]
// Working with objects
const users = [ { id: 1, name: 'Alice', age: 25 }, { id: 2, name: 'Bob', age: 30 }, { id: 3, name: 'Charlie',
age: 35 } ];
const userNames = [Link](user => [Link]);
[Link](userNames); // ['Alice', 'Bob', 'Charlie']

// filter() - select elements based on condition


const adults = [Link](user => [Link] >= 30);
[Link](adults); // [{ id: 2, name: 'Bob', age: 30 }, { id: 3, name: 'Charlie', age: 35 }]

// reduce() - reduce to a single value


const sum = [Link]((acc, curr) => acc + curr, 0); [Link](sum); // 15

// More complex reduce example const usersByAge = [Link]((groups, user) => { const
ageGroup = [Link] < 30 ? 'young' : 'adult'; groups[ageGroup] = groups[ageGroup] || [];
groups[ageGroup].push(user); return groups; }, {});

// find() and findIndex() const user = [Link](u => [Link] === 'Bob');
[Link](user); // { id: 2, name: 'Bob', age: 30 }
const index = [Link](u => [Link] === 'Bob');
[Link](index); // 1

// Chaining methods const result = numbers .filter(n => n > 2) .map(n => n * 2) .reduce((sum, n)
=> sum + n, 0);
[Link](result); // 24 (32 + 42 + 5*2)

The map() method creates a new array by applying a transformation function to each element of
the original array. The original array remains unchanged, embodying the principle of immutability.
The filter() method creates a new array containing only elements that pass a test implemented
by the provided function.

The reduce() method is the most powerful and flexible of the array methods. It reduces an array
to a single value by repeatedly applying a function that combines the accumulated result with
each element. While often used for summing numbers, reduce() can build any type of value,
including objects and arrays.

1.10 JavaScript Modules

1.10.1 The Need for Modules

Before ES6 modules, JavaScript lacked a built-in module system, leading to various community
solutions and significant challenges in large-scale application development. The global
namespace became polluted with variables and functions from different scripts, leading to
naming conflicts and making it difficult to track dependencies.

Dependency management was particularly problematic. Developers had to manually ensure


scripts were loaded in the correct order, and there was no standard way to explicitly declare what
a script depended on or what it provided to other scripts. This led to fragile applications where
changing the load order could break functionality.

1.10.2 ES6 Module System

The ES6 module system addresses these issues with a standardized approach to organizing and
sharing code. Here's how modules work in practice:

// [Link] - Named exports


export const PI = 3.14159;
export function add(a, b) {
return a + b;
}
export function multiply(a, b) {
return a * b;
}
// [Link] - Default export
const utils = {
formatDate(date) {
return [Link]();
},
capitalize(str) {
return [Link](0).toUpperCase() + [Link](1);
}
};
export default utils;
// [Link] - Importing
import { add, multiply, PI } from './[Link]';
import utils from './[Link]';
[Link](add(2, 3)); // 5
[Link](PI); // 3.14159
[Link]([Link]('hello')); // 'Hello'
// Mixed imports
import React, { useState, useEffect } from 'react';
// Rename imports
import { add as addition } from './[Link]';
// Import all as namespace
import * as math from './[Link]';
[Link]([Link](2, 3)); // 5
Modules are files that explicitly declare their dependencies through import statements and their
public API through export statements. This creates clear contracts between different parts of an
application. Only explicitly exported values are accessible from outside the module; everything
else remains private.

1.10.3 Import and Export Patterns

Named exports allow a module to export multiple values, each with a specific name. These
exports can be functions, classes, variables, or any other JavaScript value. When importing, you
must use the same names or explicitly rename them. Default exports provide a way to export a
single main value from a module. This is useful when a module has one primary purpose.

Re-exports allow a module to export values from another module, effectively passing them
through. This is useful for creating "barrel" modules that aggregate and re-export related
functionality from multiple modules, providing a single convenient import point for consumers.

1.11 Asynchronous JavaScript Concepts

1.11.1 The Event Loop

JavaScript's concurrency model is based on an event loop, which enables asynchronous


programming despite JavaScript being single-threaded. Understanding the event loop is crucial
for writing efficient asynchronous code and avoiding common pitfalls.

The call stack executes synchronous code. When a function is called, it's added to the stack, and
when it returns, it's removed. JavaScript can only execute one piece of code at a time, processing
whatever is at the top of the stack. The task queue holds callbacks from asynchronous operations
like setTimeout, I/O operations, and events. When the call stack is empty, the event loop takes
the first task from the queue and pushes it onto the stack for execution.
1.11.2 Callbacks, Promises, and Async/Await

Let's explore the evolution of asynchronous JavaScript with practical examples:

// Callbacks - the traditional approach


function fetchUserData(userId, callback) {
setTimeout(() => {
const user = { id: userId, name: 'John Doe' };
callback(user);
}, 1000);
}
fetchUserData(1, (user) => {
[Link](user); // { id: 1, name: 'John Doe' }
});
// Promises - a better abstraction
function fetchUserDataPromise(userId) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (userId > 0) {
const user = { id: userId, name: 'John Doe' };
resolve(user);
} else {
reject(new Error('Invalid user ID'));
}
}, 1000);
});
}
fetchUserDataPromise(1)
.then(user => [Link](user))
.catch(error => [Link](error));
// Async/Await - syntactic sugar over promises
async function getUserData() {
try {
const user = await fetchUserDataPromise(1);
[Link](user);
// Multiple async operations
const posts = await fetchUserPosts([Link]);
const comments = await fetchPostComments(posts[0].id);
return { user, posts, comments };
} catch (error) {
[Link]('Error fetching data:', error);
}
}
// [Link] for parallel operations
async function fetchMultipleUsers(userIds) {
const promises = [Link](id => fetchUserDataPromise(id));
const users = await [Link](promises);
return users;
}

Callbacks were JavaScript's original mechanism for handling asynchronous operations. While
conceptually simple, callbacks can lead to deeply nested code when multiple asynchronous
operations need to be coordinated, a problem known as "callback hell."

Promises provide a cleaner abstraction for asynchronous operations. A promise represents a


value that may not be available yet but will be resolved in the future. The ability to chain promises
with .then() and handle errors with .catch() makes complex asynchronous flows more
manageable.
Async/await provides syntactic sugar over promises that makes asynchronous code look and
behave more like synchronous code. Functions marked with async always return a promise, and
the await keyword pauses the function execution until a promise resolves.

1.12 Best Practices for React Development

1.12.1 Code Organization

Good code organization is essential for maintaining large React applications. Using meaningful
and consistent naming conventions helps developers quickly understand what variables and
functions do. Functions should be small and focused on a single responsibility, making them
easier to test and reuse. Related functionality should be grouped together, whether in the same
file or in logically organized directories.

The principle of least surprise suggests that code should behave in ways that developers expect.
This means following established patterns and conventions within the React ecosystem and being
consistent throughout your application. When you must deviate from common patterns, clear
documentation explaining why helps future maintainers understand your decisions.

1.12.2 Performance Considerations

Performance in React applications often comes down to avoiding unnecessary re-renders.


Understanding JavaScript's equality comparisons and immutability patterns is crucial because
React uses these to determine when components need to update. Creating new objects and
arrays rather than modifying existing ones ensures React can efficiently detect changes:

// Bad - mutating state directly


const handleAddItem = (item) => {
[Link](item); // React won't detect this change
setState(state);
};
// Good - creating new array
const handleAddItem = (item) => {
setState({
...state,
items: [...[Link], item]
});
};
// Using map for updates
const handleUpdateItem = (id, updates) => {
setState({
...state,
items: [Link](item =>
[Link] === id ? { ...item, ...updates } : item
)
});
};

Bundle size is another critical performance consideration. Understanding how JavaScript


modules work and how bundlers process them helps you structure your code to enable effective
code splitting and tree shaking.

1.12.3 Error Handling

Robust error handling prevents applications from crashing and provides better user experiences.
JavaScript's try/catch blocks allow you to handle synchronous errors, while promise rejections
and async/await require different strategies:

// Synchronous error handling


try {
const data = [Link](jsonString);
processData(data);
} catch (error) {
[Link]('Invalid JSON:', [Link]);
// Handle error gracefully
}
// Async error handling with promises
fetchData()
.then(data => processData(data))
.catch(error => {
[Link]('Failed to fetch data:', error);
// Show user-friendly error message
});
// Async/await error handling
async function loadUserData(userId) {
try {
const user = await fetchUser(userId);
const preferences = await fetchUserPreferences(userId);
return { user, preferences };
} catch (error) {
// Log error for debugging
[Link](`Failed to load data for user ${userId}:`, error);
// Return default data or rethrow
throw new Error('Unable to load user data');
}
}

Understanding these different error handling mechanisms is essential for building reliable
applications. In production, error boundaries (a React feature that leverages JavaScript's error
handling) prevent entire applications from crashing due to component errors.
1.13 Summary

This chapter has provided a comprehensive foundation of JavaScript concepts essential for React
development. We began by exploring the evolution of JavaScript and the revolutionary changes
introduced in ES6, understanding why these changes were necessary for modern web
development.

We examined modern variable declarations and scope management, understanding how let and
const address the historical issues with var. The exploration of functions covered both traditional
and arrow functions, with particular attention to how arrow functions' lexical this binding solves
common problems in React components.

De-structuring and the spread operator were revealed as powerful features for working with data
structures, while template literals showed how modern JavaScript makes string handling more
elegant. We delved into JavaScript's type system, understanding both primitive and object types
and how type coercion affects our code.

The functional programming features of JavaScript, particularly array methods, were shown to
align perfectly with React's declarative paradigm. The module system's importance in organizing
large-scale applications was explored, along with the patterns for importing and exporting code.

Finally, we touched on asynchronous JavaScript concepts and best practices that will be crucial
when building React applications. Throughout the chapter, we've included practical examples to
illustrate how these concepts work in real code, preparing you for the hands-on work ahead.

These concepts form the backbone of modern JavaScript development and are prerequisites for
understanding React's component-based architecture. In the following chapters, we will see how
these JavaScript features are applied in React development, building upon this theoretical and
practical foundation to create powerful, maintainable web applications.
1.14 Review Questions

1.14.1 Multiple Choice Questions


1. Which of the following is NOT a primitive type in JavaScript?
a) Number
b) String
c) Array
d) Boolean
2. What is the main difference between let and const declarations?
a) let is function-scoped, const is block-scoped
b) const creates an immutable binding that cannot be reassigned
c) let is hoisted, const is not
d) There is no difference in modern JavaScript
3. Which ES6 feature allows you to extract values from arrays or properties from objects?
a) Spread operator
b) Template literals
c) De-structuring
d) Arrow functions
4. What is the primary advantage of arrow functions over traditional function expressions?
a) They are always faster
b) They have lexical this binding
c) They can be used as constructors
d) They support the arguments object
5. Which array method would be most appropriate for transforming each element in an array
without modifying the original array?
a) forEach()
b) filter()
c) map()
d) reduce()
1.14.2 Short Answer Questions
1. Explain the concept of hoisting in JavaScript and how it differs between var, let, and const.
2. Describe the difference between synchronous and asynchronous programming in JavaScript.
3. What are the benefits of using the ES6 module system over traditional script loading?
4. Explain the concept of "temporal dead zone" in relation to let and const declarations.
5. Compare and contrast object de-structuring with array de-structuring.

1.14.3 Practical Exercises


1. Write a function using arrow syntax that takes an array of numbers and returns an object
containing the sum, average, min, and max values. Use array methods and de-structuring where
appropriate.
2. Create a simple module that exports both named and default exports. The module should contain
utility functions for string manipulation (capitalize, reverse, truncate). Then show how to import
and use these functions in another file.
3. Given an array of user objects with properties (id, name, age, email), write code using array
methods to:
a. Filter users who are 18 or older
b. Map the filtered users to include only name and email
c. Sort the results alphabetically by name

1.14.4 Essay Questions


1. Discuss the evolution of JavaScript from ES5 to ES6 and explain why these changes were
necessary for modern web development.
2. Analyze the functional programming features in JavaScript and their importance in React
development.
3. Evaluate the different approaches to handling asynchronous operations in JavaScript (callbacks,
promises, async/await) and their respective advantages and disadvantages.
2 Introduction to React JS

Learning Objectives

By the end of this chapter, students will be able to:

• Understand what React is and why it has become a dominant library for building user interfaces,
• Set up a React development environment using [Link] and create-react-app,
• Create and understand functional components as the building blocks of React applications,
• Work with props to pass data between components,
• Implement basic state management using the useState hook,
• Build simple interactive React applications that respond to user input.

2.1 Introduction

React has revolutionized the way we build user interfaces for web applications. Created by
Facebook (now Meta) in 2013, React has grown from an internal project to one of the most
popular JavaScript libraries in the world. This chapter introduces you to React's fundamental
concepts and provides hands-on experience creating your first React components.

Understanding React requires a shift in thinking about how web applications are built. Instead of
manipulating the DOM directly, React introduces a declarative approach where you describe
what the UI should look like at any given state, and React efficiently updates the DOM to match
that description. This mental model, combined with React's component-based architecture,
makes building complex user interfaces more manageable and maintainable.
2.2 What is React?

2.2.1 Understanding React's Core Philosophy

React is a JavaScript library for building user interfaces, particularly web applications that require
frequent data changes. Unlike full frameworks that provide everything needed to build an
application, React focuses specifically on the view layer, giving developers the freedom to choose
other libraries for different aspects of their application.

At its core, React embraces several key principles that set it apart from traditional web
development approaches. The first is the concept of declarative programming. Instead of
imperatively telling the browser how to update the page step by step, you declare what the page
should look like based on the current application state. React then figures out the most efficient
way to update the DOM to match your declaration.

The second principle is component-based architecture. React applications are built using
components, which are self-contained pieces of UI that manage their own state and rendering
logic. Components can be composed together like building blocks, allowing developers to build
complex UIs from simple, reusable pieces. This modular approach promotes code reusability,
makes testing easier, and helps teams collaborate more effectively.

The third principle is the unidirectional data flow. Data in React applications flows in one direction,
from parent components to child components through props. This predictable data flow makes
applications easier to debug and understand, as you can trace where data comes from and how
it affects the UI.

2.2.2 The Virtual DOM

One of React's most innovative features is the Virtual DOM, a lightweight JavaScript
representation of the actual DOM. When you write React code, you're not directly manipulating
the browser's DOM. Instead, you're working with React's Virtual DOM, which acts as an
intermediary layer.
The Virtual DOM solves a fundamental performance problem in web development. Direct DOM
manipulation is expensive because the browser must recalculate layouts, repaint elements, and
perform other costly operations. When you have an application with frequent updates, these
operations can make the UI feel sluggish and unresponsive.

React's Virtual DOM works by maintaining a virtual representation of your UI in memory. When
the state of your application changes, React creates a new virtual DOM tree representing the
new state. It then compares this new tree with the previous virtual DOM tree, a process called
"diffing." Through this comparison, React identifies exactly what has changed and updates only
those specific parts of the real DOM. This selective updating, called "reconciliation," dramatically
improves performance, especially in applications with complex UIs and frequent updates.

2.2.3 Why Choose React?

React has become popular for several compelling reasons. First, its component-based
architecture aligns well with modern software development practices. Components encapsulate
both logic and presentation, making them easy to understand, test, and reuse. This modularity is
particularly valuable in large applications where different teams might work on different parts of
the UI.

Second, React's ecosystem is vast and mature. The community has created thousands of libraries
and tools that work with React, from state management solutions to UI component libraries. This
ecosystem means you rarely have to build common functionality from scratch, accelerating
development time.

Third, React's learning curve, while initially steep, plateaus relatively quickly. Once you
understand the core concepts of components, props, and state, you can build increasingly
complex applications using the same patterns. This consistency makes React knowledge
transferable across projects and teams.
Finally, React's popularity means excellent job prospects for developers. Many companies use
React for their web applications, creating a strong demand for React developers. Learning React
opens doors to numerous career opportunities in web development.

2.3 Setting Up the Development Environment

2.3.1 Installing [Link]

Before we can start building React applications, we need to set up our development environment.
React development requires [Link], a JavaScript runtime that allows us to run JavaScript outside
the browser. [Link] comes with npm (Node Package Manager), which we'll use to install React
and other dependencies.

To install [Link], visit the official [Link] website ([Link]) and download the installer for
your operating system. For this course, we recommend using the LTS (Long Term Support) version,
which provides stability and long-term maintenance. During installation, make sure to include
npm, which is typically selected by default.

After installation, you can verify that [Link] and npm are properly installed by opening a
terminal or command prompt and running the following commands:

node --version

npm –version

These commands should display version numbers, confirming successful installation. If you see
version numbers (for example, node v18.17.0 and npm 9.6.7), you're ready to proceed. If not,
you may need to restart your terminal or check your system's PATH environment variable.

2.3.2 Creating Your First React Application

React provides an official tool called Create React App that sets up a new React project with a
modern build configuration. This tool handles complex webpack configuration, Babel setup, and
development server, allowing you to focus on writing React code rather than configuring build
tools.

To create a new React application, open your terminal and navigate to the directory where you
want to create your project. Then run:

npx create-react-app my-first-react-app


cd my-first-react-app
npm start

The npx command runs the latest version of create-react-app without globally installing it. This
process might take a few minutes as it downloads dependencies and sets up your project
structure. Once complete, the npm start command launches a development server and opens
your new React application in your default web browser at [Link]

2.3.3 Understanding the Project Structure

Create React App generates a project structure that follows React best practices. Let's explore
the key files and directories:

The node_modules directory contains all the project dependencies. This folder is typically large
and should not be committed to version control. The public directory contains static files that
don't go through the build process. The [Link] file is particularly important as it's the single
HTML page that hosts your React application.
The src directory is where you'll spend most of your time. It contains all your React components
and associated files. The [Link] file is the entry point of your application, where React is
initialized and the root component is rendered. The [Link] file contains the main App component,
which serves as the starting point for your component tree.

The [Link] file lists your project dependencies and scripts. You can run various commands
defined in this file, such as npm start for development, npm test for testing, and npm run build
for creating a production build.

2.4 Understanding Components

2.4.1 What Are Components?

Components are the fundamental building blocks of React applications. A component is a self-
contained piece of UI that encapsulates its own structure, style, and behavior. Think of
components as custom HTML elements that you can create and reuse throughout your
application.

In traditional web development, you might have a large HTML file with JavaScript manipulating
various parts of it. This approach becomes unwieldy as applications grow. React's component-
based approach solves this by breaking the UI into independent, reusable pieces. Each
component manages its own piece of the UI, making the overall application easier to understand
and maintain.

Components can be as simple as a button or as complex as an entire form or page. The key is that
each component has a single, well-defined purpose. This single responsibility principle makes
components easier to understand, test, and reuse. When building React applications, you'll often
start with larger components and then break them down into smaller, more focused components
as patterns emerge.
2.4.2 Creating Your First Functional Component

Let's create our first React component. In React, components are JavaScript functions that return
JSX (JavaScript XML), a syntax extension that looks like HTML but is actually JavaScript. Here's a
simple component:

This Welcome component is a function that returns JSX describing what should appear on the
screen. The JSX looks like HTML, but it's actually JavaScript code that React transforms into
function calls that create React elements. Notice how we export the component so it can be
imported and used in other files.

To use this component, we need to import it and include it in our JSX:


Notice how we can use the Welcome component multiple times, just like an HTML element. Each
instance is independent, demonstrating the reusable nature of components. When React renders
this, it will display the Welcome message three times.

Output in the browser:

2.4.3 Component Naming and Organization

React has specific conventions for components that help maintain consistency across projects.
Component names must start with a capital letter to distinguish them from regular HTML
elements. When React sees an element starting with a lowercase letter, it treats it as a DOM tag.
When it starts with a capital letter, React treats it as a component.

Component files are typically organized in a components directory within the src folder. Each
component usually lives in its own file, with the filename matching the component name. This
organization makes it easy to find and maintain components as your application grows.

Here's a more complex example showing component organization:

// src/components/[Link]
function Header() {
return (
<header>
<h1>My React Application</h1>
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
<a href="/contact">Contact</a>
</nav>
</header>
);
}
export default Header;
// src/components/[Link]
function Footer() {
const currentYear = new Date().getFullYear();
return (
<footer>
<p>&copy; {currentYear} My React Application. All rights reserved.</p>
</footer>
);
}
export default Footer;
// src/[Link]
import Header from './components/Header';
import Footer from './components/Footer';
import Welcome from './components/Welcome';
function App() {
return (
<div className="App">
<Header />
<main>
<Welcome />
</main>
<Footer />
</div>
);
}
export default App;

This example demonstrates how components can be composed together to create a complete
page layout. Each component has a specific responsibility: Header for navigation, Footer for
copyright information, and Welcome for the main content.

Output in the browser:

2.5 Working with Props

2.5.1 Understanding Props

Props (short for properties) are how we pass data from parent components to child components
in React. They're similar to function arguments or HTML attributes. Props make components
flexible and reusable by allowing them to display different content based on the values passed
to them.
Props are read-only, meaning a component cannot modify its own props. This immutability is a
key principle in React that helps maintain predictable data flow. When a parent component
passes props to a child, the child can use those props to render different content or behave
differently, but it cannot change the prop values themselves.

Think of props as a component's configuration. Just as HTML elements have attributes that affect
their behavior and appearance, React components have props that customize their output. This
system allows you to create generic components that can be specialized for different use cases.

2.5.2 Passing and Using Props

Let's modify our Welcome component to accept props:

// src/components/[Link]
function Welcome(props) {
return (
<div>
<h1>Welcome to React, {[Link]}!</h1>
<p>You are {[Link]} years old.</p>
<p>{[Link]}</p>
</div>
);
}
export default Welcome;
// src/[Link]
import Welcome from './components/Welcome';
function App() {
return (
<div className="App">
<Welcome
name="Alice"
age={25}
message="Hope you enjoy learning React!"
/>
<Welcome
name="Bob"
age={30}
message="React makes building UIs fun!"
/>
</div>
);
}
export default App;

Notice how we pass props to the Welcome component using syntax similar to HTML attributes.
String props are passed in quotes, while numeric values and other JavaScript expressions are
passed in curly braces. The component receives all props as properties of a single props object.

Output in the browser:

We can make our code cleaner using de-structuring:


// src/components/[Link]
function Welcome({ name, age, message }) {
return (
<div>
<h1>Welcome to React, {name}!</h1>
<p>You are {age} years old.</p>
<p>{message}</p>
</div>
);
}
export default Welcome;

De-structuring props directly in the function parameter makes the code more readable and
shows clearly which props the component expects. This pattern is widely used in React
development.

2.5.3 Props Validation and Default Values

While JavaScript is dynamically typed, it's helpful to document what props a component expects.
We can provide default values for props to make components more robust:

// src/components/[Link]
function UserCard({ name = "Guest", role = "Visitor", isActive = false }) { return (
{name}
Role: {role}
Status: {isActive ? "Active" : "Inactive"}
); }
export default UserCard;
// src/[Link] import UserCard from './components/UserCard';
function App() { return (
{/* Uses all default values */}
); }

Default values ensure that components work even when some props are not provided, making
them more flexible and preventing errors from undefined values.

Output in the browser:

2.6 State and Interactivity

2.6.1 Understanding State

While props allow parent components to pass data to children, state allows components to
manage their own data that can change over time. State is what makes React applications
interactive and dynamic. When state changes, React automatically re-renders the component to
reflect the new state.
State represents any data that can change during the component's lifetime. This might include
user input, data fetched from an API, timers, or any other dynamic values. The key difference
between props and state is that props are passed from parent to child and are immutable within
the component, while state is managed internally by the component and can be changed.

In functional components, we manage state using the useState hook, one of React's built-in hooks.
Hooks are special functions that allow functional components to use React features that were
previously only available in class components.

2.6.2 Using the useState Hook

The useState hook is the most fundamental hook in React. It allows functional components to
have state. Here's how to use it:

// src/components/[Link]
import { useState } from 'react';
function Counter() {
// Declare state variable 'count' with initial value 0
const [count, setCount] = useState(0);
const increment = () => {
setCount(count + 1);
};
const decrement = () => {
setCount(count - 1);
};
const reset = () => {
setCount(0);
};
return (
<div>
<h2>Counter: {count}</h2>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Decrement</button>
<button onClick={reset}>Reset</button>
</div>
);
}
export default Counter;

The useState hook returns an array with two elements: the current state value and a function to
update it. We use array destructuring to assign these to variables. The convention is to name the
setter function with "set" followed by the state variable name.

When you call the setter function (like setCount), React schedules a re-render of the component
with the new state value. This re-render happens asynchronously and efficiently updates only
the parts of the DOM that have changed.

Output in the browser (initial state):

After clicking Increment twice:


2.6.3 Handling User Input

State becomes particularly useful when handling user input. Let's create a component that
responds to user typing:

// src/components/[Link]
import { useState } from 'react';
function Greeting() {
const [name, setName] = useState('');
const [submitted, setSubmitted] = useState(false);
const handleInputChange = (event) => {
setName([Link]);
setSubmitted(false);
};
const handleSubmit = (event) => {
[Link]();
setSubmitted(true);
};
return (
<div>
<form onSubmit={handleSubmit}>
<input
type="text"
value={name}
onChange={handleInputChange}
placeholder="Enter your name"
/>
<button type="submit">Submit</button>
</form>
{name && !submitted && (
<p>Hello, {name}! Click submit when ready.</p>
)}
{submitted && name && (
<h2>Welcome to React, {name}!</h2>
)}
</div>
);
}
export default Greeting;

This example demonstrates several important concepts. First, we use controlled components
where the input's value is controlled by React state. The value prop of the input is set to our state
variable, and the onChange handler updates the state when the user types.

Second, we handle form submission by preventing the default browser behavior and updating
our component state. This pattern of controlling form inputs through React state is fundamental
to handling user input in React applications.

Output in the browser (initial state):

While typing "John":


After clicking Submit:

2.6.4 Multiple State Variables

Components often need to track multiple pieces of state. You can call useState multiple times in
a single component:

// src/components/[Link]
import { useState } from 'react';
function UserForm() {
const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');
const [email, setEmail] = useState('');
const [submitted, setSubmitted] = useState(false);
const handleSubmit = (event) => {
[Link]();
setSubmitted(true);
};
const handleReset = () => {
setFirstName('');
setLastName('');
setEmail('');
setSubmitted(false);
};
return (
<div>
{!submitted ? (
<form onSubmit={handleSubmit}>
<div>
<input
type="text"
value={firstName}
onChange={(e) => setFirstName([Link])}
placeholder="First Name"
required
/>
</div>
<div>
<input
type="text"
value={lastName}
onChange={(e) => setLastName([Link])}
placeholder="Last Name"
required
/>
</div>
<div>
<input
type="email"
value={email}
onChange={(e) => setEmail([Link])}
placeholder="Email"
required
/>
</div>
<button type="submit">Submit</button>
</form>
):(
<div>
<h3>Submitted Information:</h3>
<p>Name: {firstName} {lastName}</p>
<p>Email: {email}</p>
<button onClick={handleReset}>Submit Another</button>
</div>
)}
</div>
);
}
export default UserForm;

Each piece of state is independent, and updating one doesn't affect the others. This granular
control over state makes it easy to manage complex component behavior.

Sample Output in the browser (form view):

After filling and submitting:


2.7 Building Interactive Components

2.7.1 Combining Props and State

Real-world components often use both props and state. Props provide configuration from parent
components, while state manages internal component data. Let's create a more complex
example that demonstrates this combination:

// src/components/[Link]
import { useState } from 'react';
function TodoItem({ task, onDelete }) {
const [isCompleted, setIsCompleted] = useState(false);
const handleToggle = () => {
setIsCompleted(!isCompleted);
};
const textStyle = {
textDecoration: isCompleted ? 'line-through' : 'none',
color: isCompleted ? '#888' : '#000'
};
return (
<div className="todo-item">
<input
type="checkbox"
checked={isCompleted}
onChange={handleToggle}
/>
<span style={textStyle}>{task}</span>
<button onClick={() => onDelete(task)}>Delete</button>
</div>
);
}
export default TodoItem;
// src/components/[Link]
import { useState } from 'react';
import TodoItem from './TodoItem';
function TodoList() {
const [tasks, setTasks] = useState([]);
const [inputValue, setInputValue] = useState('');
const addTask = (event) => {
[Link]();
if ([Link]()) {
setTasks([...tasks, inputValue]);
setInputValue('');
}
};
const deleteTask = (taskToDelete) => {
setTasks([Link](task => task !== taskToDelete));
};
return (
<div className="todo-list">
<h2>My Todo List</h2>
<form onSubmit={addTask}>
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue([Link])}
placeholder="Add a new task"
/>
<button type="submit">Add</button>
</form>
<div className="tasks">
{[Link]((task, index) => (
<TodoItem
key={index}
task={task}
onDelete={deleteTask}
/>
))}
</div>
{[Link] === 0 && (
<p>No tasks yet. Add one above!</p>
)}
</div>
);
}
export default TodoList;

This example shows several important patterns. The TodoList component manages the list of
tasks in its state and passes individual tasks as props to TodoItem components. Each TodoItem
manages its own completed state internally. The parent component also passes a callback
function (onDelete) that child components can call to communicate back to the parent.
Example Output in the browser (initial state):

After adding tasks:

2.7.2 Event Handling Best Practices

React's event handling system is similar to HTML's but with some important differences. React
events are named using camelCase rather than lowercase, and you pass a function as the event
handler rather than a string. React's synthetic event system ensures consistent behavior across
different browsers.

Here's an example demonstrating various event handling patterns:

// src/components/[Link]
import { useState } from 'react';
function EventDemo() {
const [message, setMessage] = useState('');
const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 });
const [inputFocused, setInputFocused] = useState(false);
const handleClick = () => {
setMessage('Button clicked!');
};
const handleMouseMove = (event) => {
setMousePosition({
x: [Link],
y: [Link]
});
};
const handleFocus = () => {
setInputFocused(true);
setMessage('Input focused');
};
const handleBlur = () => {
setInputFocused(false);
setMessage('Input lost focus');
};
return (
<div className="event-demo" onMouseMove={handleMouseMove}>
<h3>Event Handling Demo</h3>
<button onClick={handleClick}>Click Me</button>
<input
type="text"
onFocus={handleFocus}
onBlur={handleBlur}
style={{
border: inputFocused ? '2px solid blue' : '1px solid gray'
}}
placeholder="Click to focus"
/>
<p>Message: {message}</p>
<p>Mouse Position: X: {mousePosition.x}, Y: {mousePosition.y}</p>
</div>
);
}
export default EventDemo;

When handling events in React, it's important to understand that event handlers receive a
synthetic event object that wraps the native browser event. This provides consistent properties
and methods across different browsers.

Example Output in the browser:

When the input is focused, it gets a blue border:


The mouse position updates in real-time as you move the mouse around the component area.

2.7.3 Building a Complete Interactive Application

Let's combine everything we've learned to build a simple but complete interactive application -
a color picker:

// src/components/[Link]
import { useState } from 'react';
function ColorPicker() {
const [selectedColor, setSelectedColor] = useState('#000000');
const [customColors, setCustomColors] = useState([]);
const [colorName, setColorName] = useState('');
const predefinedColors = [
{ name: 'Red', value: '#FF0000' },
{ name: 'Green', value: '#00FF00' },
{ name: 'Blue', value: '#0000FF' },
{ name: 'Yellow', value: '#FFFF00' },
{ name: 'Purple', value: '#800080' },
{ name: 'Orange', value: '#FFA500' }
];
const handleColorSelect = (color) => {
setSelectedColor(color);
};
const addCustomColor = (event) => {
[Link]();
if ([Link]()) {
setCustomColors([...customColors, {
name: colorName,
value: selectedColor
}]);
setColorName('');
}
};
const boxStyle = {
width: '200px',
height: '200px',
backgroundColor: selectedColor,
border: '2px solid #333',
margin: '20px auto'
};
return (
<div className="color-picker">
<h2>Color Picker</h2>
<div style={boxStyle}></div>
<p>Selected Color: {selectedColor}</p>
<div>
<h3>Choose a Color:</h3>
<input
type="color"
value={selectedColor}
onChange={(e) => handleColorSelect([Link])}
/>
</div>
<div>
<h3>Predefined Colors:</h3>
{[Link]((color) => (
<button
key={[Link]}
onClick={() => handleColorSelect([Link])}
style={{
backgroundColor: [Link],
color: 'white',
margin: '5px',
padding: '10px',
border: 'none',
cursor: 'pointer'
}}
>
{[Link]}
</button>
))}
</div>
<div>
<h3>Save Custom Color:</h3>
<form onSubmit={addCustomColor}>
<input
type="text"
value={colorName}
onChange={(e) => setColorName([Link])}
placeholder="Color name"
/>
<button type="submit">Save</button>
</form>
</div>

{[Link] > 0 && (


<div>
<h3>Your Custom Colors:</h3>
{[Link]((color, index) => (
<button
key={index}
onClick={() => handleColorSelect([Link])}
style={{
backgroundColor: [Link],
color: 'white',
margin: '5px',
padding: '10px',
border: 'none',
cursor: 'pointer'
}}
>
{[Link]}
</button>
))}
</div>
)}
</div>
);
}
export default ColorPicker;
This color picker demonstrates many React concepts working together. It uses multiple state
variables to track the selected color, custom colors, and input values. It handles various events
including color selection, form submission, and button clicks. The component dynamically
renders content based on state, showing custom colors only when they exist.

Example Browser Display:

The colored box changes instantly as you select colors. Custom color buttons appear with their
saved background colors. The predefined color buttons are styled with their respective colors
(red button is red, blue button is blue, etc.).
2.8 Best Practices and Common Patterns

2.8.1 Component Design Principles

As you begin building React applications, following established best practices will help you create
maintainable and scalable code. One fundamental principle is to keep components small and
focused. Each component should have a single, clear responsibility. When a component starts
handling too many concerns, it's time to break it into smaller components.

Another important principle is to lift state up when multiple components need to share the same
changing data. Instead of duplicating state in multiple components, keep it in their closest
common ancestor and pass it down through props. This ensures a single source of truth for your
data and makes your application's data flow more predictable.

Components should also be pure whenever possible. A pure component always renders the same
output for the same props and state. This predictability makes components easier to test and
reason about. Avoid side effects in the render method, and instead use event handlers or React's
built-in hooks for side effects.

2.8.2 Naming Conventions and Code Style

Consistent naming conventions make code more readable and maintainable. React components
should use PascalCase naming, starting with a capital letter. Event handler functions typically
start with "handle" followed by the event name, like handleClick or handleSubmit. State setter
functions follow the pattern "set" plus the state variable name.

Props that represent event handlers are typically prefixed with "on", such as onClick or onSubmit.
This convention clearly distinguishes props that pass data from those that pass callback functions.
Boolean props often start with "is", "has", or "should" to indicate their true/false nature.
File organization is also important. Each component should typically live in its own file, named
after the component. Related components can be grouped in directories. Style files, if used,
should follow a similar naming pattern and be co-located with their components.

2.8.3 Performance Considerations

While React is generally fast, understanding some performance basics helps build efficient
applications from the start. React re-renders components when their state or props change. This
is usually fine, but unnecessary re-renders can impact performance in complex applications.

One simple optimization is to avoid creating new objects or functions inside the render method
when possible. Each render creates new instances, which can cause child components to re-
render even when the data hasn't actually changed. For event handlers, define them as
component methods rather than inline arrow functions when performance is a concern.

Another consideration is list rendering. When rendering lists of components, always provide a
unique key prop. React uses keys to identify which items have changed, been added, or been
removed. Using array indices as keys can cause issues when the list order changes, so prefer
stable, unique identifiers when available.

2.9 Summary

This chapter introduced you to React, one of the most popular libraries for building user
interfaces. We began by understanding React's core philosophy, including its declarative nature,
component-based architecture, and unidirectional data flow. These principles form the
foundation of React development and distinguish it from traditional web development
approaches.

We explored the Virtual DOM, React's innovative solution to performance challenges in dynamic
web applications. By maintaining a lightweight representation of the DOM in memory and
efficiently updating only what has changed, React enables smooth, responsive user interfaces
even with frequent updates.

The practical portion of this chapter walked you through setting up a React development
environment using [Link] and Create React App. We examined the project structure and
understood the role of each key file and directory. This foundation prepares you for building
React applications throughout the rest of this course.

We then dove into components, the building blocks of React applications. You learned to create
functional components, organize them effectively, and understand how they work together to
create complete user interfaces. We explored props as a mechanism for passing data between
components, making them flexible and reusable.

State management through the useState hook brought interactivity to our components. We saw
how state allows components to respond to user actions and update their display accordingly.
Through practical examples like counters, forms, and todo lists, we demonstrated how state and
props work together to create dynamic applications.

The chapter concluded with best practices and patterns that will serve you well as you continue
your React journey. Following these conventions and principles will help you write clean,
maintainable React code that scales well as your applications grow.

In the next chapter, we'll explore the lifecycle of components in more detail, understanding how
React components are created, updated, and removed from the DOM. This deeper
understanding will enable you to build more sophisticated applications and handle complex
scenarios effectively.

2.10 Review Questions

2.10.1 Multiple Choice Questions


1. What is the primary purpose of React's Virtual DOM?
a) To replace HTML entirely
b) To improve performance by minimizing actual DOM updates
c) To make websites work offline
d) To enable server-side rendering
2. Which of the following is the correct way to update state in a functional component?
a) state = newValue
b) [Link](newValue)
c) setState(newValue) where setState comes from useState
d) [Link] = newValue
3. What is the main difference between props and state?
a) Props can be modified by the component, state cannot
b) State can be modified by the component, props cannot
c) Props and state are the same thing
d) State is only used in class components
4. How do you handle events in React?
a) Using lowercase event names like HTML
b) Using camelCase event names and passing functions
c) Using addEventListener method
d) Events are handled automatically
5. What does JSX stand for?
a) JavaScript Extension
b) Java Syntax XML
c) JavaScript XML
d) JSON Expression

2.10.2 Short Answer Questions


1. Explain the difference between controlled and uncontrolled components in React forms.
2. Why must React component names start with a capital letter?
3. Describe the purpose of the key prop when rendering lists in React.
4. What is the significance of one-way data flow in React applications?
5. Explain how the useState hook works and what it returns.
2.10.3 Practical Exercises
1. Create a TemperatureConverter component that allows users to input a temperature in Celsius
and displays the equivalent in Fahrenheit. Include a toggle to switch between Celsius to
Fahrenheit and Fahrenheit to Celsius conversion.
2. Build a ShoppingList component where users can:
a. Add items to a list
b. Mark items as purchased (with strikethrough styling)
c. Remove items from the list
d. Display the total count of items and how many are purchased
3. Create a ProfileCard component that accepts props for name, title, email, and avatar URL. Then
create a TeamDirectory component that renders multiple ProfileCard components with different
team member data.

2.10.4 Essay Questions


1. Discuss the advantages of React's component-based architecture compared to traditional web
development approaches. Include examples of how this architecture promotes code reusability
and maintainability.
2. Explain the concept of "lifting state up" in React. Why is this pattern important, and when should
you apply it? Provide a scenario where lifting state up would be necessary.
3. Compare and contrast props and state in React. Discuss when to use each, how they affect
component re-rendering, and their role in creating interactive applications.
3 The lifecycle of a component

Learning Objectives

By the end of this chapter, you will:

• Define what a component lifecycle is in the context of React.


• Differentiate between class components and functional components in terms of lifecycle
management.
• Identify the key lifecycle phases: Mounting, Updating, and Unmounting.
• Explain the purpose, implementation and behavior of core class lifecycle methods.
• Understand how React Hooks (useEffect, useLayoutEffect, useRef, etc.) simulate lifecycle
behavior in functional components.
• Diagnose common bugs or performance issues related to improper lifecycle use (e.g.,
memory leaks, unnecessary re-renders).
• Create simple React components demonstrating lifecycle behaviors with both class and
functional paradigms.

3.1 Introduction to a Component Lifecycle?

A component lifecycle refers to the series of phases that a software component goes through
from its creation to its destruction. This concept is fundamental in modern software development
frameworks, particularly in front-end technologies like React, Vue, and Angular, where
components serve as the building blocks of user interfaces. The lifecycle encompasses distinct
stages including initialization, mounting, updating, and unmounting, each providing specific
opportunities for developers to execute code at precise moments during the component's
existence. Understanding these phases allows developers to manage resources efficiently,
handle data fetching, set up event listeners, and perform cleanup operations at the appropriate
times.

In the realm of [Link], the life cycle of a component encompasses a sequence of events and
methods that occur from the moment the component is loaded into memory until it persists in
memory. These events and methods, collectively known as the component's life cycle, play a vital
role in its creation, rendering, updating, and eventual destruction, However, with the
introduction of React Hooks, a more flexible and comprehensive approach to managing
component lifecycle and state has emerged. Hooks provide a paradigm shift, enabling developers
to utilize functions instead of class-based components, thus simplifying and enhancing the
management of component lifecycle and state. (N Poornima & O Kavita 2023).

Each lifecycle phase serves a specific purpose and offers hooks or methods that developers can
leverage to control component behavior. During the mounting phase, components are created
and inserted into the DOM, making it ideal for initial data loading and setup operations. The
updating phase occurs when component state or props change, triggering re-renders and
allowing for performance optimizations through comparison of previous and current values.
Finally, the unmounting phase provides a crucial opportunity to clean up resources, cancel
network requests, and remove event listeners to prevent memory leaks. This systematic
approach to component management ensures predictable behavior, optimal performance, and
maintainable code architecture in complex applications.
3.2 Lifecycle Phases in Class Components

The lifecycle of the component is divided into four phases listed below.

Fig 3.1 Life Cycle Methods.

Source: Awesome [Link] (Unleash the Power of Modern UI Building), By N Poornima & O
Kavita 2023.

3.2.1 Mounting Phase


The mounting phase in class components represents the initial creation and insertion of a
component into the DOM. During this critical phase, several lifecycle methods are executed in a
specific sequence to ensure proper component initialization. The process begins with the
constructor method, where the component's initial state is established and event handlers are
bound. Following this, the “componentDidMount” method is invoked immediately after the
component is successfully mounted to the DOM, making it the ideal location for performing side
effects such as API calls, setting up subscriptions, or initializing third-party libraries. This phase
also includes the render method, which returns the JSX that defines the component's UI structure.
The mounting phase is executed only once during the component's entire lifecycle, making it
perfect for one-time setup operations that require access to the actual DOM elements.

3.2.2 Updating Phase


The updating phase occurs whenever a class component's state or props change, triggering a re-
evaluation and potential re-rendering of the component. This phase begins with the
“componentDidUpdate” method, which receives the previous props and state as parameters,
allowing developers to compare current values with previous ones and perform conditional
operations based on these changes. The “shouldComponentUpdate” method can be
implemented to optimize performance by preventing unnecessary re-renders when specific
conditions are met. During this phase, the render method is called again to generate the updated
JSX based on the new state or props. The updating phase can occur multiple times throughout a
component's lifecycle, making it essential for handling dynamic data changes, updating the UI in
response to user interactions, and managing side effects that depend on prop or state
modifications.

3.2.3 Unmounting Phase


The unmounting phase marks the final stage of a class component's lifecycle, occurring when the
component is about to be removed from the DOM and destroyed. This phase is primarily
governed by the “componentWillUnmount” method, which serves as the cleanup mechanism for
the component. During this critical phase, developers must perform essential cleanup operations
such as cancelling network requests, clearing timers and intervals, removing event listeners, and
unsubscribing from external data sources to prevent memory leaks and ensure optimal
application performance. The unmounting phase is executed only once, just before the
component is permanently removed from the component tree. Failure to properly handle
cleanup operations during this phase can lead to memory leaks, continued execution of
abandoned processes, and potential application instability, making it one of the most important
phases for maintaining robust and efficient applications.
3.3 Functional Components and Lifecycle Using Hooks

Functional components represent a modern approach to building React applications, offering a


cleaner and more concise syntax compared to traditional class components. Initially, functional
components were limited to rendering static UI elements without access to state management
or lifecycle methods. However, the introduction of React Hooks in version 16.8 revolutionized
functional component development by providing a way to "hook into" React's state and lifecycle
features without writing class components. This paradigm shift has made functional components
the preferred choice for most React development, as they reduce boilerplate code, improve
readability, and encourage better separation of concerns through custom hooks that can
encapsulate and reuse stateful logic across multiple components.

The useEffect hook serves as the primary mechanism for handling lifecycle events in functional
components, effectively replacing the multiple lifecycle methods found in class components with
a single, versatile API. This hook accepts a function that contains the side effect code and an
optional dependency array that controls when the effect should run. When used without a
dependency array, useEffect runs after every render, mimicking the behavior of
componentDidUpdate. With an empty dependency array, it runs only once after the initial render,
similar to componentDidMount. The hook also supports cleanup functions by returning a
function from the effect, which executes when the component unmounts or before the effect
runs again, providing the equivalent functionality of “componentWillUnmount”.

Beyond the basic useEffect patterns, functional components can leverage multiple hooks and
advanced techniques to create sophisticated lifecycle management strategies. Custom hooks can
be created to encapsulate complex lifecycle logic, making it reusable across different
components and promoting cleaner code organization.

Mounting Equivalent
Here's an example usage of getDerivedStateFromProps() component life cycle method:

[Link]

import React from 'react'

class MyComponent extends [Link] {

static getDerivedStateFromProps(nextProps, prevState) {

[Link]([Link])

[Link]([Link])

if ([Link] !== [Link]) {

return {

value: [Link]

};

return null;

constructor(props) {

super(props);

[Link] = {

value: [Link]

render() {

return (

<div>

<h2>Value: {[Link]}</h2>
</div>

);

export default MyComponent.

On execution of the above program, the following output is generated:

The Mounting equivalent demonstrates the Functional components replicating the mounting
phase of class components using the useEffect hook. By passing an empty dependency array ([]),
React ensures the effect runs only once after the initial render. This behavior mirrors
componentDidMount in class components.

The values of current prop and previous state are logged to the console as shown in the following figure:
Change the value of prop to ‘MBA’ as shown below: With this change, the following output is generated
in the browser:

Updating Equivalent

jsx

useEffect(() => {

// Run when dependencies change

[Link]("Component updated!");
}, [someStateOrProp]);

The code demonstrates the uses of the useEffect hook to mimic the update phase in React
functional components. It runs the effect only when someStateOrProp changes, as specified in
the dependency array. This behavior mirrors componentDidUpdate in class components and is
commonly used for side effects like logging or data fetching.

Unmounting Equivalent

jsx

useEffect(() => {

const timer = setInterval(() => [Link]("Running..."), 1000);

return () => {

clearInterval(timer); // Clean up (unmounting)

};

}, []);

The code demonstrates the uses of useEffect with an empty dependency array to run once when
the component mounts. Inside the effect, a timer is started, and the returned function acts as a
cleanup that stops the timer. This cleanup function runs when the component unmounts,
simulating componentWillUnmount in class components.

3.4 Key Lifecycle Use Cases

Use Case Class Component Functional Component (Hooks)


Fetch data on mount componentDidMount() useEffect(() => {}, [])

Cleanup on unmount componentWillUnmount() useEffect(() => { return () => {} }, [])

Update on prop/state componentDidUpdate() useEffect(() => {}, [dep])


change

3.4.1 Practical Example: Fetching API Data


Class Component:

jsx

class User extends [Link] {

state = { user: null };

componentDidMount() {

fetch("/api/user")

.then(res => [Link]())

.then(user => [Link]({ user }));

render() {

return <div>{[Link]?.name}</div>;

Functional Component:

jsx

function User() {
const [user, setUser] = useState(null);

useEffect(() => {

fetch("/api/user")

.then(res => [Link]())

.then(setUser);

}, []);

return <div>{user?.name}</div>;

3.5 Topic summary

The lifecycle of a component describes the entire path of a software component from its
inception to its termination in contemporary frontend frameworks such as React, Vue, and
Angular. This includes three essential stages: mounting (initial creation and DOM integration for
one-time setup tasks like data fetching), updating (managing state and prop alterations that can
happen repeatedly for dynamic UI enhancements and performance improvements), and
unmounting (cleanup and resource management to avert memory leaks prior to component
removal).

Traditional class components utilize specific lifecycle methods such as componentDidMount,


componentDidUpdate, and componentWillUnmount for detailed control; in contrast, modern
functional components utilize React Hooks, especially the flexible useEffect hook added in
version 16.8, which offers a cohesive API that consolidates various lifecycle methods via
dependency arrays that manage execution timing—an empty array [] for mount equivalent, no
array for update equivalent, and cleanup functions for unmount equivalent.
The shift from class components to functional components with hooks has transformed React
development by providing clearer syntax, enhanced separation of concerns, reusable custom
hooks, minimized boilerplate code, and improved maintainability, all while ensuring that
effective lifecycle management is crucial for creating reliable applications with optimal
performance, efficient resource management, and scalable code architecture that avoids
common issues like memory leaks in complicated applications.

3.6 Review questions

1. Analyze the differences between class component lifecycle methods and functional
component hooks in React. In your analysis, discuss:

• The advantages and disadvantages of each approach

• How the useEffect hook replaces multiple class lifecycle methods

• Why React moved towards functional components with hooks

2. A developer notices that their React application is experiencing memory leaks. Explain how
improper lifecycle management could cause this issue and provide specific examples of what
should be cleaned up during the unmounting phase.

Lifecycle Phase Evaluation

[Link] and contrast the three main lifecycle phases (Mounting, Updating, Unmounting) in
terms of:

• When each phase occurs

• What operations are typically performed in each phase

• The frequency of execution for each phase

4. Evaluate the statement: "The useEffect hook with an empty dependency array [] is exactly
equivalent to componentDidMount." Support your evaluation with technical reasoning.
Performance Optimization

A React application is experiencing performance issues due to unnecessary re-renders.

5. Explain how lifecycle methods can be used to optimize component performance in both class
and functional components.

6. Design a strategy using dependency arrays in useEffect to prevent unnecessary API calls when
only specific props change. Include code snippets to illustrate your approach.

Problem-Solving Scenario

You are tasked with converting a legacy class component to a functional component. The class
component has the following lifecycle methods:

• Constructor for initial state

• componentDidMount for API calls

• componentDidUpdate for responding to prop changes

• componentWillUnmount for cleanup

7. Outline the conversion strategy you would use, explaining how each class lifecycle method
would be replaced with hooks.

8. Identify potential challenges in this conversion and how you would address them.

Component Implementation

1. Create a functional component called WeatherWidget that demonstrates proper lifecycle


management. The component should:

• Accept a city prop

• Fetch weather data from an API when the city changes

• Display a loading state while fetching


• Clean up any ongoing requests when unmounting

• Handle error states appropriately

Requirements:

• Use appropriate hooks for lifecycle management

• Implement proper cleanup to prevent memory leaks

• Handle loading and error states

• Code should be well-structured and commented

Debugging Challenge

2. The following functional component has several lifecycle-related issues. Identify and fix all
problems:

jsx

function UserProfile({ userId }) {

const [user, setUser] = useState(null);

const [posts, setPosts] = useState([]);

useEffect(() => {

fetchUser(userId).then(setUser);

fetchUserPosts(userId).then(setPosts);

});

useEffect(() => {

const subscription = subscribeToUserUpdates(userId, (updatedUser) => {


setUser(updatedUser);

});

}, []);

return (

<div>

<h1>{user?.name}</h1>

<PostsList posts={posts} />

</div>

);

Your task:

• Identify all issues with the lifecycle management

• Provide the corrected code with explanations for each fix

Custom Hook Development

Create a custom hook called useDataFetcher that:

• Accepts a URL and dependency array as parameters

• Manages loading, data, and error states

• Automatically refetches when dependencies change

• Cancels ongoing requests when dependencies change or component unmounts

• Returns an object with { data, loading, error, refetch }

Requirements:
• Implement proper lifecycle management

• Handle cleanup and request cancellation

• Provide clear documentation/comments


4 React JSX

Learning Objectives

By the end of this chapter, you will:

• The student must gain an understanding of JSX Syntax and Structure.

• Identify key differences between JSX and HTML attributes (className vs class, htmlFor vs for).

• Implement conditional rendering using ternary operators.

• Handling Events in JSX.

• Apply inline styles using the style attribute with object syntax.

• JSX Performance Considerations and Accessibility in JSX.

4.1 Introduction to React JSX

JSX (JavaScript XML) is an extension of syntax for JavaScript that enables you to write code similar
to HTML directly in your JavaScript files. Created by Facebook for React, JSX connects the logic of
your application with its visual representation, offering a more intuitive and effective approach
to constructing user interfaces.

At first sight, JSX may seem like a combination of HTML and JavaScript, and that's precisely the
intention. It merges the well-known framework of markup with the dynamic features of
JavaScript, enabling developers to build interactive and adaptable user interfaces with
unmatched simplicity and versatility.

Within every React component, there is an embedded render() function that plays a crucial role
in generating the HTML output rendered in a browser. This function defines how the
component's UI should be displayed and is responsible for returning the JSX (JavaScript XML)
code that represents the component's structure and content. However, JSX itself is not
understood by JavaScript engines. It needs to be transformed into standard JavaScript code
before it can be executed. This transformation process is typically handled by preprocessors like
Babel, which convert JSX expressions into regular JavaScript objects that can be understood and
parsed by the JavaScript engine.

By using JSX, developers can write code that closely resembles the final HTML structure and
achieve a more concise and readable representation of the component's UI. This allows for easier
maintenance, better collaboration between developers, and improved code organization. The
render() function in a React component is responsible for generating the HTML output that is
rendered in a browser. JSX, an extension of React, enables developers to write JavaScript
functions using a syntax similar to HTML. Preprocessors like Babel transform JSX expressions into
standard JavaScript objects that can be executed by JavaScript engines, allowing for more
intuitive and expressive component definitions.

For example, the following JSX Hello World:

<div>Hello World</div>

is converted into the following function call:

[Link]("div", null, "Hello World");

4.1.1 Why use JSX?


Through JSX React brings several advantages to web development, providing a polished and
efficient approach to building user interfaces. Here are some key benefits of React:

Enhanced Performance: React's code optimization techniques during the translation process
make it faster than regular JavaScript. It employs a virtual DOM that efficiently updates only the
modified components instead of re-rendering the entire HTML structure, resulting in improved
performance and a smoother user experience.
Consolidated Markup and Logic: Unlike traditional web applications where markup and logic
reside in separate HTML and JavaScript files, React combines them within components. This
consolidation simplifies code organization and promotes a more cohesive development approach,
allowing developers to easily manage and maintain both the visual representation and the
functionality of the application.

Type Safety: React offers a type-safe development environment, where most errors are caught
during compilation rather than at runtime. By utilizing tools like TypeScript or PropTypes,
developers can define and enforce strict type checks, enabling early detection of potential errors
and improving overall code reliability.

Streamlined Template Creation: React simplifies the creation of templates by utilizing JSX, a
syntax extension that allows developers to write HTML-like code directly within JavaScript. This
approach provides a more intuitive and concise way to define component structures and their
dynamic behaviour. JSX is then transformed into standard JavaScript objects, facilitating template
creation and maintenance.

4.2 JSX Syntax and Structure

JSX follows specific syntax rules that differentiate it from regular HTML while maintaining familiar
markup patterns. Understanding these rules is essential for effective React development.

4.2.1 Basic JSX Rules


Single Parent Element: JSX expressions must be wrapped in a single parent element. This can be
a regular HTML element or a React Fragment.

// Valid JSX - single parent div

function MyComponent() {

return (

<div>
<h1>Title</h1>

<p>Content</p>

</div>

);

// Valid JSX - using React Fragment

function MyComponent() {

return (

<>

<h1>Title</h1>

<p>Content</p>

</>

);

// Invalid JSX - multiple parent elements

function MyComponent() {

return (

<h1>Title</h1>

<p>Content</p> // This will cause an error

);
}

Self-Closing Tags: All tags must be properly closed, including self-closing tags that require a
forward slash.

// Correct

<img src="[Link]" alt="Description" />

<input type="text" />

<br />

// Incorrect

<img src="[Link]" alt="Description">

<input type="text">

<br>

JavaScript Expressions: Use curly braces {} to embed JavaScript expressions within JSX.

function Greeting() {

const name = "Alice";

const age = 25;

return (

<div>

<h1>Hello, {name}!</h1>

<p>You are {age} years old.</p>

<p>Next year you'll be {age + 1}.</p>


</div>

);

4.2.2 JSX vs HTML Attribute Differences


JSX uses camelCase naming convention and has specific attribute names that differ from HTML
to avoid conflicts with JavaScript reserved words.

Key Differences:

HTML Attribute JSX Attribute Example


class className <div className="container">
for htmlFor <label htmlFor="email">
tabindex tabIndex <div tabIndex="0">
readonly readOnly <input readOnly />
maxlength maxLength <input maxLength="10" />
// HTML

<div class="container">

<label for="email">Email:</label>

<input type="email" id="email" class="form-input" readonly>

</div>

// JSX

<div className="container">

<label htmlFor="email">Email:</label>

<input type="email" id="email" className="form-input" readOnly />

</div>
4.3 Conditional Rendering in JSX

Conditional rendering allows you to display different content based on certain conditions. JSX
provides several methods to implement conditional rendering.

4.3.1 Ternary Operator


The ternary operator (condition ? trueValue : falseValue) is the most common method for
conditional rendering in JSX.

function UserGreeting({ isLoggedIn, username }) {

return (

<div>

{isLoggedIn ? (

<h1>Welcome back, {username}!</h1>

):(

<h1>Please log in to continue.</h1>

)}

</div>

);

// Usage

<UserGreeting isLoggedIn={true} username="John" />

<UserGreeting isLoggedIn={false} />


4.3.2 Logical AND Operator
Use the logical AND operator (&&) when you want to render something conditionally or nothing
at all.

function Notification({ hasMessages, messageCount }) {

return (

<div>

<h1>Dashboard</h1>

{hasMessages && (

<div className="notification">

You have {messageCount} new messages!

</div>

)}

</div>

);

4.3.3 Complex Conditional Rendering


For more complex conditions, you can use functions or immediately invoked function expressions
(IIFE).

function StatusIndicator({ status }) {

const getStatusMessage = () => {

switch(status) {
case 'loading':

return <div className="spinner">Loading...</div>;

case 'success':

return <div className="success">Operation completed!</div>;

case 'error':

return <div className="error">Something went wrong!</div>;

default:

return <div>Ready</div>;

};

return (

<div className="status-container">

{getStatusMessage()}

</div>

);

4.4 Event Handling in JSX

JSX provides a synthetic event system that wraps native DOM events, providing consistent
behavior across different browsers.
4.4.1 Basic Event Handling
Event handlers in JSX are passed as functions and use camelCase naming convention.

function ButtonExample() {

const handleClick = (event) => {

[Link]('Button clicked!');

[Link]('Event type:', [Link]);

};

const handleMouseOver = () => {

[Link]('Mouse over button');

};

return (

<button

onClick={handleClick}

onMouseOver={handleMouseOver}

onMouseOut={() => [Link]('Mouse left button')}

>

Click Me

</button>

);

}
4.4.2 Form Event Handling
Handling form events requires special attention to controlled components and state
management.

import { useState } from 'react';

function ContactForm() {

const [formData, setFormData] = useState({

name: '',

email: '',

message: ''

});

const handleInputChange = (event) => {

const { name, value } = [Link];

setFormData(prevData => ({

...prevData,

[name]: value

}));

};

const handleSubmit = (event) => {

[Link]();

[Link]('Form submitted:', formData);

// Process form data here

};
return (

<form onSubmit={handleSubmit}>

<input

type="text"

name="name"

value={[Link]}

onChange={handleInputChange}

placeholder="Your Name"

/>

<input

type="email"

name="email"

value={[Link]}

onChange={handleInputChange}

placeholder="Your Email"

/>

<textarea

name="message"

value={[Link]}

onChange={handleInputChange}

placeholder="Your Message"

/>
<button type="submit">Send Message</button>

</form>

);

4.4.3 Event Object and Parameters


You can pass additional parameters to event handlers using arrow functions or the bind method.

function ItemList({ items, onItemClick }) {

return (

<ul>

{[Link](item => (

<li

key={[Link]}

onClick={(event) => onItemClick(event, [Link])}

>

{[Link]}

</li>

))}

</ul>

);

}
4.5 Styling in JSX

JSX provides multiple approaches to styling components, with inline styles being one of the
primary methods recommended by React.

4.5.1 Inline Styles


React strongly recommends the use of inline styles to apply styling to elements. When setting
inline styles in React, it is important to follow the camelCase syntax, where the first word is in
lowercase and the first letter of each subsequent word is capitalized. React also conveniently
handles the addition of the 'px' unit after numeric values for specific elements.

import React from 'react';

const MyComponent = () => {

const divStyle = {

backgroundColor: 'blue',

color: 'white',

fontSize: '20px',

padding: '10px',

borderRadius: '5px',

marginBottom: '15px'

};

const dynamicStyle = {

width: 200, // React adds 'px' automatically


height: 100,

border: '2px solid red',

display: 'flex',

justifyContent: 'center',

alignItems: 'center'

};

return (

<div>

<div style={divStyle}>

Styled with inline styles

</div>

<div style={dynamicStyle}>

Dynamic styling

</div>

</div>

);

};

4.5.2 Dynamic Styling


Inline styles can be dynamically computed based on component state or props.

function ProgressBar({ percentage, color = 'blue' }) {

const containerStyle = {
width: '100%',

height: '20px',

backgroundColor: '#f0f0f0',

borderRadius: '10px',

overflow: 'hidden'

};

const progressStyle = {

width: `${percentage}%`,

height: '100%',

backgroundColor: color,

transition: 'width 0.3s ease'

};

return (

<div style={containerStyle}>

<div style={progressStyle}></div>

</div>

);

4.5.3 CSS Classes vs Inline Styles


While inline styles are powerful, CSS classes are often preferred for complex styling scenarios.

// Using CSS classes

import './[Link]';
function Button({ variant, size, children }) {

const className = `btn btn-${variant} btn-${size}`;

return (

<button className={className}>

{children}

</button>

);

// Combining CSS classes with inline styles

function Card({ title, content, highlighted }) {

const cardStyle = highlighted ? {

boxShadow: '0 4px 8px rgba(0,0,0,0.2)',

transform: 'scale(1.02)'

} : {};

return (

<div className="card" style={cardStyle}>

<h3 className="card-title">{title}</h3>

<p className="card-content">{content}</p>

</div>

);
}

4.6 JSX Performance Considerations

Understanding performance implications of JSX helps in building efficient React applications.

4.6.1 Virtual DOM Optimization


JSX elements are converted to virtual DOM nodes, which React uses to efficiently update the
actual DOM.

// Efficient: React can optimize this structure

function ProductList({ products }) {

return (

<div className="product-list">

{[Link](product => (

<div key={[Link]} className="product-item">

<h3>{[Link]}</h3>

<p>${[Link]}</p>

</div>

))}

</div>

);
}

4.6.2 Key Props for Lists


Always provide unique keys when rendering lists to help React identify which items have changed.

// Good: Using unique, stable keys

function TodoList({ todos }) {

return (

<ul>

{[Link](todo => (

<li key={[Link]}>

<span>{[Link]}</span>

<input

type="checkbox"

checked={[Link]}

onChange={() => toggleTodo([Link])}

/>

</li>

))}

</ul>

);

// Bad: Using array index as key (can cause issues)


function BadTodoList({ todos }) {

return (

<ul>

{[Link]((todo, index) => (

<li key={index}> {/* Avoid this pattern */}

<span>{[Link]}</span>

</li>

))}

</ul>

);

4.6.3 Avoiding Inline Function Creation


Creating functions inline in JSX can impact performance due to unnecessary re-renders.

// Less efficient: Creates new function on each render

function ProductCard({ product, onAddToCart }) {

return (

<div className="product-card">

<h3>{[Link]}</h3>

<button onClick={() => onAddToCart([Link])}>

Add to Cart

</button>

</div>
);

// More efficient: Using useCallback or class methods

import { useCallback } from 'react';

function ProductCard({ product, onAddToCart }) {

const handleAddToCart = useCallback(() => {

onAddToCart([Link]);

}, [[Link], onAddToCart]);

return (

<div className="product-card">

<h3>{[Link]}</h3>

<button onClick={handleAddToCart}>

Add to Cart

</button>

</div>

);

4.7 Accessibility in JSX

JSX supports all HTML accessibility attributes, making it easy to build inclusive web applications.
4.7.1 Semantic HTML Elements
Use appropriate semantic HTML elements to provide meaning and structure.

function Article({ title, author, content, publishDate }) {

return (

<article>

<header>

<h1>{title}</h1>

<p>

By <span className="author">{author}</span>

<time dateTime={publishDate}>

{new Date(publishDate).toLocaleDateString()}

</time>

</p>

</header>

<main>

<p>{content}</p>

</main>

</article>

);

4.7.2 ARIA Attributes


JSX supports all ARIA attributes using camelCase naming convention.
function NavigationMenu({ isOpen, toggleMenu }) {

return (

<>

<button

aria-expanded={isOpen}

aria-controls="navigation-menu"

onClick={toggleMenu}

>

Menu

</button>

<nav

id="navigation-menu"

aria-hidden={!isOpen}

role="navigation"

>

<ul role="menubar">

<li role="none">

<a href="/home" role="menuitem">Home</a>

</li>

<li role="none">

<a href="/about" role="menuitem">About</a>

</li>
</ul>

</nav>

</>

);

4.7.3 Form Accessibility


Ensure forms are accessible with proper labels and descriptions.

function AccessibleForm() {

const [email, setEmail] = useState('');

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

return (

<form>

<div className="form-group">

<label htmlFor="email">

Email Address

<span aria-label="required">*</span>

</label>

<input

type="email"

id="email"

value={email}
onChange={(e) => setEmail([Link])}

aria-describedby="email-help email-error"

aria-invalid={!![Link]}

required

/>

<div id="email-help" className="help-text">

We'll never share your email address.

</div>

{[Link] && (

<div id="email-error" className="error-text" role="alert">

{[Link]}

</div>

)}

</div>

</form>

);

}
4.8 Best Practices and Common Patterns

4.8.1 4.8.1 Component Composition


Use component composition to build complex UIs from simpler components.

function Card({ children, title, footer }) {

return (

<div className="card">

{title && <div className="card-header">{title}</div>}

<div className="card-body">{children}</div>

{footer && <div className="card-footer">{footer}</div>}

</div>

);

function UserProfile({ user }) {

return (

<Card

title={<h2>{[Link]}</h2>}

footer={<button>Edit Profile</button>}

>

<img src={[Link]} alt={`${[Link]}'s avatar`} />

<p>{[Link]}</p>

</Card>
);

4.8.2 Prop Destructuring


Use destructuring to make component props more readable.

// Instead of this

function UserCard(props) {

return (

<div>

<h3>{[Link]}</h3>

<p>{[Link]}</p>

<button onClick={[Link]}>Edit</button>

</div>

);

//Use this

function UserCard({ user: { name, email }, onEdit }) {

return (

<div>

<h3>{name}</h3>

<p>{email}</p>
<button onClick={onEdit}>Edit</button>

</div>

);

4.9 Chapter Summary

JSX is a powerful syntax extension that bridges the gap between JavaScript logic and HTML
markup in React applications. It provides an intuitive way to describe user interfaces while
maintaining the full power of JavaScript. Key takeaways from this chapter include:

JSX transforms HTML-like syntax into JavaScript function calls, making component development
more intuitive and maintainable. The syntax differs from HTML in specific ways, such as using
className instead of class and htmlFor instead of for, following JavaScript naming conventions.

Conditional rendering in JSX can be achieved through ternary operators, logical AND operators,
and function-based approaches, providing flexibility in displaying dynamic content based on
application state.

Event handling in JSX uses a synthetic event system that provides consistent cross-browser
behavior, with event handlers passed as functions using camelCase naming conventions.

Styling in JSX can be accomplished through inline styles using JavaScript objects with camelCase
property names, allowing for dynamic styling based on component state and props.

Performance considerations include proper use of keys in lists, avoiding inline function creation
in render methods, and understanding how the virtual DOM optimizes updates.

Accessibility in JSX is achieved by using semantic HTML elements, proper ARIA attributes, and
ensuring forms are properly labeled and described for screen readers and other assistive
technologies.
By mastering these JSX concepts and patterns, developers can build robust, performant, and
accessible React applications that provide excellent user experiences across different devices and
browsers.
5 Building Apps in ReactJS

Learning Objectives

By the end of this chapter, learners will be able to:

• Define ReactJS and explain its core concepts and philosophy


• Understand the role of React in modern web development
• Identify the primary use cases and applications of React
• Analyse the advantages and disadvantages of using React for web development
• Explain the Virtual DOM concept and its performance benefits
• Understand component-based architecture and its benefits
• Set up a React development environment
• Create and structure basic React applications

5.1 Introduction to ReactJS

ReactJS represents a paradigm shift in how we approach building user interfaces for web
applications. Developed by Facebook (now Meta) in 2013, React has fundamentally changed the
landscape of front-end development by introducing a component-based architecture that
promotes reusability, maintainability, and scalability.

The emergence of React addressed several critical challenges that developers faced with
traditional DOM manipulation approaches. Before React, developers often struggled with
complex state management, inefficient DOM updates, and maintaining large-scale applications.
React's declarative approach and innovative concepts like the Virtual DOM have made it one of
the most popular JavaScript libraries for building user interfaces.
Understanding React is crucial for modern web developers, as it forms the foundation for
numerous frameworks and influences how we think about user interface development. This
chapter will provide you with a comprehensive understanding of React's core concepts, its
applications, and why it has become an industry standard.

5.1.1 What is React?


React is a declarative, efficient, and flexible JavaScript library for building user interfaces,
particularly web applications. At its core, React is designed around the concept of building
complex UIs from small, isolated pieces of code called "components."

5.1.2 Primary Applications of React


1. Web Applications: React builds dynamic Single-Page Applications (SPAs) like Facebook and
Netflix, as well as Progressive Web Apps (PWAs) that offer native app-like experiences with offline
capabilities and push notifications.
2. Cross-Platform Development: Through React Native, developers create native mobile apps for
iOS and Android, while Electron enables desktop applications like Discord and VS Code across
Windows, macOS, and Linux.
3. Content-Driven Sites: React powers static websites with interactive features using tools like
Gatsby and [Link], making it ideal for blogs, documentation, and marketing sites.
4. Enterprise Solutions: React's scalability supports large-scale business applications including
dashboards, content management systems, and CRM tools.
The key advantage is React's unified component-based approach that allows developers to use
the same concepts across web, mobile, and desktop platforms, maximizing code reusability and
developer efficience.

5.1.3 [Link] Prerequisites -

JavaScript Fundamentals (Essential):


• ES6+ features: arrow functions, destructuring, template literals, modules
• Functions, objects, arrays, and their manipulation methods
• Asynchronous programming: promises, async/await, API calls
• DOM manipulation and event handling

HTML Basics (Required):

• Structure: Understanding of HTML document structure, DOCTYPE, head/body sections


• Elements: Common tags (div, span, h1-h6, p, a, img, ul/ol/li, form, input, button)
• Attributes: id, class, src, href, alt, and data attributes
• Semantic HTML: header, nav, main, section, article, aside, footer

CSS Basics (Required):

• Selectors: Element, class (.class), ID (#id), and attribute selectors


• Properties: color, background, margin, padding, border, font, display
• Layout: Flexbox, Grid basics, positioning (static, relative, absolute)
• Responsive Design: Media queries and mobile-first approach
• Box Model: Understanding margin, border, padding, and content areas

5.2 Essential Software for React Development

5.2.1 Core Requirements:


• [Link] & npm: Required for package management and running React applications (download
from [Link])

• Code Editor: Visual Studio Code is the most popular choice, enhanced with extensions like
ESLint, Prettier, and React snippets for better development experience

Development Tools:
• React Developer Tools: Browser extension for Chrome/Firefox that allows inspection of React
component hierarchies and debugging

• Project Scaffolding: Either Create React App (npx create-react-app my-app) or Vite (npm create
vite@latest my-app) to quickly set up new React projects with proper configuration

5.2.2 How to setup React enviroment

To start using React, you can create a new project with Create React App:

Recommended IDE is Visual Studio Code & NodeJS please download & install on the following links
below

1. [Link]
2. [Link]

Step One. Create a folder on the desktop and name it ReactJS (any othername will do as well)

Step Two. Open the folder in the VS Code as depicted Below

Step Three. Open Terminal tab and select New Termianal enter the following commands
1. npm create vite@latest
2. give your project a name
3. select a framework (React)
4. select varient (JavaScript)
5. Now runthe following commands

• cd new-app (app name if you have given a different name, please use that name )
• npm install
• npm run dev
Step 6. Copy localhost and paste in Chrome browser (recomemended)

[Link]

Congratulationsyou have successully configured ReactJS

Your App Structure should be as follows


For a quick summary visit [Link]

Install the following extensions

1. Prettier - Code formatter


2. Live Server

5.3 First Single Page application (Hello World)

React applications are constructed from components - individual UI elements that combine their
own functionality with visual presentation. Components can range from simple elements like
buttons to complex structures like complete pages.
React components are JavaScript functions that output markup code:

The core concept remains the same: components serve as the fundamental building blocks of
React applications, each encapsulating both behavior and display logic within reusable JavaScript
functions that generate the necessary markup for rendering.

Here's the complete code showing how components can be nested

[Link]

Browser Output
A key distinction in React! The capitalization rule helps React differentiate between:

• React components: <MyButton />, <MyApp /> - always capitalized

• HTML elements: <div>, <h1>, <button> - always lowercase

This naming convention is crucial because React uses it to determine whether to render a custom
component or a built-in HTML element.

When this code runs, you'll see:

• The heading "Welcome to my React app"

• Below it, a button displaying "I'm a React button"

The MyButton component gets rendered wherever <MyButton /> appears in the JSX, making it a
reusable piece of UI that can be easily included in different parts of your application.

[Link] [Link]
5.7 What is JSX in React?

JSX (JavaScript XML) is a syntax extension for JavaScript that allows you to write HTML-like code
directly within JavaScript files. It was created by Facebook specifically for React to make
component creation more intuitive and readable.

5.8 Virtual DOM vs. Browser DOM


Consider the Browser DOM as the actual construction site of your web page - it's the real,
heavyweight structure that browsers use to render what users see. However, making changes
directly to this structure is expensive and time-consuming.

React's Virtual DOM acts like an architect's draft blueprint - a fast, lightweight copy kept in
memory. When changes are needed, React first updates this digital sketch, compares it with the
previous version, then efficiently applies only the necessary modifications to the actual Browser
DOM. This approach is like planning renovations on paper before touching the real building,
resulting in much faster and smoother updates.

5.9 Components: The Building Blocks


In React, your entire application is constructed from components - think of them as modular
building blocks that can be assembled, rearranged, and updated independently. When your app
needs to change, React orchestrates these updates through a streamlined process:

1. State Changes: React detects when data in your application has been modified and identifies
which components need attention

2. Calculate Updates: React intelligently determines exactly what has changed by comparing the
current Virtual DOM with the previous version, identifying only the specific differences
3. Efficient Re-rendering: The actual Browser DOM receives only the precise updates needed - no
unnecessary modifications. Through React's optimization strategies, your application maintains
peak performance and responsiveness, regardless of its complexity.

5.4 React Components

Components allow you to break down your user interface into separate, reusable parts that you
can work on independently. Think of components as special JavaScript functions - they take in
data (called "props") and return instructions for what should be displayed on the screen.

This modular approach makes your code easier to manage, test, and reuse across different parts
of your application.
Key Concepts:

1. Modular: Break UI into independent, manageable pieces


2. Reusable: Use the same component multiple times with different data
3. Isolated: Each component manages its own logic and state
4. Composable: Combine simple components to build complex interfaces
5. Declarative: Describe what the UI should look like, not how to achieve it

5.4.1 Functional Components (Modern Approach - Recommended)


Functional components are JavaScript functions that return JSX. They are simpler, more concise,
and support React Hooks.

Building Modern Web Applications with ReactJS Functional Components

For developers creating dynamic and scalable web applications, ReactJS functional components
are an essential tool. ReactJS stands as one of the most widely-used JavaScript libraries,
empowering developers to build reusable UI elements for web applications. The introduction of
React hooks has transformed functional components into powerful building blocks, allowing
developers to implement sophisticated functionality with concise, readable code. This guide
examines ReactJS functional components, their mechanics, and their role in creating
maintainable applications.

Understanding ReactJS Functional Components

ReactJS functional components are JavaScript functions that output JSX elements - templates
defining the component's visual structure. JSX combines HTML-like syntax with JavaScript
capabilities, creating a seamless development experience. While originally designed for
presentational purposes without state or complex behavior, modern functional components can
handle any use case through hooks. Their straightforward nature makes them lightweight,
testable, and perfect for building user interfaces.

The Mechanics of Functional Components


Functional components accept data through props - JavaScript objects containing property-value
pairs passed from parent components. The component processes these props and generates a
JSX structure describing its appearance and behavior. During rendering, React constructs a virtual
DOM representation of the application's current state. When props change or component state
updates, React efficiently updates the virtual DOM and re-renders only the necessary parts of the
component.

Benefits of Choosing Functional Components

1. Clarity: Their function-based structure creates more readable and maintainable code,
particularly beneficial for projects of any size.
2. Efficiency: Without class instantiation overhead or this binding complexities, functional
components deliver superior rendering performance.
3. Testing Ease: Pure function nature makes them straightforward to test, with predictable inputs
and outputs simplifying unit testing strategies.
4. Modularity: High reusability across different projects makes them valuable for component
libraries and design systems.

Here's a basic example of a React Functional Component called App that returns JSX:

This component demonstrates the fundamental structure of a functional component - it's a


JavaScript function that returns JSX elements describing what should appear on the screen.
5.4.2 How to Create a ReactJS Functional Component?
Creating a ReactJS functional component involves defining a JavaScript function that returns JSX.
Here's the basic approach.

5.4.3 When to Use ReactJS Functional Components


Functional components are now the preferred approach for React development and should be
used in virtually all scenarios. Here's when and why:

Primary Use Cases

1. Default Choice: Functional components should be your go-to option for new React
development. They work for both simple presentational components and complex stateful
components.
2. State Management: With React Hooks (introduced in React 16.8), functional components can
handle state using useState, useReducer, and other hooks, eliminating the previous limitation.
3. Lifecycle Operations: Hooks like useEffect provide all the functionality previously available only
in class component lifecycle methods.
Modern Context

The information about functional components being limited is outdated. Since React 16.8,
functional components with hooks can:

• Manage local state with useState


• Handle side effects with useEffect (replaces componentDidMount, componentDidUpdate, etc.)

• Access context with useContext

• Optimize performance with useMemo and useCallback

Advantages of Functional Components

1. Simplicity: Cleaner syntax with less boilerplate code compared to class components.
2. Performance: Generally, more efficient due to reduced overhead and better optimization by
React.
3. Testing: Easier to test since they're pure functions that take props and return JSX.
4. Modern Patterns: Better integration with modern React patterns like hooks, concurrent
features, and the latest React development tools.
5. Code Reusability: Custom hooks allow sharing stateful logic between components more
effectively than class-based patterns.

5.4.4 React Functional Components with Props


Props serve as the communication mechanism between React components, enabling data flow
down the component hierarchy. Understanding how to work with props in functional components
is fundamental to building dynamic React applications.

Basic Props Implementation

Here's how props work in functional components


How Props Flow

Props function as parameters for React functional components, making components flexible and
reusable. The parent component (App) determines what data to pass down, while the child
component (Headline) remains generic and adaptable. This pattern allows the same component
to render different content based on the props it receives.

When you render a component, props are passed using HTML-like attribute syntax. The receiving
component accesses these props through the function's first parameter, which is always a props
object containing all passed data.

Props Destructuring

Since props arrive as an object and you typically need specific values, JavaScript destructuring
provides a cleaner approach:
Further reading

1. React Arrow Function Component


2. React Stateless Function Component
3. React Function Component: state

5.5 Event Handler in React

Event Handling in React Functional Components

Event handling is a fundamental concept in React that enables user interaction with your
application. Let's explore how to implement event handlers in functional components, starting
with the most common scenarios.

Basic Button Click Events

The simplest event handler example involves a button with an onClick attribute. This attribute
accepts a function that executes whenever the button is clicked:
Arrow Function Syntax

Event handlers can be written using arrow functions for a more concise approach:
However, when multiple event handlers exist in a component, using function declarations can
improve code organization and readability

State Updates with Event Handlers

Event handlers typically implement business logic, often involving state updates. Here's an
example using React's useState hook:

Working with Input Events

Input fields require access to the event object, which React passes as the first parameter to event
handlers. This synthetic event wraps the native HTML event and provides additional functionality:
Controlled Components

To create a controlled component, pass the state value back to the input element through the
value attribute:
Updating the screen

Often, you’ll want your component to “remember” some information and display it. For example,
maybe you want to count the number of times a button is clicked. To do this, add state to your
component.

First, import useState from React:

Here's the complete setup for adding state to your component:


5.5.1 [Link]

5.6 Understanding Hooks

Functions that begin with use are called Hooks. The useState function is a built-in Hook that React
provides. You can discover additional built-in Hooks in the API documentation. It's also possible
to create custom Hooks by combining existing ones.
Hooks have stricter rules than regular functions. You must call Hooks only at the top level of your
components (or within other Hooks). If you need to use useState inside a conditional statement
or loop, you should create a separate component and place it there instead.

Sharing Data Between Components

In the earlier example, each MyButton maintained its own separate count value, and clicking any
individual button only affected that specific button's count:

This demonstrates component isolation - each instance of MyButton has its own state that
operates independently. When you interact with one button, it doesn't influence the state of
other button instances on the page. Each component maintains its own private state unless
explicitly designed to share data with other components.

The

first MyButton updates its count to 1


Initially, each MyButton’s count state is 0

However, often you’ll need components to share data and always update together.
To make both MyButton components display the same count and update together, you need to
move the state from the individual buttons “upwards” to the closest component containing all of
them.

In this example, it is MyApp:

Initially, MyApp’s count state is 0 and is


passed down to both childre On click, MyApp updates its count state to 1
and passes it down to both children

Now when you click either button, the count in MyApp will change, which will change both of the
counts in MyButton. Here’s how you can express this in code.

First, move the state up from MyButton into MyApp:


Then, pass the state down from MyApp to each MyButton, together with the shared click handler.
You can pass information to MyButton using the JSX curly braces, just like you previously did with
built-in tags like <img>:
The information you pass down like this is called props. Now the MyApp component contains the
count state and the handleClick event handler, and passes both of them down as props to each of
the buttons.

Finally, change MyButton to read the props you have passed from its parent component:

When you click the button, the onClick handler fires. Each button’s onClick prop was set to the
handleClick function inside MyApp, so the code inside of it runs. That code calls setCount(count
+ 1), incrementing the count state variable. The new count value is passed as a prop to each
button, so they all show the new value. This is called “lifting state up”. By moving state up, you’ve
shared it between components.
5.7 Working with Hooks

In React, functions that begin with use are known as Hooks. The useState Hook is one of React's
built-in offerings, and you can explore additional built-in Hooks in the official API documentation.
You also have the flexibility to create custom Hooks by combining existing ones.
Hooks come with specific usage rules that make them more restrictive than regular functions.
They must be called at the top level of your components or other Hooks. If you need to use
useState within a conditional statement or loop, the solution is to extract that logic into a separate
component.

Sharing State Between Components

In the earlier example, each MyButton component maintained its own separate count state.
When a button was clicked, only that specific button's count value would update, leaving the
other buttons unaffected

The first MyButton updates its count to 1


Initially, each MyButton’s count state is 0

In many cases, you'll want components to share the same data and update synchronously.

To have both MyButton components show identical count values and change together, you must
relocate the state from each individual button "up" to their nearest shared parent component.

For this example, that shared parent is MyApp:


When you click any button now, the count state in MyApp updates, causing both MyButton
components to reflect the new value. Here's how to implement this in code:

When you click the button, the onClick handler is triggered. Since each button's onClick prop
points to the handleClick function defined in MyApp, that function executes. The function calls
setCount(count + 1), which increases the count state variable by one. This updated count value
gets passed down as a prop to each button, ensuring they all display the same new value. This
pattern is known as "lifting state up" - by relocating state to a higher level, you enable multiple
components to share it.

Example
5.7.1 [Link]

Browser Output
5.8 Lists and Keys in React JS

React employs lists to dynamically render multiple components, with keys serving as identifiers
that help React efficiently detect which items have been modified, inserted, or deleted.

The Purpose of Keys

Keys provide React with a way to uniquely identify elements during list rendering. This enhances
performance by reducing unnecessary re-renders, as React relies on keys to monitor changes
within dynamic lists.

Understanding Lists and Keys in ReactJS

Lists represent collections of elements that you can render using JSX syntax. JSX enables you to
write HTML-like code within JavaScript and use it to build React components. Here's an example
of creating a number list using an array and JSX:

The map() method is a JavaScript array function that accepts a callback function and executes it
on every array element, producing a new array containing the results. In this scenario, we're using
an arrow function that receives a number parameter and returns an <li> element containing that
number as its content.

Example 1: Rendering a Simple List

Here, we use .map() to iterate over the fruits array and render each item inside an <li>.
Browser Output

Example 2: Rendering a List of Objects

Here, each object has a unique id, which we use as the key for better performance.
Browser Output
Example 3: Adding Items to a List Dynamically

The list updates dynamically when clicking the "Add Item" button.

Browser Output
Example 4: Removing an Item from a List

Removes an item from the list using the filter() function.


Browser Output

5.9 Building Forms in React

Forms are essential components in web applications that allow users to input and submit data.
React provides several approaches to handle forms, with controlled components being the most
common and recommended pattern.

Controlled Components

In controlled components, form data is handled by React state rather than the DOM. The input's
value is controlled by React state, and changes are handled through event handlers.

To create interactive controls for submitting information, render the built-in browser <form>
component:
Managing Form Submission on the Client Side

You can pass a function to the action prop of a form to execute that function when the form is
submitted. The function will receive formData as a parameter, allowing you to access all the data
submitted through the form. This approach differs from traditional HTML forms, where the action
attribute only accepts URLs. Once the action function completes successfully, all uncontrolled
form field elements are automatically reset to their initial state.

Browser Output

Showing a Pending State During Form Submission


To show a pending state while a form is being submitted, you can use the useFormStatus Hook
within a component that's rendered inside a <form> element. This Hook returns a pending
property that you can read to determine the submission status.

In this approach, the pending property serves as an indicator that the form is currently processing
the submission.

[Link]

Managing Form Submission Errors

Sometimes the function executed by a <form>'s action prop will throw an error. You can manage
these errors by enclosing the <form> within an Error Boundary component. When the function
triggered by the <form>'s action prop encounters an error, the Error Boundary's fallback
component will be rendered instead of the form.
[Link]

Managing Multiple Submission Actions


Forms can be configured to execute different submission actions depending on which button the
user clicks. You can associate each button within a form with a specific action or behavior by
configuring the formAction prop.
When a user clicks a particular button, the form submits and triggers the corresponding action
defined by that button's attributes and action handler. For example, a form might submit an
article for review as its default behavior, while including an additional button with formAction
configured to save the article as a draft instead.
5.10 Gym Membership Sign up Form Example

[Link]
import React, { useState } from "react";
import "./[Link]";

function App() {
const [formData, setFormData] = useState({
fullName: "",
email: "",
phone: "",
password: "",
});

const handleChange = (e) => {


const { name, value } = [Link];
setFormData((prev) => ({ ...prev, [name]: value }));
};

const handleSubmit = (e) => {


[Link]();
alert(`Thank you for signing up, ${[Link]}!`);
// Here, you'd normally send `formData` to your backend
setFormData({
fullName: "",
email: "",
phone: "",
password: "",
});
};

return (
<div className="signup-container">
<h2>Gym Membership Sign Up</h2>
<form onSubmit={handleSubmit} className="signup-form">
<label>
Full Name:
<input
type="text"
name="fullName"
value={[Link]}
onChange={handleChange}
required
/>
</label>

<label>
Email Address:
<input
type="email"
name="email"
value={[Link]}
onChange={handleChange}
required
/>
</label>
<label>
Phone Number:
<input
type="tel"
name="phone"
value={[Link]}
onChange={handleChange}
required
/>
</label>

<label>
Password:
<input
type="password"
name="password"
value={[Link]}
onChange={handleChange}
required
/>
</label>

<button type="submit">Sign Up</button>


</form>
</div>
);
}

export default App;


[Link]
.signup-container {
max-width: 400px;
margin: 50px auto;
padding: 20px;
border-radius: 10px;
background-color: #f3f3f3;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}

.signup-form {
display: flex;
flex-direction: column;
}

.signup-form label {
margin-bottom: 15px;
font-weight: bold;
}

.signup-form input {
padding: 8px;
margin-top: 5px;
border: 1px solid #ccc;
border-radius: 5px;
}

.signup-form button {
padding: 10px;
background-color: #a72887;
color: rgb(255, 255, 255);
border: none;
border-radius: 5px;
font-size: 16px;
cursor: pointer;
}

.signup-form button:hover {
background-color: #218838;
}

Browser Output
Doctor Appointment Booking Example

[Link]
import React, { useState } from "react";
import "./[Link]";

function App() {
const [formData, setFormData] = useState({
fullName: "",
email: "",
phone: "",
doctor: "",
date: "",
reason: "",
});

const handleChange = (e) => {


const { name, value } = [Link];
setFormData((prev) => ({ ...prev, [name]: value }));
};

const handleSubmit = (e) => {


[Link]();
alert(
`Appointment booked successfully for ${[Link]} with Dr. ${[Link]} on
${[Link]}.`
);

// Reset form
setFormData({
fullName: "",
email: "",
phone: "",
doctor: "",
date: "",
reason: "",
});
};

return (
<div className="form-container">
<h2>Doctor Appointment Booking</h2>
<form onSubmit={handleSubmit} className="appointment-form">
<label>
Full Name:
<input
type="text"
name="fullName"
value={[Link]}
onChange={handleChange}
required
/>
</label>

<label>
Email Address:
<input
type="email"
name="email"
value={[Link]}
onChange={handleChange}
required
/>
</label>

<label>
Phone Number:
<input
type="tel"
name="phone"
value={[Link]}
onChange={handleChange}
required
/>
</label>

<label>
Select Doctor:
<select
name="doctor"
value={[Link]}
onChange={handleChange}
required
>
<option value="">-- Choose Doctor --</option>
<option value="Smith">Dr. Smith</option>
<option value="Patel">Dr. Patel</option>
<option value="Moyo">Dr. Moyo</option>
</select>
</label>

<label>
Appointment Date:
<input
type="date"
name="date"
value={[Link]}
onChange={handleChange}
required
/>
</label>
<label>
Reason for Visit:
<textarea
name="reason"
value={[Link]}
onChange={handleChange}
required
></textarea>
</label>

<button type="submit">Book Appointment</button>


</form>
</div>
);
}

export default App;

[Link]

.form-container {
max-width: 500px;
margin: 50px auto;
padding: 25px;
background-color: #f7f9fa;
border-radius: 10px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}

.appointment-form {
display: flex;
flex-direction: column;
}
.appointment-form label {
margin-bottom: 15px;
font-weight: 500;
}

.appointment-form input,
.appointment-form select,
.appointment-form textarea {
padding: 10px;
margin-top: 5px;
border-radius: 5px;
border: 1px solid #ccc;
width: 100%;
}

.appointment-form textarea {
resize: vertical;
height: 80px;
}

.appointment-form button {
padding: 12px;
background-color: #007bff;
color: white;
font-size: 16px;
border: none;
border-radius: 6px;
cursor: pointer;
margin-top: 10px;
}

.appointment-form button:hover {
background-color: #0056b3;
}

Browser Output
[Link]
import React, { useState } from "react";
import "./[Link]"; // Create this file

function DarkModeToggle() {
const [dark, setDark] = useState(false);

return (
<div className={dark ? "dark-mode" : "light-mode"}>
<h1>{dark ? "Dark" : "Light"} Mode</h1>
<button
className={dark ? "btn-dark" : "btn-light"}
onClick={() => setDark(!dark)}
>
Toggle {dark ? "Light" : "Dark"} Mode
</button>
</div>
);
}

export default DarkModeToggle;

[Link]
.dark-mode,
.light-mode {
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-family: Arial, sans-serif;
text-align: center;
transition: background-color 0.5s, color 0.5s;
}

.dark-mode {
background-color: #333;
color: #fff;
}

.light-mode {
background-color: #fff;
color: #000;
}

.btn-dark,
.btn-light {
padding: 12px 24px;
font-size: 16px;
border: none;
border-radius: 6px;
cursor: pointer;
margin-top: 20px;
transition: background-color 0.3s ease;
}

.btn-dark {
background-color: #555;
color: #fff;
}
.btn-dark:hover {
background-color: #666;
}

.btn-light {
background-color: #007bff;
color: #fff;
}

.btn-light:hover {
background-color: #0056b3;
}

Browser Output
6 References

1. Naik, P.G. and Oza, K.S. (2023) Awesome [Link]: unleash the power of modern UI building.
International Institute of Organized R
2. Banks, A. and Porcello, E. (2017) Learning React: functional web development with React and
Redux. Sebastopol, CA: O'Reilly Media.

You might also like