It is a popular open-source JavaScript library used for building user interfaces, particularly single-page applications (SPA).
Isomorphic
Technology is isomorphic when it can run in both server and client
Ex. React JS, Next JS
Know how
Browsers don’t support directly including or loading JavaScript files from within other JavaScript files. The loading of JavaScript files is managed by the HTML document through script tags.
But, once installed as a package, we need something to
put all the code together that can be included in the HTML so that the browser can get access to the code. For this, there are build tools such as browserify or webpack that can
put together your own modules as well as third-party libraries in a bundle that can be included in the HTML.
Important features of ReactJs
Component-Based Architecture
It helps to create components that manages it's own state
Supports server-side rendering as well as client-side rendering
Virtual DOM:
When the state of an object changes, React updates the virtual DOM first, and then it efficiently updates the real DOM only where changes have occurred. It uses diffing algorithm to detect changes periodically
JSX Syntax:
React uses JSX (JavaScript XML), a syntax extension that allows you to write HTML directly within JavaScript.
MVC (Model View Controller)
It is a design pattern in which application is separated into three interconnected components
Model
Represent the business and data logic. This can include fetching data from a server, interacting with a database, or managing in-memory data(State management).
View
Represent rendering of UI and presenting data to the user
// UserView.js
import React from 'react';
// This is a simple React functional component that acts as the View
function UserView({ user }) {
return (
<div>
<h1>User Information</h1>
<p>Name: {user.name}</p>
<p>Email: {user.email}</p>
</div>
);
}
export default UserView;
Controller
Manages the interaction between Model and View. It handles user input, manipulates data through the Model, and updates the View
// UserController.js
import React, { useState, useEffect } from 'react';
import UserView from './UserView';
import { fetchUserData, updateUserData } from './model';
function UserController() {
const [user, setUser] = useState(null);
useEffect(() => {
// Fetch user data when the component mounts
const userData = fetchUserData();
setUser(userData);
}, []);
const handleUpdate = () => {
// Update user data and refresh view
const newData = { name: 'Jane Doe', email: 'jane.doe@example.com' };
updateUserData(newData);
setUser(newData); // Update local state to reflect changes
};
if (!user) {
return <div>Loading...</div>;
}
return (
<div>
<UserView user={user} />
<button onClick={handleUpdate}>Update User</button>
</div>
);
}
export default UserController;
Class Component
import React, { Component } from 'react';
// Define the class component
class MyComponent extends Component {
// Initial state
constructor(props) {
super(props);
this.state = {
// Define your initial state here
count: 0
};
// Bind event handlers if necessary
this.handleClick = this.handleClick.bind(this);
}
// Lifecycle method: componentDidMount
componentDidMount() {
// Code to run after the component has been mounted
console.log('Component did mount');
}
// Lifecycle method: componentDidUpdate
componentDidUpdate(prevProps, prevState) {
// Code to run after the component updates
console.log('Component did update');
}
// Lifecycle method: componentWillUnmount
componentWillUnmount() {
// Code to run before the component unmounts
console.log('Component will unmount');
}
// Event handler method
handleClick() {
this.setState(prevState => ({
count: prevState.count + 1
}));
}
// Render method
render() {
return (
<div>
<h1>Hello, {this.props.name}!</h1>
<p>Current count: {this.state.count}</p>
<button onClick={this.handleClick}>Increase Count</button>
</div>
);
}
}
// Default props (optional)
MyComponent.defaultProps = {
name: 'World'
};
export default MyComponent;
Props (short for properties)
They are read-only attributes passed from a parent component to a child component, enabling the sharing of data and configuration between components.
Props are like arguments you pass to a function. They let a parent component pass data to a child component and customize its appearance
//default value for props
function Avatar({ person, size = 100 }) {
// ...
}
export default function Profile() {
return (
<Avatar
person={{ name: 'Lin Lanying', imageId: '1bX5QH6' }}
size={100}
/>
);
}
State
State is like a component’s memory. It lets a component keep track of some information and change it in response to interactions
state is fully private to the component declaring it
Event Propagation
events typically propagate through the DOM tree in two phases: the capture phase and the bubble phase.
Event Propagation Phases
Capture Phase: The event starts from the top of the DOM tree and travels down to the target element.
Bubble Phase: After reaching the target element, the event bubbles back up to the top of the DOM tree.
<div id="container" onclick="handleDivClick()">
<button onclick="handleButtonClick1()">Button 1</button>
<button onclick="handleButtonClick2()">Button 2</button>
</div>
function handleDivClick() {
console.log('Div clicked');
}
function handleButtonClick1() {
console.log('Button 1 clicked');
}
function handleButtonClick2() {
console.log('Button 2 clicked');
}
Click on Button 1:
The event is first captured and handled by handleButtonClick1().
After that, the event bubbles up to handleDivClick().
If you want to prevent the event from bubbling up to parent elements, you can use the event.stopPropagation() method within the button's onClick handler:
function handleButtonClick1(event) {
event.stopPropagation();
console.log('Button 1 clicked');
}
screen updates follow a lifecycle that involves three primary phases: Trigger, Render, and Commit.
Trigger
Description: This phase begins when an event or state change prompts an update in the React component
Render
Description: During this phase, React computes what the new UI should look like based on the changes. React performs a reconciliation process to determine the minimal set of changes required to update the DOM
Commit
Description: This is the final phase where React applies the changes to the actual DOM based on the diffing results
Batching:
Batching of state updates is a key optimization technique in React that helps improve performance by reducing the number of re-renders and DOM updates.
Batching refers to the process of grouping multiple state updates together into a single update.
function MyComponent() {
const [count, setCount] = useState(0);
const [text, setText] = useState('');
const handleClick = () => {
setCount(count + 1);
setText('Updated');
};
return (
<div>
<p>Count: {count}</p>
<p>Text: {text}</p>
<button onClick={handleClick}>Update</button>
</div>
);
}
When handleClick is invoked by clicking the button, both setCount and setText are called.
React batches these state updates together, performs a single re-render, and applies both updates in one go.
Synthetic Event
It is an object that is a cross-browser wrapper around the native browser events. React implements its own event system to provide a consistent and performant way to handle events in a cross-browser manner.
React uses a single event listener for all events and delegates the event handling to a common parent element (the root of the DOM tree). This reduces the overhead of attaching and managing multiple event listeners.
Array
Map
In React, the map method is commonly used to render lists of data.
import React from 'react';
const UserList = () => {
const users = [
{ id: 1, name: 'John Doe', email: 'john@example.com' },
{ id: 2, name: 'Jane Smith', email: 'jane@example.com' },
{ id: 3, name: 'Mike Johnson', email: 'mike@example.com' }
];
return (
<div>
<h1>User List</h1>
<ul>
{users.map(user => (
<li key={user.id}>
<h2>{user.name}</h2>
<p>{user.email}</p>
</li>
))}
</ul>
</div>
);
};
export default UserList;
Filter
The filter method in JavaScript is used to create a new array with elements that pass the test implemented by the provided function
const chemists = people.filter(person =>
person.profession === 'chemist'
);
React.Fragment
It allows you to group a list of children without adding extra nodes to the DOM
<>
</>
React.StrictMode
It provide warnings and hints to developers about best practices, deprecated features, and potential problems.
It encourages the use of modern React features like functional components, hooks;
Render Props
It is a powerful pattern to create components in which we pass a function/component as a prop to dynamically determine what to render.
This can be used when the parent component wants access the child component's functions and states
Child component
import React, { useState } from 'react';
function Counter({ render }) {
const [count, setCount] = useState(0);
const increment = () => setCount(count + 1);
const decrement = () => setCount(count - 1);
// Call the render prop function with the current count and control functions
return render({ count, increment, decrement });
}
export default Counter;
Parent component
import React from 'react';
import Counter from './Counter';
function App() {
return (
<div>
<h1>Counter Example</h1>
<Counter
render={({ count, increment, decrement }) => (
<div>
<p>Current Count: {count}</p>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Decrement</button>
</div>
)}
/>
</div>
);
}
export default App;
Difference between ES5 and ES6
Variables
ES5
var name = 'John';
ES6
let name = 'John';
const age = 30;
Function Declaration
ES5
//Arrow functions
var sum = function(a, b) {
return a + b;
};
ES6
const sum = (a, b) => a + b;
Default Parameters
function greet(name) {
var name = name || 'Guest';
return 'Hello, ' + name;
}
ES6
function greet(name = 'Guest') {
return `Hello, ${name}`;
}
Destruction
Destructuring allows unpacking values from arrays or properties from objects into distinct variables.
var person = { name: 'John', age: 30 };
var name = person.name;
var age = person.age;
ES6
const person = { name: 'John', age: 30 };
const { name, age } = person;
Promises
function asyncOperation(callback) {
setTimeout(function() {
callback('result');
}, 1000);
}
ES6
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('result');
}, 1000);
});
promise.then(result => console.log(result));
Import and Export
ES5
// CommonJS
// app.js
const math = require('./math.js');
//math.js
function add(a, b) {
return a + b;
}
function subtract(a, b) {
return a - b;
}
module.exports = {
add,
subtract
};
ES6
// Module
import { mod } from './dep.js';
// Exporting
export function mod() {
return 'Hello';
}
const add = (a, b) => a + b;
const subtract = (a, b) => a - b;
export { add }; // Named export
// export multiple items from a module
// you need to use the same name as the export
export default subtract; // Default export
// export a single value or function from a module
// you can give any name to the imported item.
Classes
ES5
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.greet = function() {
return 'Hello, ' + this.name;
};
ES6
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
return `Hello, ${this.name}`;
}
}
Class component creation
ES5
var MyComponent = React.createClass({
getInitialState: function() {
return { count: 0 };
},
incrementCount: function() {
this.setState({ count: this.state.count + 1 });
},
render: function() {
return (
<div>
<h1>Count: {this.state.count}</h1>
<button onClick={this.incrementCount}>Increment</button>
</div>
);
}
});
ES6
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
this.incrementCount = this.incrementCount.bind(this);
}
incrementCount() {
this.setState({ count: this.state.count + 1 });
}
render() {
return (
<div>
<h1>Count: {this.state.count}</h1>
<button onClick={this.incrementCount}>Increment</button>
</div>
);
}
}
Conditional/ternary Operation
<div>
{isLoggedIn ? (
<AdminPanel />
) : (
<LoginForm />
)}
</div>
Types of Components
Functional Components
These are the simplest type of React components. They are JavaScript functions that receive props as arguments and return JSX to be rendered. Functional components can be stateless or stateful with the help of Hooks.
// Functional Component
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}
Class Components
These components are more traditional and provide additional features compared to functional components, such as lifecycle methods. They are defined using ES6 classes and must extend React.Component
Important points:
It has all lifecycle methods (more overhead compared to functional components)
It is defined using ES6 classes
It is not concise and easy to read like functional components
import React, { Component } from 'react';
class Counter extends Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
increment = () => {
this.setState({ count: this.state.count + 1 });
}
componentDidMount() {
console.log('Component mounted');
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={this.increment}>Click me</button>
</div>
);
}
}
Higher Order Components
HOCs are functions that take a component and return a new component with additional functionality or data.
Controlled Components
In controlled components, the form data is handled by the React component state. The state serves as the "single source of truth" for the input elements.
import React, { useState } from 'react';
function ControlledComponent() {
const [name, setName] = useState('');
const handleChange = (event) => {
setName(event.target.value);
};
const handleSubmit = (event) => {
event.preventDefault();
alert(`A name was submitted: ${name}`);
};
return (
<form onSubmit={handleSubmit}>
<label>
Name:
<input type="text" value={name} onChange={handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
export default ControlledComponent;
Uncontrolled Components
In uncontrolled components, form data is handled by the DOM itself. Instead of using state to control form inputs, refs are used to access form values directly.
Refs are used to directly access and manipulate the DOM elements or to store mutable values that don’t trigger a re-render when changed.
import React, { useRef } from 'react';
function UncontrolledComponent() {
const nameInput = useRef(null);
const handleSubmit = (event) => {
event.preventDefault();
alert(`A name was submitted: ${nameInput.current.value}`);
};
return (
<form onSubmit={handleSubmit}>
<label>
Name:
<input type="text" ref={nameInput} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
export default UncontrolledComponent;
Short-circuit evaluation
It is a technique used to conditionally render components or elements based on certain conditions.
function MyComponent({ isLoggedIn }) {
return (
<div>
<h1>Welcome to the website!</h1>
{isLoggedIn && <p>You are logged in!</p>}
</div>
);
}
Difference between controlled and uncontrolled
import React, { useRef } from 'react';
function UncontrolledForm() {
const inputRef = useRef(null);
// Handle form submission
const handleSubmit = (event) => {
event.preventDefault();
alert('Submitted value: ' + inputRef.current.value); // Access value using ref
};
return (
<form onSubmit={handleSubmit}>
<label>
Uncontrolled Input:
<input
type="text"
ref={inputRef} // Attach ref to access DOM value
/>
</label>
<button type="submit">Submit</button>
</form>
);
}
export default UncontrolledForm;
State Management:
Controlled Components: State is managed by React.
Uncontrolled Components: State is managed by the DOM.
Form Element Values:
Controlled Components: Value is controlled via React state (value prop).
Uncontrolled Components: Value is accessed directly from the DOM using ref.
Public folder
Images are placed in public folder and referenced via relative paths
// Assume image is placed at public/images/logo.png
function Logo() {
return <img src="/images/logo.png" alt="Logo" />;
}
React Hooks
Lifecycle features for a functional component.
Initial Phase - when a component is being created
Mounting Phase - inserted into the DOM.
Updating Phase - when a component's state or props change, causing it to re-render.
Unmounting Phase - Phase-when a component is being removed from the DOM.
Lifecycle methods:
React lifecycle methods allow you to hook into different phases of a component's lifecycle.
Intial render
getDefaultProps()
getInitialState()
componentWillMount()
render()
componentDidMount()
State change
shouldComponentUpdate()
componentWillUpdate()
render()
componentDidUpdate()
Props change
componentWillReceiveProps()
shouldComponentUpdate()
componentWillUpdate()
render()
componentDidUpdate()
Unmount
componentWillUnmount()
Prop drilling
Prop drilling is a pattern in React where data is passed from a parent component to a deeply nested child component through intermediary components.
Hooks
Hooks—functions starting with use—can only be called at the top level of your components or your own Hooks.
useState()
The useState hook is used to manage state in functional components.
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
export default Counter;
useEffect
The useEffect hook in React is used to handle side effects in functional components.
import React, { useEffect } from 'react';
useEffect(() => {
// side effect code here
}, [dependencies]);
Dependency Array
No Dependency Array: The effect runs after every render.
Empty Dependency Array: The effect runs only once, after the initial render
Specific Dependencies: The effect runs only when one or more of the specified dependencies change.
useParams
It is used to extract parameters from the URL.
import { useParams } from 'react-router-dom';
function ProductDetail() {
const { id } = useParams(); // Extracts the `id` parameter from the URL
return <div>Product ID: {id}</div>;
}
useNavigate
It is used to programmatically navigate between routes. It replaces useHistory from earlier versions.
import { useNavigate } from 'react-router-dom';
function HomeButton() {
const navigate = useNavigate();
return (
<button onClick={() => navigate('/')}>
Go to Home
</button>
);
}
useRef
The useRef hook is used to create mutable references that persist across renders. It can be used to access DOM elements directly.
import React, { useRef } from 'react';
function FocusInput() {
const inputRef = useRef(null);
const focusInput = () => {
inputRef.current.focus();
};
return (
<div>
<input ref={inputRef} type="text" />
<button onClick={focusInput}>Focus Input</button>
</div>
);
}
export default FocusInput;
ReactDOM.render
The ReactDOM.render method is used to render a React element (or a component) into a DOM container.
import React from 'react';
import ReactDOM from 'react-dom';
import MyComponent from './MyComponent';
ReactDOM.render(<MyComponent />, document.getElementById('root'));
render()
In the context of React class components, the render() method is a lifecycle method that must be implemented. It describes what the UI should look like for the component.
import React from 'react';
class MyComponent extends React.Component {
render() {
return (
<div>
<h1>Hello, World!</h1>
</div>
);
}
}
export default MyComponent;
Normal DOM
It is a programming interface for web documents.
Direct manipulation of the DOM can be slow and expensive because it involves updating the entire structure of the web page.
Virtual DOM
It is a concept implemented by libraries like React, where a virtual representation of the real DOM is kept in memory and synced with the real DOM by a library such as ReactDOM. When the state of an application changes, the Virtual DOM is updated first, instead of the real DOM.
The virtual DOM employs a reconciliation algorithm to calculate the differences between the previous virtual DOM and the current virtual DOM, and then applies the necessary changes to the real DOM
Working of Virtual DOM:
1) When a component is first rendered, a virtual DOM tree is created based on the component's render output.
2) When the state of a component changes, a new virtual DOM tree is created.
3) The new virtual DOM tree is compared (or "diffed") with the previous virtual DOM tree to determine what has changed.
4) Only the parts of the DOM that have changed are updated in the real DOM. This process is called "reconciliation".
5) Changes are batched and applied in a single pass to minimize the number of updates to the real DOM, which improves performance
CSR
- A user clicks a link to visit a webpage.
- The browser sends an HTTP request to the server for the requested page.
- The server responds with a minimal HTML document, often including references to JavaScript files (like bundled JavaScript code) and CSS files. The HTML document typically contains a <div> element with an ID where the React app (or other JavaScript frameworks) will be rendered.
- Once the browser receives the HTML, it starts loading and executing the JavaScript files specified in the HTML. This file contains the code for rendering the user interface and handling user interactions.
Stay Connected!
If you enjoyed this post, don’t forget to follow me on social media for more updates and insights:
Twitter: madhavganesan
Instagram: madhavganesan
LinkedIn: madhavganesan
Top comments (5)
Great reads, thank you very much Madhav
Revision notes. Very well explained.
Perfectly Articulated!
Engaging content.
Thank you my friend
You really helped me get start easily with react
If you know anything about training and using llms locally then please share that too
Thx for your comment Shouryan✌️
Will post that very soon💯