JavaScript VS React:
React's Other Features:
Note:
Library:
createRoot()
.Frameworks:
create-react-app:
In your terminal, execute the following command:
npx create-react-app [app-name]
npx create-react-app my-app --template [tempname]
Eg:
npx create-react-app my-app --template typescript
create-react-app:
my-app
├── README.md
├── node_modules
├── package.json
├── .gitignore
├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── robots.txt
└── src
├── App.css
├── App.js
├── App.test.js
├── index.css
├── index.js
├── logo.svg
├── serviceWorker.js
└── setupTests.js
// App.jsx
import React from "react";
import './App.scss';
const App = () => {
return (
<div className="app">
Hello World
</div>
);
};
export default App;
// index.js
import React from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';
const rootElement = document.getElementById('root');
const root = createRoot(rootElement);
root.render(<App />);
// index.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>React App</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
// App.jsx
import React from "react";
import './App.scss';
const App = () => {
return (
<div className="app">
Hello World
</div>
);
};
export default App;
// index.js
import React from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';
const rootElement = document.getElementById('root');
const root = createRoot(rootElement);
root.render(<App />);
// index.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>React App</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
create-react-app:
App.js:
it has the React component which needs to be shown on the UI,index.html:
it's the UI page which appears on the browser,index.js:
it's the page that adds the the React component (<App/>
) to the current UI, for that, it has 2 steps:React Functional Component (RFC):
function DivContainer() {
return (
<div>Hello There</div>
);
}
function MyButton() {
return (
<button>I'm a button</button>
);
}
function TwoHTMLs() {
return (
// Error
<div>Hello There</div>
<button>I'm a button</button>
);
}
function OneHTML() {
return (
// No Error
<div>Hello There
<button>I'm a button</button>
</div>
);
}
React Functional Component (RFC):
function DivContainer() {
const randomNumber = Math.round(Math.random()*100).toFixed(2)
if (randomNumber > 20) {
console.log("Greater")
} else {
console.log("Lesser")
}
return (
<div>Hello There</div>
);
}
JSX
// Rendering JS in return along with HTML
// use curly braces {} for adding JS in
// HTML (JSX)
function RandomNumberGenerator() {
const randomNumber = Math.random()*100)
return (
<div>Random Number: {randomNumber}</div>
);
}
// Conditional Rendering
function ConditionalMessage() {
const randomNumber = Math.random()*100)
return (
<div>
{
randomNumber > 20
? <div>Random Number: {randomNumber}</div>
: <div>Sorry, get a number!</div>
}
</div>
);
}
JSX
// Conditional Rendering
function RandomNumberGenerator() {
const randomNumber = Math.random()*100)
const isRandomNumberGreater = randomNumber > 20
return (
<div className="random">
Random Number Generator
{
isRandomNumberGreater &&
<div className="number">
Random Number: {randomNumber}
</div>
}
</div>
);
}
State in React Component:
import { useState } from "react";
// Conditional Rendering
function RandomNumberGenerator() {
const [count, setCount] = useState(0)
return (
<div className="wrapper">
<button onClick={() => setCount(count + 1)}>
+
</button>
<div>Count: {count}</div>
<button onClick={() => setCount(count - 1)}>
-
</button>
</div>
);
}
useState Hook:
import { useState } from "react";
// Conditional Rendering
function RandomNumberGenerator() {
const [count, setCount] = useState(0)
return (
<div className="wrapper">
<button onClick={() => setCount(count + 1)}>
+
</button>
<div>Count: {count}</div>
<button onClick={() => setCount(count - 1)}>
-
</button>
</div>
);
}
useState Hook:
import { useState } from "react";
// Conditional Rendering
function RandomNumberGenerator() {
const [count, setCount] = useState(0)
const handlePlusClick = () => {
const newCount = count + 1;
setCount(newCount)
}
const handleMinusClick = () => {
const newCount = count - 1;
setCount(newCount)
}
return (
<div className="wrapper">
<button onClick={handlePlusClick}>
+
</button>
<div>Count: {count}</div>
<button onClick={handleMinusClick}>
-
</button>
</div>
);
}
useState Hook:
import { useState } from "react";
// Conditional Rendering
function RandomNumberGenerator() {
const [count, setCount] = useState(0)
const handlePlusClick = () => {
setCount(currentCount => { return currentCount + 1 })
}
const handleMinusClick = () => {
setCount(currentCount => { return currentCount - 1 })
}
return (
<div className="wrapper">
<button onClick={handlePlusClick}>
+
</button>
<div>Count: {count}</div>
<button onClick={handleMinusClick}>
-
</button>
</div>
);
}
Events in React
- onClick,
- onChange,
- onBlur,
- onLoad,
- onKeyUp,
- onKeyDown,
- onMouseDown,
- onMouseUp,
- onMouseLeave,
- onCopy,
- onCut,
- onPaste,
- onScroll
import { useState } from "react";
// Conditional Rendering
function RandomNumberGenerator() {
const [count, setCount] = useState(0)
return (
<div
onClick={e => console.log('onClick')}
onMouseEnter={e => console.log('onMouseEnter')}
onMouseOver={e => console.log('onMouseOver')}
onMouseDown={e => console.log('onMouseDown')}
onMouseUp={e => console.log('onMouseUp')}
onMouseLeave={e => console.log('onMouseLeave')}
>
<input
onChange={e => console.log('onChange')}
onFocus={e => console.log('onFocus')}
onBlur={e => console.log('onBlur')}
/>
</div>
);
}
Events in React
- onClick,
- onChange,
- onBlur,
- onLoad,
- onKeyUp,
- onKeyDown,
- onMouseLeave,
- onCopy,
- onCut,
- onPaste
import { useState } from "react";
function InputComponent() {
const [inputValue, setInputValue] = useState('')
const [inputFocus, setInputFocus] = useState(false)
const handleInputChange = (e) => {
setInputValue(e.target.value)
}
const handleInputFocus = (e) => {
setInputFocus(true)
}
return (
<div>
<input
className={`input ${inputFocus && "focus"}`}
onChange={handleInputChange}
value={inputValue}
onFocus={handleInputFocus}
placeholder={"Enter your name"}
type="text"
/>
</div>
);
}
/* App.css */
.focus {
outline: orange dashed 2px;
}
Events in React
import { useState } from "react";
function InputComponent() {
const [inputValue, setInputValue] = useState('')
const [inputFocus, setInputFocus] = useState(false)
const handleInputChange = (e) => {
setInputValue(e.target.value)
}
return (
<div>
<input
onChange={handleInputValue}
value={input}
placeholder={"Enter your name"}
type="text"
style={{
color: inputValue.length > 4 ? "yellow" : "black",
}}
/>
</div>
);
}
UI Updates in React:
import { useState } from "react";
function InputComponent() {
const [inputValue, setInputValue] = useState('')
const [inputFocus, setInputFocus] = useState(false)
const handleInputChange = (e) => {
setInputValue(e.target.value)
}
console.log("1", inputValue)
return (
<div>
{console.log("2", inputValue)}
<input
onChange={handleInputValue}
value={input}
placeholder={"Enter your name"}
type="text"
style={{
color: inputValue.length > 4 ? "yellow" : "black",
}}
/>
</div>
);
}
Deep Dive React Component Update:
When you open a URL, all the UI elements (HTML elements) are assembled and a DOM Tree is created,
Mounting: Addition of your React component's HTML to the DOM Tree is called Mounting,
When you refresh the page, the existing UI is removed, the entire DOM is dumped, and then again a new one is created,
Unmounting: Removal of your React component's HTML from the DOM Tree is called Unmounting,
Re-rendering: It's a React's special implementation.
import { useState } from "react";
function InputComponent() {
const [inputValue, setInputValue] = useState('')
const [inputFocus, setInputFocus] = useState(false)
const handleInputChange = (e) => {
setInputValue(e.target.value)
}
return (
<div>
<input
onChange={handleInputValue}
value={input}
placeholder={"Enter your name"}
type="text"
style={{
color: inputValue.length > 4 ? "yellow" : "black",
}}
/>
</div>
);
}
Deep Dive React Component Update:
Re-rendering:
import { useState } from "react";
function InputComponent() {
const [inputValue, setInputValue] = useState('')
const [inputFocus, setInputFocus] = useState(false)
const handleInputChange = (e) => {
setInputValue(e.target.value)
}
return (
<div>
<input
onChange={handleInputValue}
value={input}
placeholder={"Enter your name"}
type="text"
style={{
color: inputValue.length > 4 ? "yellow" : "black",
}}
/>
</div>
);
}
Deep Dive React Component Update:
Re-rendering:
import { useState } from "react";
function InputComponent() {
const [inputValue, setInputValue] = useState('')
const handleInputChange = (e) => {
setInputValue(e.target.value)
}
return (
<div>
<input
onChange={handleInputValue}
value={input}
placeholder={"Enter your name"}
type="text"
style={{
color: inputValue.length > 4 ? "yellow" : "black",
}}
/>
</div>
);
}
Deep Dive React Component Update:
Re-rendering:
import { useState } from "react";
function InputComponent() {
const [inputValue, setInputValue] = useState('')
const [inputFocus, setInputFocus] = useState(false)
const handleInputChange = (e) => {
setInputValue(e.target.value);
setInputFocus(true)
}
return (
<div>
<input
onChange={handleInputValue}
value={input}
placeholder={"Enter your name"}
type="text"
style={{
color: inputValue.length > 4 ? "yellow" : "black",
backgroundColor: inputFocus ? "green" : "white"
}}
/>
</div>
);
}
Deep Dive React Component Update:
Re-rendering:
import { useState } from "react";
function InputComponent() {
const [inputValue, setInputValue] = useState('')
const [inputFocus, setInputFocus] = useState(false)
const handleInputChange = (e) => {
setInputValue(e.target.value);
setInputFocus(true) // this works only once
console.log(e.target.value, inputValue, inputFocus)
}
function handleFocusToggle() {
setInputFocus(!inputFocus)
}
return (
<div>
<input
onChange={handleInputValue}
value={input}
placeholder={"Enter your name"}
type="text"
style={{
color: inputValue.length > 4 ? "yellow" : "black",
backgroundColor: inputFocus ? "green" : "white"
}}
/>
<button onClick={handleFocusToggle}>Toggle</button>
</div>
);
}
Variables in a React Component:
- created using useState,
- its value persists across re-renders,
- changes to this variable cause re-render
Local Variable:
- normal JS variable created inside React Component,
- value is lost in component re-render,
- every re-render creates a new variable,
- changes to this variable doesn't cause re-render
Global Variable:
- created outside React Component,
- its value persists across re-renders,
- changes to this variable don't cause re-render
import { useState } from "react";
let globalCount = 100;
function InputComponent() {
const [inputValue, setInputValue] = useState('')
const [inputFocus, setInputFocus] = useState(false)
let localVariable = 400;
const handleInputChange = (e) => {
setInputValue(e.target.value);
}
function handleFocusToggle() {
setInputFocus(!inputFocus)
}
return (
<div>
<input
onChange={handleInputValue}
value={input}
style={{
color: inputValue.length > 4 ? "yellow" : "black",
}}
/>
<button onClick={handleFocusToggle}>Toggle</button>
</div>
);
}
useRef Hook:
document.getElementById
and other DOM methods,current
object of ref variable (ref.current)
import { useState, useRef } from "react";
function InputComponent() {
// const [inputValue, setInputValue] = useState('')
const inputRef = useRef('')
const handleInputChange = (e) => {
inputRef.current.value = e.target.value);
}
return (
<div>
<input
ref={inputRef}
onChange={handleInputValue}
// value={input}
style={{
color: inputValue.length > 4 ? "yellow" : "black",
}}
/>
</div>
);
}
useRef Hook:
import { useState, useRef } from "react";
function InputComponent() {
const [toggle, setToggle] = useState(false)
const inputRef = useRef('')
const handleInputChange = (e) => {
inputRef.current.value = e.target.value);
console.log(inputRef.current.value)
}
console.log(inputRef.current.value)
return (
<div>
<input
ref={inputRef}
onChange={(e) => {
handleInputValue(e);
setToggle(!toggle)
}}
// value={input}
style={{
color: inputValue.length > 4 ? "yellow" : "black",
}}
/>
</div>
);
}
Nested React Components:
"return"
statement of another React component (parent),import { useState, useRef } from "react";
function Parent() {
const [toggle, setToggle] = useState(false)
return (
<div>
<ChildComponent/>
</div>
);
}
const ChildComponent = () => {
return (
<div>
I'm a Child Comp
</div>
)
}
Passing Data from Parent To Child React Comp:
import { useState, useRef } from "react";
function Parent() {
const [toggle, setToggle] = useState(false)
const address = {
line1: "245, C sector",
line2: "Indrapuri",
city: "Bhopal"
}
return (
<div>
<ChildComponent name={"Yash"} age={30} add={address}/>
</div>
);
}
const ChildComponent = (propObject) => {
const { name, add } = propObject;
return (
<div>
<div>{name}</div>
<div>{propObject.age}</div>
</div>
)
}
Passing Props Deep Down:
import { useState, useRef } from "react";
function Parent() {
const [value, setValue] = useState(100)
return (
<div>
<Comp1 prop1={value}/>
</div>
);
}
const Comp1 = (propObject) => {
return (
<div>
<Comp3 prop3={propObject.prop1}/>
</div>
)
}
const Comp3 = (propObject) => {
return (
<div>
{propObject.prop3}
</div>
)
}
Passing Props Deep Down:
import { useState, useContext, createContext } from "react";
// Step 1 - Create Context
const PropContext = createContext();
function Parent() {
const [value, setValue] = useState(100)
// Step 2 - Wrap ypur component in provider
return (
<PropContext.Provider value={{value}}>
<Comp1 />
</PropContext.Provider>
);
}
const Comp1 = () => {
return (
<div>
<Comp3 />
</div>
)
}
const Comp3 = () => {
// Step 3 - Extract data through useContext
const { value } = useContext(PropContext)
return (
<div>
{value}
</div>
)
}
With multi-level nested Components:
import { useState, useContext, createContext } from "react";
// Step 1 - Create Context
const PropContext = createContext();
function Parent() {
const [value, setValue] = useState(100)
// Step 2 - Wrap ypur component in provider
return (
<PropContext.Provider value={{value}}>
<Comp1 />
</PropContext.Provider>
);
}
const Comp1 = () => {
return (
<div>
<Comp3 />
</div>
)
}
const Comp3 = () => {
// Step 3 - Extract data through useContext
const { value } = useContext(PropContext)
return (
<div>
{value}
</div>
)
}
A React Component re-renders due to exactly 3 reasons:
import { useState, useContext, createContext } from "react";
// Step 1 - Create Context
const PropContext = createContext();
function Parent() {
const [value, setValue] = useState(100)
// Step 2 - Wrap ypur component in provider
return (
<PropContext.Provider value={{value}}>
<Comp1 />
</PropContext.Provider>
);
}
const Comp1 = () => {
return (
<div>
<Comp3 />
</div>
)
}
const Comp3 = () => {
// Step 3 - Extract data through useContext
const { value } = useContext(PropContext)
return (
<div>
{value}
</div>
)
}
useEffect Hook:
import { useState, useEffect } from "react";
function App() {
const [value, setValue] = useState(100)
useEffect(() => {
console.log('effect called')
// this effect runs only on first
// render of the component (mounting)
}, [])
return (
<div className="app">
Show value: {value}
<div/>
);
}
export default App;
3 cases of useEffect Hook:
import { useState, useEffect } from "react";
function App() {
const [value, setValue] = useState(100)
useEffect(() => {
console.log('effect called on every render')
// this effect runs on mount and then every
// re-render of the component
})
useEffect(() => {
console.log('effect called on mount only')
// this effect runs only on first
// render of the component (mounting)
}, [])
useEffect(() => {
console.log('effect called on every render')
// this effect runs "value" variable
// changes on call "setValue"
}, [value])
return (
<div className="app">
Show value: {value}
<input
onChange={(e) => setValue(e.target.value)}
value={value}
/>
<div/>
);
}
export default App;
import { useState, useEffect } from "react";
let globalCount = 20;
function App() {
const [value, setValue] = useState(100)
let localCount = 50;
const newRef = useRef(0)
useEffect(() => {
console.log('effect runs on mount')
// then it never runs, because
// changes to localCount or globalCount or newRef
// variable are not tracked
}, [ localCount, globalCount, newRef.current ])
useEffect(() => {
console.log('effect runs on mount')
// then it runs only when
// "value" state changes
}, [value])
return (
<div className="app">
Show value: {value}
<input
onChange={(e) => setValue(e.target.value)}
value={value}
/>
<div/>
);
}
export default App;
useEffect Hook:
import { useState, useEffect } from "react";
let globalCount = 20;
function App() {
const [value, setValue] = useState(100);
useEffect(() => {
setValue(value + 1)
}, [value])
useEffect(() => {
setValue(value + 1)
})
return (
<div className="app">
Show value: {value}
<input
onChange={(e) => setValue(e.target.value)}
value={value}
/>
<div/>
);
}
export default App;
useEffect with 2nd arg non-empty array:
useEffect with return:
removeEventListeners
etcimport { useState, useEffect } from "react";
let globalCount = 20;
function App() {
const [value, setValue] = useState(100)
useEffect(() => {
console.log('effect runs on mount')
// then it runs only when
// "value" state changes
return () => { console.log("Hi") }
}, [value])
return (
<div className="app">
Show value: {value}
<input
onChange={(e) => setValue(e.target.value)}
value={value}
/>
<div/>
);
}
export default App;
useEffect with return:
import { useState, useEffect } from "react";
let globalCount = 20;
function App() {
const [value, setValue] = useState(100)
useEffect(() => {
// this won't cause an infinite re-render
// because the setValue is called when
// the component is being unmount before
// a re-render
return () => { setValue(value + 1) }
}, [value])
return (
<div className="app">
Show value: {value}
<input
onChange={(e) => setValue(e.target.value)}
value={value}
/>
<div/>
);
}
export default App;
calling APIs in useEffect:
import { useState, useEffect } from "react";
function App() {
const [userData, setUserData] = useState([])
const API = "https://jsonplaceholder.typicode.com/users"
useEffect(() => {
async function callUserAPI() {
const getUserData = await fetch(API)
const userDataJSON = await getUserData.json()
console.log(userDataJSON)
setUserData(userDataJSON)
}
callUserAPI()
}, [])
return (
<div className="app">
{userData.length === 0
? <Loader/>
: userData.map(user => <User user={user}/>)
}
<div/>
);
}
export default App;
Routing in React
import { useState, useEffect } from "react";
function App() {
const [userData, setUserData] = useState([])
const API = "https://jsonplaceholder.typicode.com/users"
useEffect(() => {
async function callUserAPI() {
const getUserData = await fetch(API)
const userDataJSON = await getUserData.json()
console.log(userDataJSON)
setUserData(userDataJSON)
}
callUserAPI()
}, [])
return (
<div className="app">
{userData.length === 0
? <Loader/>
: userData.map(user => <User user={user}/>)
}
<div/>
);
}
export default App;