Getting Started
npx create-react-app your-app-name
npm start
Components
Create a new file , here is an example of a sample component .
JSX
React.createElement()calls.props
state
- Constructor
- static getDerivedStateFromProps
- render
- componentDidMount
useState) via an onChangehandler. useRef hook to fetch values when needed.Hooks
Hooks must only be called at the top level of a component or custom hook (never inside loops, conditions, or nested functions).
useEffect mimic lifecycle phases?An empty dependency array
[] mimics componentDidMount by running once. [dependency] mimics componentDidUpdate. componentWillUnmount to clear memoryuseReducer over useState?useReducer is preferred when managing complex state trees with deeply nested objects, or when the next state depends heavily on the previous state via specific action dispatches.useEffect and useLayoutEffect.useEffect triggers asynchronously after the browser paints the screen pixels, preventing blocking. useLayoutEffect fires synchronously after all DOM alterations but before the browser paints, which prevents layout shifts during explicit DOM measurementsReact.memo, useMemo, and useCallback differ?React.memo is a Higher-Order Component that skips re-rendering a component if its primitive props do not change. useMemo caches the calculated result value of an intensive function. useCallback caches the function instance itselfto maintain stable reference equality across renders.Routing
The most common library: react-router-dom
1. BrowserRouter — wraps your app and enables URL-based routing
2. Routes + Route — define which component renders at which path
3. Link — navigate without a full page reload (replaces <a href>)
4. useNavigate — programmatic navigation (e.g., after a form submit)
import { useNavigate } from 'react-router-dom';
const navigate = useNavigate();
navigate('/dashboard');
5. useParams — read URL parameters
import { useParams } from 'react-router-dom';
// Route: /users/:id
const { id } = useParams(); // e.g., "42" from /users/42
useLocation
A hook that returns the current URL location object. You're using just the pathname from it:
useParams
Reads dynamic segments from the URL. You define a dynamic segment with : in the route:
<Route path="/employee/:id" element={<Employee />} />
Then inside Employee:
const { id } = useParams();
// URL /employee/42 → id = "42"
// URL /employee/99 → id = "99"
Useful when you want one route to handle many different items — like a profile page, product detail, etc.
useNavigate
Gives you a function to navigate programmatically — i.e., from code rather than a user clicking a <Link>.
const navigate = useNavigate();
// go to a route
navigate('/address');
// go back (like browser back button)
navigate(-1);
// replace current history entry (no back button entry added)
navigate('/home', { replace: true });
ES6
Refer file
ES6+ feature used
1. ES6 Modules — import / export
import { useState } from 'react';
import AddressForm from './components/AddressForm';
export default function App() { ... }
Before ES6, scripts were loaded via <script> tags with no module system. ES6 introduced import/export to split code into reusable files.
- import { useState } — named import, pulls a specific exported value by name
- import AddressForm — default import, pulls whatever the file exported as default
- export default function App — marks App as the default export of this file
2. const and let
const [addresses, setAddresses] = useState([]);
const handleSave = (address) => { ... };
const handleDelete = (id) => { ... };
ES6 replaced var with const and let.
- const — value cannot be reassigned (the variable binding is fixed). Used for everything here because none of these variables are reassigned — setAddresses updates React state, not the variable itself.
- let — block-scoped and can be reassigned. Not used here but preferred over var when reassignment is needed.
- var — function-scoped, hoisted, prone to bugs. Avoided in modern JS.
3. Arrow Functions
const handleSave = (address) => {
setAddresses((prev) => [...prev, address]);
};
const handleDelete = (id) => {
setAddresses((prev) => prev.filter((a) => a.id !== id));
};
Arrow functions are a shorter syntax for functions. Three things make them different from regular function:
- Shorter syntax — no function keyword needed
- Implicit return — if the body is a single expression with no {}, it returns automatically:
(a) => a.id !== id // same as: function(a) { return a.id !== id; }
- Lexical this — they don't have their own this, they inherit it from the surrounding scope. Important in class components, less relevant in functional components.
4. Array Destructuring
const [addresses, setAddresses] = useState([]);
Destructuring unpacks values from an array into variables. useState returns an array of two items — the state value and the setter. Without destructuring you'd write:
const state = useState([]);
const addresses = state[0];
const setAddresses = state[1];
Destructuring does it in one line.
5. Spread Operator ...
setAddresses((prev) => [...prev, address]);
...prev spreads all existing items from the prev array into a new array, then appends address at the end. This creates a new array rather than mutating the existing one — which is required in React for
state updates.
Without spread:
prev.push(address); // mutates — bad in React
return prev;
With spread:
return [...prev, address]; // new array — correct
6. Array .filter() with Arrow Function
setAddresses((prev) => prev.filter((a) => a.id !== id));
.filter() is not strictly ES6 (it's ES5), but the arrow function passed to it is ES6. It returns a new array containing only items where the condition is true — here, every address except the one being
deleted. Again, creates a new array rather than mutating.
7. Template Literals (not in App.jsx but used throughout the project)
Just worth knowing — backtick strings with ${} interpolation:
`Hello ${name}` // instead of "Hello " + name
Summary table:
┌────────────────────────────┬─────────────────────────────────────┐
│ Feature │ Where in App.jsx │
├────────────────────────────┼─────────────────────────────────────┤
│ import / export default │ top and bottom of file │
├────────────────────────────┼─────────────────────────────────────┤
│ const │ every variable declaration │
├────────────────────────────┼─────────────────────────────────────┤
│ Arrow functions => │ handleSave, handleDelete, callbacks │
├────────────────────────────┼─────────────────────────────────────┤
│ Array destructuring [a, b] │ const [addresses, setAddresses] │
├────────────────────────────┼─────────────────────────────────────┤
│ Spread operator ... │ [...prev, address] │
├────────────────────────────┼─────────────────────────────────────┤
│ .filter() with arrow │ prev.filter((a) => ...) │
└────────────────────────────┴─────────────────────────────────────┘
Yes, here are the remaining important ES6+ features not in your App.jsx:
1. Object Destructuring
// Instead of:
const name = person.name;
const age = person.age;
// ES6:
const { name, age } = person;
// With renaming:
const { name: fullName } = person; // fullName = person.name
// With defaults:
const { city = 'Unknown' } = person;
You already use this in your project — useLocation:
const { pathname } = useLocation();
2. Default Parameters
function greet(name = 'Guest') {
return `Hello, ${name}`;
}
greet(); // "Hello, Guest"
greet('Zainab'); // "Hello, Zainab"
Before ES6 you had to write name = name || 'Guest' inside the function body.
3. Template Literals
const name = 'Zainab';
const age = 25;
// Old way:
"Hello " + name + ", you are " + age + " years old."
// ES6:
`Hello ${name}, you are ${age} years old.`
// Multi-line (no \n needed):
const html = `
<div>
<p>${name}</p>
</div>
`;
4. Shorthand Object Properties
const name = 'Alice';
const age = 30;
// Old:
const person = { name: name, age: age };
// ES6 — when key and variable name are the same:
const person = { name, age };
You use this in your project:
onSave({ ...form, id: Date.now() })
// form already has name, city etc — spread + add id
5. Computed Property Names
const field = 'city';
const value = 'Mumbai';
// Old — couldn't use variables as keys directly:
const obj = {};
obj[field] = value;
// ES6:
const obj = { [field]: value }; // { city: 'Mumbai' }
You use this in your project for form state:
const { name, value } = e.target;
setForm((prev) => ({ ...prev, [name]: value }));
// ^^^^^^ computed key
6. Classes
class Animal {
constructor(name) {
this.name = name;
}
speak() {
return `${this.name} makes a noise.`;
}
}
class Dog extends Animal {
speak() {
return `${this.name} barks.`;
}
}
const d = new Dog('Rex');
d.speak(); // "Rex barks."
Less common in modern React (functional components replaced class components) but still used in backend Node.js code and libraries.
7. Promises
fetch('https://api.example.com/data')
.then((res) => res.json())
.then((data) => console.log(data))
.catch((err) => console.error(err));
You use this heavily in your project for API calls. A Promise represents a value that will be available in the future — either resolved (success) or rejected (error).
8. Async / Await (ES2017, built on Promises)
// Same fetch, but reads like synchronous code:
async function loadCountries() {
try {
const res = await fetch('https://countriesnow.space/api/v0.1/countries');
const json = await res.json();
setCountries(json.data.map((c) => c.country).sort());
} catch (err) {
setError('Failed to load countries.');
}
}
await pauses execution until the Promise resolves. Must be inside an async function. Cleaner than chained .then() for complex logic.
9. Optional Chaining ?. (ES2020)
const city = user?.address?.city;
// If user or address is null/undefined, returns undefined instead of throwing
Without it:
const city = user && user.address && user.address.city;
10. Nullish Coalescing ?? (ES2020)
const name = user.name ?? 'Anonymous';
// Returns right side only if left side is null or undefined
Different from || which also triggers on 0, '', false:
const count = 0 || 10; // 10 ← probably not what you want
const count = 0 ?? 10; // 0 ← correct
11. for...of loop
const cities = ['Mumbai', 'Delhi', 'Chennai'];
for (const city of cities) {
console.log(city);
}
Cleaner than a for loop with index. Works on arrays, strings, Maps, Sets.
12. Map and Set
// Set — unique values only
const unique = new Set([1, 2, 2, 3, 3]); // {1, 2, 3}
// Map — key-value pairs, any type as key
const map = new Map();
map.set('name', 'Alice');
map.get('name'); // 'Alice'
Quick reference:
┌───────────────────────┬────────────────────────────────────┐
│ Feature │ Use case │
├───────────────────────┼────────────────────────────────────┤
│ Object destructuring │ Unpack object properties │
├───────────────────────┼────────────────────────────────────┤
│ Default parameters │ Fallback values in functions │
├───────────────────────┼────────────────────────────────────┤
│ Template literals │ String interpolation, multiline │
├───────────────────────┼────────────────────────────────────┤
│ Shorthand properties │ { name } instead of { name: name } │
├───────────────────────┼────────────────────────────────────┤
│ Computed keys │ { [fieldName]: value } │
├───────────────────────┼────────────────────────────────────┤
│ Classes │ OOP, used in older React / Node │
├───────────────────────┼────────────────────────────────────┤
│ Promises .then() │ Async API calls │
├───────────────────────┼────────────────────────────────────┤
│ Async/Await │ Cleaner async code │
├───────────────────────┼────────────────────────────────────┤
│ Optional chaining ?. │ Safe property access │
├───────────────────────┼────────────────────────────────────┤
│ Nullish coalescing ?? │ Null-safe defaults │
├───────────────────────┼────────────────────────────────────┤
│ for...of │ Clean iteration │
├───────────────────────┼────────────────────────────────────┤
│ Map / Set │ Unique collections, typed maps │
└───────────────────────┴────────────────────────────────────┘