React Js
React Js
And ReactJS
Brief history of Web Applications
● Initially: static HTML files only with HTML forms for input
Responsibilities:
● Web application's model data needs are specified by the view designers
But need to be persisted by the database
● Conflict: Database Schemas don't like changing frequently but web
application model data might (e.g. user will like this view better if we add …
and lose ...)
Fourth-generation frameworks
Examples: React.js, Vue.js, Angular(v2)
● Virtual DOM
○ Render view into DOM-like data structure (not real DOM)
○ Benefits: Performance, Server-side rendering, Native apps
ReactJS
● JavaScript framework for writing the web applications
○ Like AngularJS - Snappy response from running in browser
○ Less opinionated: only specifies rendering view and handling user interactions
Component #1 Babel
Webpack
Component #2 Babel Output
Bundle.js
...
Component #N Babel
};
export default ReactAppView;
<div>
<label>Name: </label>
ReactAppView render() method <input type="text" … />
<h1>Hello!</h1>
</div>
render() {
let label = React.createElement('label', null,'Name: ');
let input = React.createElement('input',{type:'text'});
let h1 = React.createElement('h1',null ,'Hello!');
return React.createElement('div', null, label, input, h1);
}
Returns element tree with div (label, input, and h1) elements
ReactAppView render() method w/o variables
render() {
return React.createElement('div', null,
React.createElement('label', null,'Name: '),
React.createElement('input',
{ type: 'text', value: this.state.yourName,
onChange: (event) => this.handleChange(event) }),
React.createElement('h1', null,
'Hello ', this.state.yourName, '!')
);
}
Use JSX to generate calls to createElement
render() {
return (
<div>
<label>Name: </label>
<input type="text" />
<h1>Hello!</h1>
</div>
);
}
● JSX makes building tree look like templated HTML embedded in JavaScript.
App.js - use functions to create elements
function App() {
return (
<div>
<label>Name: </label>
<input type="text" />
<h1>Hello!</h1>
</div>
);
}
● JSX
const myElement = <h1>I Love JSX!</h1>;
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(myElement);
JSX Rules
● A React component name must be capitalized (otherwise treated as built-
in components)
● Return multiple HTML elements
const App = () => {
return (
<div>
<h1>Hello World!</h1>
<p>Tanishka here!</p>
</div>
);
}
JSX Rules
● Every tag, including self closing tags, must be closed. In case of self
closing tags you have to add a slash at the end
const App = () => {
return (
<>
<img src="./assets/react.svg" alt="" />
</>
);
}
JSX Rules
● JSX is closer to JavaScript than to HTML, the React DOM uses the
camelCase naming convention for HTML attribute names.
For example: tabIndex, onChange, and so on.
</span>
);
Use JS in JSX
● Put plain JavaScript code in curly brackets
const App = () => {
const name = "Tanishka";
return (
<>
<h1>My name is {name}</h1>
</>
);
}
JSX templates must return a valid children param
let greeting;
const en = "Hello"; const sp = <b>Hola</b>;
let {useSpanish} = this.prop;
if (useSpanish) {greeting = sp} else {greeting = en};
<div>{greeting}</div>
Iteration in JSX
● Use JavaScript array variables
let listItems = [];
for (let i = 0; i < data.length; i++) {
listItems.push(<li key={data[i]}>Data Value {data[i]}</li>);
}
return <ul>{listItems}</ul>;
● Functional programming
<ul>{data.map((d) => <li key={d}>Data Value {d}</li>)}</ul>
key= attribute improves efficiency of rendering on data change
React Component and Props
React Components
● Independent and reusable blocks of code which work in isolation
● The main advantage of components is that they help reduce redundancy.
Types of React Components
● Class components
class Greet extends React.Component {
constructor (props) { … }
render () { return <h1>Hello World!</h1>;}
}
● Functional components:
function Greet() {
return <h1>Hello World!</h1>;
}
Or
const Greet = () => <h1>Hello World!</h1>
Nested Components
● Creating more complex User Interfaces and getting rid of redundant code
const Book = () => {
return (
<div>
<h1>Book name : Cracking The Coding Interview</h1>
<h2>Author : Gayle Laakmann McDowell</h2>
</div>
);
};
● State change is one of the two things that make a React component
re-render (the other is a change in props)
o In this way, the state stores information about the component and also controls its
behavior.
Component state and input handling
import React from 'react';
class ReactAppView extends React.Component {
constructor(props) {
Make <h1>Hello {this.state.yourName}!</h1>
super(props); work
this.state = {yourName: ""};
}
handleChange(event) {
this.setState({yourName: event.target.value});
}
....
Doesn't work!
Calling React Components from events workaround
● Create instance function bound to instance
http://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/
Example of lifecycle methods - update UI every 2s
class Example extends React.Component {
...
componentDidMount() { // Start 2 sec counter
const incFunc =
() => this.setState({ counter: this.state.counter + 1 });
this.timerID = setInterval(incFunc, 2 * 1000);
}
Or using destructuring...
function MyComponent({name}) {
return <div>My name is {name}</div>;
}
● Note: if the second argument (array) is empty, the effect will run
after every re-renders, otherwise it is only run when the variables in
the array has changed.
Cleanup function in useEffect
● To use the cleanup function, we need to return a function from
within the useEffect function.
function Timer() {
const [time, setTime] = useState(0);
useEffect(() => {
let interval = setInterval(() => setTime(1), 1000);
return () => {
// setInterval cleared when component unmounts
clearInterval(interval);
}
}, []);
}
Communicating between React components
● Passing information from parent to child: Use props (attributes)
<label htmlFor="email">Email:</label>
<input type="email" id="email" name="email" value={formData.email} onChange={handleChange}/>
<label htmlFor="message">Message:</label>
<textarea id="message" name="message" value={formData.message} onChange={handleChange}/>
<button type="submit">Submit</button>
</form>
);
}
Using useState hook: input validation
function MyForm() {
const [inputValue, setInputValue] = useState('');
const [inputError, setInputError] = useState(null);
function handleInputChange(event) {
const value = event.target.value;
setInputValue(value);
if (value.length < 5) {
setInputError('Input must be at least 5 characters');
} else {
setInputError(null);
}
}
Using useState hook: input validation
function handleSubmit(event) {
event.preventDefault();
if (inputValue.length >= 5) {
// submit form
} else {
setInputError('Input must be at least 5 characters');
}
}
return (
<form onSubmit={handleSubmit}>
<label>
Fruit:
<input type="text" value={inputValue} onChange={handleInputChange} />
</label>
{inputError && <div style={{ color: 'red' }}>{inputError}</div>}
<button type="submit">Submit</button>
</form>
);
}
Uncontrolled component: Using useRef hook
● Use ref to get the current value of the input
● handleSubmit: process the input value
import { useRef } from "react";
function handleSubmit(event) {
event.preventDefault();
console.log("Input value:", inputRef.current.value);
console.log("Select value:", selectRef.current.value);
console.log("Checkbox value:", checkboxRef.current.checked);
}
Using useRef hook
return (
<form onSubmit={handleSubmit}>
<label>
<p>Name:</p>
<input ref={inputRef} type="text" />
</label>
<label>
<p>Favorite color:</p>
<select ref={selectRef}>
<option value="red">Red</option>
<option value="green">Green</option>
<option value="blue">Blue</option>
</select>
</label>
<label>
Do you like React?
<input type="checkbox" ref={checkboxRef} />
</label>
<button type="submit">Submit</button>
</form>
);
}
Use component library: React hook form
● Need to install the library: npm install react-hook-form
● The useForm hook provides several functions and properties that you
can use to manage your form:
o register: This function is used to register form fields with React Hook Form.
o errors: This represents an object containing any validation errors that occur when a
form is submitted.
o watch: This function is used to watch for changes to specific form fields. It takes an
array of form field names and returns the current value of those fields.
Use component library: React hook form
import { useForm } from 'react-hook-form';
function LoginForm() {
const { register, handleSubmit, formState: { errors } } = useForm();
const onSubmit = (data) => {
console.log(data);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<label>Email</label>
<input type="email" {...register("email", { required: true, pattern: /^\S+@\S+$/i })} />
{errors.email && <p>Email is required and must be valid</p>}
<label>Password</label>
<input type="password" {...register("password", { required: true })} />
{errors.password && <p>Password is required</p>}
<button type="submit">Submit</button>
</form>
);
}
Data Handling
What is a API?
● API stands for Application Programming Interface. It enables the
exchange of information and functionality between different systems
o E.g between a website and a server or between different software applications
● An API functions as a waiter for software applications. It is a set of
rules that lets one program ask another for something it needs.
● Why are APIs important in web development?:
o Web applications need APIs to get data from various sources, like databases or
websites.
o APIs are a scalable option for managing high data or request volumes.
o Developers use APIs to leverage existing features and services. This saves them from
reinventing the wheel.
o They keep things safe by ensuring that only authorized individuals or programs can
use them.
o An API makes a website or mobile app more enjoyable to use by integrating data.
Restful API
● REST (Representational State Transfer) is an architectural style that defines a
set of constraints to be used when creating web services
o RESTful APIs follow several key principles, including statelessness, uniform interface, and
resource-based interactions.
● Anatomy of a RESTful API:
o A RESTful API consists of resources, each identified by a unique URI (Uniform Resource
Identifier).
o These resources can be manipulated using standard HTTP methods such as GET, POST, PUT,
PATCH, and DELETE.
o The API responses typically include data in a format like JSON (JavaScript Object Notation) or
XML (eXtensible Markup Language).
● RESTful API Endpoints: Endpoints are specific URLs that represent the
resources exposed by a RESTful API.
o For example, a simple blog API might have endpoints like /posts to retrieve all blog posts and
/posts/{id} to retrieve a specific post by its unique identifier.
How to Make API Requests in React
return (
<div>
<h1>API Data</h1>
<ul>
{data.map((item) => (
<li key={item.id}>{item.title}</li>
))}
</ul>
</div>
);
};
Making GET Requests: Enhance previous example
const ApiExample = () => {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchData = async () => {
try {
// Simulating a delay to show loading state
setTimeout(async () => {
const response = await fetch('https://api.example.com/posts?userId=1');
const result = await response.json();
setData(result);
setLoading(false);
}, 1000);
} catch (error) {
console.error('Error fetching data:', error);
setLoading(false);
}
};
fetchData();
}, []);
Making GET Requests: Enhance previous example
● A loading state is introduced to provide feedback to users while the
data is being fetched
return (
<div>
<h1>API Data</h1>
{loading ? (
<p>Loading...</p>
) : (
<ul>
{data.map((item) => (
<li key={item.id}>{item.title}</li>
))}
</ul>
)}
</div>
);
};
Handling Asynchronous Operations with async/await
● The use of async/await syntax makes asynchronous code more readable
and easier to work with
● The fetchData function is declared as an asynchronous function using the
async keyword. This allows the use of await inside the function
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch('https://api.example.com/posts?userId=1');
const result = await response.json();
setData(result);
setLoading(false);
} catch (error) {
console.error('Error fetching data:', error);
setLoading(false);
}
};
fetchData();
}, []);
Error Handling When Fetching Data
const ApiExample = () => {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch('https://api.example.com/posts?userId=1');
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const result = await response.json();
setData(result);
setLoading(false);
} catch (error) {
console.error('Error fetching data:', error);
setError('An error occurred while fetching the data. Please try again later.');
setLoading(false);
}
};
fetchData();
}, []);
Error Handling When Fetching Data
● The response.ok property is checked to determine if the HTTP request was
successful. If not, an error is thrown with information about the HTTP status
return (
<div>
<h1>API Data</h1>
{loading ? (
<p>Loading...</p>
) : error ? (
<p>{error}</p>
) : (
<ul>
{data.map((item) => (
<li key={item.id}>{item.title}</li>
))}
</ul>
)}
</div>
);
};
Display API Data in React Components
import React, { useState, useEffect } from 'react';
import axios from 'axios';
useEffect(() => {
const fetchData = async () => {
try {
const response = await axios.get('https://api.example.com/data');
setApiData(response.data);
} catch (error) {
console.error('Error fetching data:', error);
}
};
fetchData();
}, []);
Display API Data in React Components
return (
<div>
<h2>API Data Display</h2>
{apiData ? (
// Render your component using the fetched data
<MyComponent data={apiData} />
) : (
// Render a loading state or placeholder
<p>Loading...</p>
)}
</div>
);
};
return (
<div>
<h2>Delete Data</h2>
<button onClick={handleDelete}>Delete</button>
</div>
);
};