JavaScript & React Complete Guide 2026 — From Basics to Pro
Master JavaScript and React in 2026 — variables, functions, ES6+, components, hooks, state management, and building production apps. The only guide you need.
Get more content like this on Telegram!
Daily AI tips, notes & resources — free
JavaScript & React Complete Guide 2026
JavaScript is the language of the web. React is how you build modern web UIs. Together, they unlock the frontend job market and power some of the world's most popular websites.
Part 1: Modern JavaScript (ES6+)
Variables and Scoping
// const — immutable reference (use by default)
const name = 'Alex';
const user = { age: 25 }; // object properties CAN change
user.age = 26; // valid
// let — mutable, block-scoped
let count = 0;
count = 1; // valid
// var — avoid in modern JS (function-scoped, hoisted)
// var x = 1; // don't use
Arrow Functions
// Traditional function
function add(a, b) { return a + b; }
// Arrow function
const add = (a, b) => a + b;
// Arrow function with body
const greet = (name) => {
const message = `Hello, ${name}!`;
return message;
};
// Arrow functions and 'this'
const timer = {
seconds: 0,
start() {
setInterval(() => {
this.seconds++; // 'this' refers to timer object
console.log(this.seconds);
}, 1000);
}
};
Destructuring
// Array destructuring
const [first, second, ...rest] = [1, 2, 3, 4, 5];
console.log(first, second, rest); // 1 2 [3, 4, 5]
// Object destructuring
const { name, age, city = 'Unknown' } = user;
// Function parameter destructuring
function processUser({ name, email, role = 'user' }) {
console.log(`${name} (${email}) — ${role}`);
}
// Nested destructuring
const { address: { city, country } } = user;
Spread & Rest
// Spread arrays
const fruits = ['apple', 'banana'];
const more = [...fruits, 'cherry', 'date'];
// Spread objects (shallow clone + extend)
const defaults = { theme: 'dark', lang: 'en', size: 'md' };
const userPrefs = { ...defaults, theme: 'light', size: 'lg' };
// Rest parameters
function sum(...numbers) {
return numbers.reduce((total, n) => total + n, 0);
}
console.log(sum(1, 2, 3, 4, 5)); // 15
Async/Await
// Modern async/await pattern
async function fetchUserPosts(userId) {
try {
const userRes = await fetch(`/api/users/${userId}`);
if (!userRes.ok) throw new Error(`HTTP ${userRes.status}`);
const user = await userRes.json();
const postsRes = await fetch(`/api/posts?userId=${userId}`);
const posts = await postsRes.json();
return { user, posts };
} catch (error) {
console.error('Fetch failed:', error.message);
throw error;
}
}
// Parallel fetching (faster)
async function fetchAll(userId) {
const [user, posts] = await Promise.all([
fetch(`/api/users/${userId}`).then(r => r.json()),
fetch(`/api/posts?userId=${userId}`).then(r => r.json()),
]);
return { user, posts };
}
Part 2: React Fundamentals
Components & JSX
// Functional component (modern React)
function PostCard({ title, excerpt, category, imageUrl, slug }) {
return (
<article className="card">
<img src={imageUrl} alt={title} loading="lazy" />
<div className="card-body">
<span className="badge">{category}</span>
<h2 className="card-title">{title}</h2>
<p className="card-excerpt">{excerpt}</p>
<a href={`/post/${slug}`} className="btn-primary">
Read More →
</a>
</div>
</article>
);
}
// List rendering
function PostGrid({ posts }) {
if (!posts?.length) return <EmptyState />;
return (
<div className="grid">
{posts.map((post) => (
<PostCard key={post.slug} {...post} />
))}
</div>
);
}
Core Hooks
import { useState, useEffect, useCallback, useMemo, useRef } from 'react';
// useState — local component state
function Counter() {
const [count, setCount] = useState(0);
const [name, setName] = useState('');
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(c => c + 1)}>+1</button>
<input value={name} onChange={e => setName(e.target.value)} />
</div>
);
}
// useEffect — side effects (data fetching, subscriptions)
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
let cancelled = false;
async function loadUser() {
try {
const res = await fetch(`/api/users/${userId}`);
const data = await res.json();
if (!cancelled) setUser(data);
} finally {
if (!cancelled) setLoading(false);
}
}
loadUser();
return () => { cancelled = true; }; // cleanup
}, [userId]); // re-run when userId changes
if (loading) return <Spinner />;
return <div>{user?.name}</div>;
}
// useCallback — memoize functions
function SearchBox({ onSearch }) {
const [query, setQuery] = useState('');
const handleSearch = useCallback(() => {
onSearch(query.trim());
}, [query, onSearch]);
return (
<div>
<input value={query} onChange={e => setQuery(e.target.value)} />
<button onClick={handleSearch}>Search</button>
</div>
);
}
// Custom Hook — reusable logic
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetch(url)
.then(r => r.json())
.then(setData)
.catch(setError)
.finally(() => setLoading(false));
}, [url]);
return { data, loading, error };
}
// Usage
function Posts() {
const { data, loading, error } = useFetch('/api/posts');
if (loading) return <Spinner />;
if (error) return <ErrorMessage error={error} />;
return <PostGrid posts={data.posts} />;
}
Part 3: Next.js in 2026
// app/posts/[slug]/page.tsx
import type { Metadata } from 'next';
interface Props { params: { slug: string } }
// Static params for SSG
export async function generateStaticParams() {
const posts = await fetch('https://api.aitechworlds.com/posts').then(r => r.json());
return posts.map((p: any) => ({ slug: p.slug }));
}
// Dynamic SEO metadata
export async function generateMetadata({ params }: Props): Promise<Metadata> {
const post = await fetch(`https://api.aitechworlds.com/posts/${params.slug}`).then(r => r.json());
return {
title: post.title,
description: post.excerpt,
openGraph: { images: [post.featuredImage] },
};
}
// Server component — no 'use client'
export default async function PostPage({ params }: Props) {
const post = await fetch(`https://api.aitechworlds.com/posts/${params.slug}`, {
next: { revalidate: 3600 }
}).then(r => r.json());
return (
<article>
<h1>{post.title}</h1>
<div dangerouslySetInnerHTML={{ __html: post.content }} />
</article>
);
}
Your React Learning Roadmap
| Week | Focus | Build |
|---|---|---|
| 1-2 | JS fundamentals | Calculator, to-do list |
| 3-4 | React basics | Counter, form validation |
| 5-6 | Hooks & state | Weather app |
| 7-8 | API integration | News aggregator |
| 9-10 | Next.js | Blog with SSG |
| 11-12 | Full project | Portfolio site |
JavaScript and React are the gateway to the modern web. Start with JS fundamentals, build real projects, and you'll be job-ready in 3-6 months of consistent effort.
Part 4: Advanced React Patterns
Once you're comfortable with basic hooks and components, these patterns separate junior developers from senior ones.
useContext — Avoiding Prop Drilling
When data needs to pass through many component layers, Context API saves you from passing props at every level.
// Create context
import { createContext, useContext, useState } from 'react';
interface User { name: string; role: string; }
const UserContext = createContext<User | null>(null);
// Provider wraps your app (or part of it)
export function UserProvider({ children }: { children: React.ReactNode }) {
const [user, setUser] = useState<User>({ name: 'Alex', role: 'admin' });
return (
<UserContext.Provider value={user}>
{children}
</UserContext.Provider>
);
}
// Any nested component can consume it
export function ProfileAvatar() {
const user = useContext(UserContext);
if (!user) return null;
return (
<div className="avatar">
<span>{user.name}</span>
<span className="badge">{user.role}</span>
</div>
);
}
Context is excellent for: authentication state, theme preferences, language settings, and other global app state.
useReducer — Complex State Logic
When useState becomes messy with multiple related state updates, useReducer brings clarity:
type Action =
| { type: 'INCREMENT' }
| { type: 'DECREMENT' }
| { type: 'RESET' }
| { type: 'SET'; payload: number };
function counterReducer(state: number, action: Action): number {
switch (action.type) {
case 'INCREMENT': return state + 1;
case 'DECREMENT': return Math.max(0, state - 1);
case 'RESET': return 0;
case 'SET': return action.payload;
default: return state;
}
}
function Counter() {
const [count, dispatch] = useReducer(counterReducer, 0);
return (
<div>
<span>{count}</span>
<button onClick={() => dispatch({ type: 'INCREMENT' })}>+</button>
<button onClick={() => dispatch({ type: 'DECREMENT' })}>-</button>
<button onClick={() => dispatch({ type: 'RESET' })}>Reset</button>
</div>
);
}
Performance Optimization
React re-renders components when state or props change. For complex UIs, uncontrolled re-renders cause performance issues.
import { useMemo, useCallback, memo } from 'react';
// memo — prevent re-render if props haven't changed
const ExpensiveComponent = memo(function ExpensiveComponent({ data }: { data: string[] }) {
return <ul>{data.map((item) => <li key={item}>{item}</li>)}</ul>;
});
function Parent() {
const [count, setCount] = useState(0);
const [items] = useState(['apple', 'banana', 'cherry']);
// useMemo — memoize expensive calculations
const sortedItems = useMemo(() => {
console.log('Sorting...'); // Only runs when items changes
return [...items].sort();
}, [items]);
// useCallback — memoize functions (prevents child re-renders)
const handleClick = useCallback(() => {
console.log('clicked');
}, []); // Empty deps = never changes
return (
<div>
<button onClick={() => setCount(c => c + 1)}>Count: {count}</button>
<ExpensiveComponent data={sortedItems} />
</div>
);
}
When to optimize: Measure first. Don't add useMemo and useCallback everywhere — they have overhead. Optimize when you observe actual slowness.
Part 5: State Management with Zustand
For applications where Context API becomes complex, Zustand is the modern alternative. It's simple, fast, and requires minimal boilerplate.
npm install zustand
import { create } from 'zustand';
interface CartStore {
items: string[];
addItem: (item: string) => void;
removeItem: (item: string) => void;
clearCart: () => void;
total: number;
}
const useCartStore = create<CartStore>((set, get) => ({
items: [],
total: 0,
addItem: (item) => set((state) => ({
items: [...state.items, item],
total: state.total + 1,
})),
removeItem: (item) => set((state) => ({
items: state.items.filter((i) => i !== item),
total: state.total - 1,
})),
clearCart: () => set({ items: [], total: 0 }),
}));
// Use in any component — no Provider needed
function CartBadge() {
const total = useCartStore((state) => state.total);
return <span className="badge">{total}</span>;
}
function AddToCartButton({ item }: { item: string }) {
const addItem = useCartStore((state) => state.addItem);
return <button onClick={() => addItem(item)}>Add to Cart</button>;
}
Zustand is simpler than Redux, lighter than Recoil, and more scalable than Context API for complex state.
Part 6: TypeScript with React
TypeScript is no longer optional for professional React development. It prevents entire categories of bugs and makes code significantly more maintainable.
// Typing component props
interface ButtonProps {
label: string;
onClick: () => void;
variant?: 'primary' | 'secondary' | 'danger';
disabled?: boolean;
children?: React.ReactNode;
}
function Button({ label, onClick, variant = 'primary', disabled = false }: ButtonProps) {
return (
<button
onClick={onClick}
disabled={disabled}
className={`btn btn-${variant}`}
>
{label}
</button>
);
}
// Typing state and events
function ContactForm() {
const [email, setEmail] = useState<string>('');
const [error, setError] = useState<string | null>(null);
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setEmail(e.target.value);
setError(null);
};
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
if (!email.includes('@')) {
setError('Please enter a valid email');
return;
}
// Submit logic
};
return (
<form onSubmit={handleSubmit}>
<input value={email} onChange={handleChange} type="email" />
{error && <span className="error">{error}</span>}
<button type="submit">Subscribe</button>
</form>
);
}
Key TypeScript patterns for React:
- Always type component props with an
interface - Type event handlers explicitly (
React.ChangeEvent<HTMLInputElement>) - Use generics for reusable components
- Avoid
any— useunknownand narrow it, or be specific
Part 7: Building a Real Project — Portfolio Site with Next.js
The best way to solidify React and Next.js knowledge is building something real. Here is a minimal, complete portfolio structure:
my-portfolio/
├── src/
│ ├── app/
│ │ ├── layout.tsx # Root layout (nav, footer)
│ │ ├── page.tsx # Home page
│ │ ├── about/page.tsx # About page
│ │ ├── projects/
│ │ │ ├── page.tsx # Projects list
│ │ │ └── [slug]/page.tsx # Project detail
│ │ └── contact/page.tsx # Contact form
│ ├── components/
│ │ ├── Navbar.tsx
│ │ ├── ProjectCard.tsx
│ │ └── Footer.tsx
│ ├── data/
│ │ └── projects.ts # Your projects data
│ └── types/
│ └── index.ts # TypeScript interfaces
├── public/ # Static assets
├── tailwind.config.ts
└── next.config.js
Projects data file:
// src/data/projects.ts
export interface Project {
slug: string;
title: string;
description: string;
technologies: string[];
githubUrl: string;
liveUrl?: string;
featuredImage: string;
}
export const PROJECTS: Project[] = [
{
slug: 'ai-chatbot',
title: 'AI Customer Support Chatbot',
description: 'A ChatGPT-powered chatbot that handles customer queries with 90% accuracy.',
technologies: ['Next.js', 'OpenAI API', 'TypeScript', 'Tailwind CSS'],
githubUrl: 'https://github.com/username/ai-chatbot',
liveUrl: 'https://chatbot-demo.vercel.app',
featuredImage: '/images/chatbot.png',
},
// Add more projects
];
This structure is clean, scalable, and something you can deploy to Vercel in minutes.
Common JavaScript & React Mistakes to Avoid
1. Mutating State Directly
// ❌ Wrong — mutating state directly
const [items, setItems] = useState([1, 2, 3]);
items.push(4); // React won't detect this change!
setItems(items); // Won't re-render
// ✅ Correct — create new array
setItems([...items, 4]);
setItems(prev => [...prev, 4]); // Use callback form for safety
2. Missing Dependency Arrays
// ❌ Runs on every render (no deps array)
useEffect(() => {
fetchData();
}); // Missing []
// ❌ Stale closure — data never updates
useEffect(() => {
fetchData(userId);
}, []); // userId not in deps
// ✅ Correct
useEffect(() => {
fetchData(userId);
}, [userId]); // Runs when userId changes
3. Using Index as Key
// ❌ Wrong — index as key breaks re-ordering
{items.map((item, index) => <Item key={index} data={item} />)}
// ✅ Correct — use stable unique ID
{items.map((item) => <Item key={item.id} data={item} />)}
The JavaScript & React Job Market in 2026
React remains dominant in the frontend job market:
- React job postings outnumber Vue 3:1 and Angular 2:1 in most markets
- Next.js is now the default React framework at most companies
- TypeScript is required or strongly preferred in 85%+ of React positions
- Salary range: $70K–$160K for frontend developers, depending on experience and location
The combination of React + TypeScript + Next.js + Tailwind CSS is the modern standard stack — and what you should be building projects with.
Your immediate next steps:
- Read the official React documentation — it was rewritten in 2023 and is excellent
- Build the portfolio project above — real code beats tutorials
- Read our Web Development Roadmap 2026 for the full frontend learning path
- Version control all your projects — see our Git and GitHub guide
Get JavaScript and React cheat sheets free on our Telegram channel!
Frequently Asked Questions
AiTechWorlds Team
✓ Verified WriterThe AiTechWorlds team is passionate about AI, technology, and education. We create high-quality, research-backed content to help you learn, grow, and succeed in the modern digital world.
Related Articles
Python OOP Complete Guide 2026 — Object-Oriented Programming Mastery
Master Python object-oriented programming from basics to advanced. Classes, inheritance, polymorphism, SOLID principles, dataclasses — everything you need to write professional Python.
Python Error Handling & Debugging 2026 — Write Bulletproof Code
Master Python error handling and debugging techniques. Learn try/except, custom exceptions, logging, pdb, and professional debugging strategies to write robust Python code.
Python Decorators and Generators — Advanced Python Made Simple 2026
Master Python decorators and generators — two of Python's most powerful features. Clear explanations, real-world examples, and practical patterns you'll actually use.
Python Testing with pytest 2026 — From Beginner to Pro Guide
Learn Python testing with pytest from scratch. Write unit tests, integration tests, use fixtures and mocks, measure coverage — everything a professional Python developer needs.