• Follow Us On :
ReactJS Tutorial

What is Hadoop Cluster: Complete Guide to Distributed Big Data Processing

Welcome to this comprehensive ReactJS tutorial designed to take you from complete beginner to confident React developer. This ReactJS tutorial covers everything you need to build modern, interactive web applications using React—the most popular JavaScript library for building user interfaces. Whether you’re starting your coding journey or transitioning from other frameworks, this ReactJS tutorial provides clear explanations, practical examples, and hands-on exercises that build real-world development skills.

Throughout this ReactJS tutorial, you’ll learn fundamental concepts including components, JSX, props, state, hooks, and event handling before progressing to advanced topics like performance optimization, custom hooks, context API, and modern React patterns. Each section includes code examples you can run and modify, reinforcing learning through practice. By the end of this ReactJS tutorial, you’ll have built multiple projects demonstrating mastery of React development principles and best practices.

This ReactJS tutorial reflects current React best practices for 2026, focusing on modern functional components and hooks rather than outdated class component patterns. You’ll learn the same techniques used by professional developers at leading technology companies, preparing you for real-world React development or job opportunities in the rapidly growing React ecosystem.

Getting Started with React

What is React and Why Learn It?

Before diving into this ReactJS tutorial, understanding what makes React special helps appreciate why millions of developers choose it.

React is:

  • A JavaScript library for building user interfaces
  • Developed and maintained by Facebook (Meta)
  • Component-based, promoting code reusability
  • Declarative, making code predictable and easier to debug
  • Focused on the view layer (the “V” in MVC)

Why Learn React:

Industry Demand: React developers are highly sought-after with excellent salaries. Most modern web applications use React or similar component-based frameworks.

Rich Ecosystem: Thousands of libraries, tools, and resources support React development. From routing (React Router) to state management (Redux, Zustand) to UI components (Material-UI, Chakra), the ecosystem provides solutions for every need.

React Native: After learning React for web, you can build mobile apps using React Native with the same concepts and similar code.

Strong Community: Millions of developers worldwide use React, providing extensive learning resources, tutorials, open-source projects, and community support.

Modern Development: React embraces modern JavaScript features and best practices, teaching you skills applicable beyond React itself.

Setting Up Your Development Environment

This ReactJS tutorial begins with proper environment setup.

Prerequisites:

  • Basic HTML, CSS, and JavaScript knowledge
  • Computer with Windows, Mac, or Linux
  • Text editor (VS Code recommended)
  • Node.js and npm installed

Step 1: Install Node.js and npm

Visit nodejs.org and download the LTS version. Node.js includes npm (Node Package Manager) which manages React and other JavaScript packages.

Verify installation by opening terminal/command prompt:

bash
node --version
npm --version

Step 2: Install VS Code (Recommended Editor)

Download from code.visualstudio.com

Recommended VS Code Extensions:

  • ES7+ React/Redux/React-Native snippets
  • Prettier – Code formatter
  • ESLint
  • Auto Rename Tag
  • Bracket Pair Colorizer

Step 3: Create Your First React App

React provides Create React App, a tool that sets up everything you need:

bash
npx create-react-app my-first-app
cd my-first-app
npm start

This creates a new React project and starts a development server. Your browser opens automatically showing the default React app at http://localhost:3000.

Project Structure:

my-first-app/
├── node_modules/      # Dependencies
├── public/           # Static files
│   └── index.html    # HTML template
├── src/              # React code
│   ├── App.js        # Main component
│   ├── App.css       # Styles
│   └── index.js      # Entry point
├── package.json      # Project configuration
└── README.md         # Documentation

Alternative: Vite (Faster Development)

For faster development experience:

bash
npm create vite@latest my-react-app -- --template react
cd my-react-app
npm install
npm run dev

Understanding React Project Structure

This ReactJS tutorial section explains key files in your React project.

public/index.html:

html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>React App</title>
  </head>
  <body>
    <div id="root"></div>
    <!-- React app injects here -->
  </body>
</html>

src/index.js (Entry Point):

javascript
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);

This file:

  1. Imports React and ReactDOM
  2. Imports your main App component
  3. Finds the <div id="root"> element
  4. Renders the App component inside it

src/App.js (Main Component):

javascript
function App() {
  return (
    <div className="App">
      <h1>Hello React!</h1>
      <p>Welcome to your first React app</p>
    </div>
  );
}

export default App;

This defines your main component returning JSX (HTML-like syntax).

Your First React Component

Let’s create your first custom component in this ReactJS tutorial.

Create src/Welcome.js:

javascript
function Welcome() {
  return (
    <div>
      <h2>Welcome to React!</h2>
      <p>This is my first custom component</p>
    </div>
  );
}

export default Welcome;

Use it in App.js:

javascript
import Welcome from './Welcome';

function App() {
  return (
    <div className="App">
      <Welcome />
    </div>
  );
}

export default App;

Key Points:

  • Components are JavaScript functions (or classes)
  • Component names start with capital letters
  • Components return JSX
  • Import components before using them
  • Self-closing tags: <Welcome /> or <Welcome></Welcome>

Save the files and see your component render automatically!

JSX: JavaScript XML

Introduction to JSX

JSX is crucial in this ReactJS tutorial—it’s how you write HTML-like code in JavaScript.

What is JSX:

  • JavaScript syntax extension
  • Looks like HTML but is actually JavaScript
  • Transpiled to JavaScript by Babel
  • Not required but highly recommended

JSX vs HTML:

HTML:

html
<div class="container">
  <h1>Hello World</h1>
</div>

JSX:

javascript
<div className="container">
  <h1>Hello World</h1>
</div>

Notice className instead of class (because class is reserved in JavaScript).

Under the Hood:

JSX:

javascript
const element = <h1>Hello, world!</h1>;

Transpiles to:

javascript
const element = React.createElement('h1', null, 'Hello, world!');

JSX Rules and Syntax

This ReactJS tutorial section covers essential JSX rules.

Rule 1: Single Parent Element

❌ Wrong:

javascript
function App() {
  return (
    <h1>Hello</h1>
    <p>World</p>
  );
}

✅ Correct:

javascript
function App() {
  return (
    <div>
      <h1>Hello</h1>
      <p>World</p>
    </div>
  );
}

Or use Fragments:

javascript
function App() {
  return (
    <>
      <h1>Hello</h1>
      <p>World</p>
    </>
  );
}

Rule 2: Close All Tags

javascript
// Self-closing tags
<img src="photo.jpg" />
<input type="text" />
<br />

// Regular tags
<div></div>
<button></button>

Rule 3: Use camelCase for Attributes

javascript
// HTML attributes become camelCase
className   // instead of class
htmlFor     // instead of for
onClick     // instead of onclick
onChange    // instead of onchange

Rule 4: JavaScript Expressions in Curly Braces

javascript
function Greeting() {
  const name = "John";
  const age = 25;
  
  return (
    <div>
      <h1>Hello {name}!</h1>
      <p>You are {age} years old</p>
      <p>Next year you'll be {age + 1}</p>
    </div>
  );
}

Embedding JavaScript Expressions

This ReactJS tutorial shows how to embed dynamic content in JSX.

Variables:

javascript
function UserInfo() {
  const user = {
    firstName: "Jane",
    lastName: "Doe",
    age: 28
  };
  
  return (
    <div>
      <h2>{user.firstName} {user.lastName}</h2>
      <p>Age: {user.age}</p>
    </div>
  );
}

Expressions:

javascript
function Calculator() {
  const a = 5;
  const b = 10;
  
  return (
    <div>
      <p>{a} + {b} = {a + b}</p>
      <p>{a} × {b} = {a * b}</p>
      <p>Is {a} greater than {b}? {a > b ? 'Yes' : 'No'}</p>
    </div>
  );
}

Function Calls:

javascript
function formatDate(date) {
  return date.toLocaleDateString();
}

function DateDisplay() {
  return (
    <div>
      <p>Today is {formatDate(new Date())}</p>
    </div>
  );
}

Conditional Rendering:

javascript
function Greeting({ isLoggedIn }) {
  return (
    <div>
      {isLoggedIn ? (
        <h1>Welcome back!</h1>
      ) : (
        <h1>Please sign in</h1>
      )}
    </div>
  );
}

Styling in JSX

This ReactJS tutorial covers different ways to style React components.

Inline Styles (Object):

javascript
function StyledComponent() {
  const divStyle = {
    color: 'blue',
    backgroundColor: 'lightgray',
    padding: '10px',
    borderRadius: '5px'
  };
  
  return (
    <div style={divStyle}>
      <h2>Styled with inline styles</h2>
    </div>
  );
}

// Or directly
function DirectStyle() {
  return (
    <div style={{ color: 'red', fontSize: '20px' }}>
      Direct inline style
    </div>
  );
}

CSS Classes:

javascript
// In App.css
/*
.card {
  border: 1px solid #ddd;
  padding: 20px;
  border-radius: 8px;
}

.card-title {
  color: #333;
  font-size: 24px;
}
*/

// In component
import './App.css';

function Card() {
  return (
    <div className="card">
      <h2 className="card-title">Card Title</h2>
      <p>Card content goes here</p>
    </div>
  );
}

Conditional Classes:

javascript
function Button({ isPrimary }) {
  const buttonClass = isPrimary ? 'btn btn-primary' : 'btn btn-secondary';
  
  return (
    <button className={buttonClass}>
      Click Me
    </button>
  );
}

Components Deep Dive

Functional Components

Modern React uses functional components—the focus of this ReactJS tutorial.

Simple Functional Component:

javascript
function Greeting() {
  return <h1>Hello, React!</h1>;
}

With Arrow Function:

javascript
const Greeting = () => {
  return <h1>Hello, React!</h1>;
};

Implicit Return (No Braces):

javascript
const Greeting = () => <h1>Hello, React!</h1>;

Multi-Line JSX:

javascript
const UserCard = () => {
  return (
    <div className="user-card">
      <img src="avatar.jpg" alt="User" />
      <h2>John Doe</h2>
      <p>Software Developer</p>
    </div>
  );
};

Component with Logic:

javascript
function Welcome() {
  const user = {
    name: "Alice",
    age: 30
  };
  
  const canVote = user.age >= 18;
  
  return (
    <div>
      <h1>Welcome, {user.name}!</h1>
      <p>Voting eligibility: {canVote ? 'Yes' : 'No'}</p>
    </div>
  );
}

Props: Passing Data to Components

Props make components reusable—essential in any ReactJS tutorial.

Passing Props:

javascript
function App() {
  return (
    <div>
      <Greeting name="Alice" age={25} />
      <Greeting name="Bob" age={30} />
    </div>
  );
}

Receiving Props:

javascript
function Greeting(props) {
  return (
    <div>
      <h2>Hello, {props.name}!</h2>
      <p>You are {props.age} years old</p>
    </div>
  );
}

Destructuring Props:

javascript
function Greeting({ name, age }) {
  return (
    <div>
      <h2>Hello, {name}!</h2>
      <p>You are {age} years old</p>
    </div>
  );
}

Default Props:

javascript
function Greeting({ name = "Guest", age = 18 }) {
  return (
    <div>
      <h2>Hello, {name}!</h2>
      <p>Age: {age}</p>
    </div>
  );
}

// Usage
<Greeting name="Alice" age={25} />
<Greeting name="Bob" />  // age defaults to 18
<Greeting />  // name defaults to "Guest", age to 18

Passing Different Data Types:

javascript
function UserProfile({ 
  name,           // string
  age,            // number
  isActive,       // boolean
  hobbies,        // array
  address,        // object
  onClick         // function
}) {
  return (
    <div onClick={onClick}>
      <h2>{name}</h2>
      <p>Age: {age}</p>
      <p>Status: {isActive ? 'Active' : 'Inactive'}</p>
      <p>Hobbies: {hobbies.join(', ')}</p>
      <p>City: {address.city}</p>
    </div>
  );
}

// Usage
<UserProfile
  name="Alice"
  age={28}
  isActive={true}
  hobbies={['reading', 'coding', 'hiking']}
  address={{ city: 'New York', country: 'USA' }}
  onClick={() => console.log('Profile clicked')}
/>

Props.children:

javascript
function Card({ children }) {
  return (
    <div className="card">
      {children}
    </div>
  );
}

// Usage
<Card>
  <h2>Card Title</h2>
  <p>Card content goes here</p>
  <button>Click Me</button>
</Card>

Component Composition

This ReactJS tutorial demonstrates building complex UIs from simple components.

Building Blocks:

javascript
function Avatar({ url }) {
  return <img src={url} alt="Avatar" className="avatar" />;
}

function UserName({ name }) {
  return <h3>{name}</h3>;
}

function UserBio({ bio }) {
  return <p>{bio}</p>;
}

function UserCard({ user }) {
  return (
    <div className="user-card">
      <Avatar url={user.avatarUrl} />
      <UserName name={user.name} />
      <UserBio bio={user.bio} />
    </div>
  );
}

// Usage
function App() {
  const user = {
    name: "John Doe",
    avatarUrl: "avatar.jpg",
    bio: "Software Developer"
  };
  
  return <UserCard user={user} />;
}

Container and Presentational Components:

javascript
// Presentational (only displays data)
function ProductCard({ product }) {
  return (
    <div className="product-card">
      <img src={product.image} alt={product.name} />
      <h3>{product.name}</h3>
      <p>${product.price}</p>
    </div>
  );
}

// Container (manages data and logic)
function ProductList() {
  const products = [
    { id: 1, name: 'Laptop', price: 999, image: 'laptop.jpg' },
    { id: 2, name: 'Phone', price: 699, image: 'phone.jpg' },
    { id: 3, name: 'Tablet', price: 499, image: 'tablet.jpg' }
  ];
  
  return (
    <div className="product-list">
      {products.map(product => (
        <ProductCard key={product.id} product={product} />
      ))}
    </div>
  );
}

Lists and Keys

Rendering lists efficiently is critical in this ReactJS tutorial.

Basic List Rendering:

javascript
function FruitList() {
  const fruits = ['Apple', 'Banana', 'Orange', 'Mango'];
  
  return (
    <ul>
      {fruits.map((fruit, index) => (
        <li key={index}>{fruit}</li>
      ))}
    </ul>
  );
}

Using Unique IDs (Better):

javascript
function TodoList() {
  const todos = [
    { id: 1, text: 'Learn React', completed: true },
    { id: 2, text: 'Build a project', completed: false },
    { id: 3, text: 'Deploy app', completed: false }
  ];
  
  return (
    <ul>
      {todos.map(todo => (
        <li key={todo.id}>
          <input type="checkbox" checked={todo.completed} />
          {todo.text}
        </li>
      ))}
    </ul>
  );
}

Rendering Component Lists:

javascript
function UserItem({ user }) {
  return (
    <div className="user-item">
      <h3>{user.name}</h3>
      <p>{user.email}</p>
    </div>
  );
}

function UserList() {
  const users = [
    { id: 1, name: 'Alice', email: 'alice@example.com' },
    { id: 2, name: 'Bob', email: 'bob@example.com' },
    { id: 3, name: 'Charlie', email: 'charlie@example.com' }
  ];
  
  return (
    <div>
      {users.map(user => (
        <UserItem key={user.id} user={user} />
      ))}
    </div>
  );
}

Why Keys Matter:

  • Help React identify which items changed, added, or removed
  • Optimize rendering performance
  • Should be stable, unique, and consistent across re-renders
  • Avoid using array index as key when items can be reordered

State Management with Hooks

Introduction to React Hooks

Hooks revolutionized React—central to this ReactJS tutorial.

What are Hooks:

  • Functions that let you “hook into” React features
  • Use state and lifecycle in functional components
  • Introduced in React 16.8
  • Start with “use” (useState, useEffect, etc.)

Hook Rules:

  1. Only call hooks at the top level (not inside loops, conditions, or nested functions)
  2. Only call hooks from React functions (components or custom hooks)

Most Common Hooks:

  • useState – Add state to components
  • useEffect – Perform side effects
  • useContext – Access context
  • useReducer – Complex state logic
  • useCallback – Memoize callbacks
  • useMemo – Memoize values
  • useRef – Reference values/DOM elements

useState: Managing Component State

useState is fundamental in this ReactJS tutorial.

Basic Usage:

javascript
import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);
  
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>
        Increment
      </button>
    </div>
  );
}

How it Works:

  • useState(0) initializes state with value 0
  • Returns array with two elements: [currentState, updaterFunction]
  • count is the current state value
  • setCount is the function to update state
  • When state updates, component re-renders

Multiple State Variables:

javascript
function UserForm() {
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  const [age, setAge] = useState(0);
  
  return (
    <form>
      <input 
        value={name}
        onChange={(e) => setName(e.target.value)}
        placeholder="Name"
      />
      <input 
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        placeholder="Email"
      />
      <input 
        value={age}
        onChange={(e) => setAge(Number(e.target.value))}
        placeholder="Age"
        type="number"
      />
    </form>
  );
}

State with Objects:

javascript
function UserProfile() {
  const [user, setUser] = useState({
    name: '',
    email: '',
    age: 0
  });
  
  const updateField = (field, value) => {
    setUser(prevUser => ({
      ...prevUser,
      [field]: value
    }));
  };
  
  return (
    <div>
      <input 
        value={user.name}
        onChange={(e) => updateField('name', e.target.value)}
      />
      <input 
        value={user.email}
        onChange={(e) => updateField('email', e.target.value)}
      />
    </div>
  );
}

State with Arrays:

javascript
function TodoApp() {
  const [todos, setTodos] = useState([]);
  const [input, setInput] = useState('');
  
  const addTodo = () => {
    setTodos([...todos, { id: Date.now(), text: input }]);
    setInput('');
  };
  
  const removeTodo = (id) => {
    setTodos(todos.filter(todo => todo.id !== id));
  };
  
  return (
    <div>
      <input 
        value={input}
        onChange={(e) => setInput(e.target.value)}
      />
      <button onClick={addTodo}>Add Todo</button>
      
      <ul>
        {todos.map(todo => (
          <li key={todo.id}>
            {todo.text}
            <button onClick={() => removeTodo(todo.id)}>Delete</button>
          </li>
        ))}
      </ul>
    </div>
  );
}

Functional Updates:

javascript
function Counter() {
  const [count, setCount] = useState(0);
  
  // When new state depends on previous state
  const increment = () => {
    setCount(prevCount => prevCount + 1);
  };
  
  // Multiple updates
  const incrementByThree = () => {
    setCount(prev => prev + 1);
    setCount(prev => prev + 1);
    setCount(prev => prev + 1);
  };
  
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>+1</button>
      <button onClick={incrementByThree}>+3</button>
    </div>
  );
}

useEffect: Side Effects and Lifecycle

useEffect handles side effects in this ReactJS tutorial.

Basic useEffect:

javascript
import { useState, useEffect } from 'react';

function DocumentTitle() {
  const [count, setCount] = useState(0);
  
  useEffect(() => {
    document.title = `Count: ${count}`;
  });
  
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>
        Increment
      </button>
    </div>
  );
}
Also Read: ReactJS interview questions

useEffect with Dependency Array:

javascript
// Runs on every render
useEffect(() => {
  console.log('Runs every render');
});

// Runs only on mount
useEffect(() => {
  console.log('Runs once on mount');
}, []);

// Runs when count changes
useEffect(() => {
  console.log('Count changed:', count);
}, [count]);

// Runs when count or name changes
useEffect(() => {
  console.log('Count or name changed');
}, [count, name]);

Cleanup Function:

javascript
function Timer() {
  const [seconds, setSeconds] = useState(0);
  
  useEffect(() => {
    const interval = setInterval(() => {
      setSeconds(prev => prev + 1);
    }, 1000);
    
    // Cleanup function
    return () => {
      clearInterval(interval);
    };
  }, []);
  
  return <div>Seconds: {seconds}</div>;
}

Fetching Data:

javascript
function UserList() {
  const [users, setUsers] = useState([]);
  const [loading, setLoading] = useState(true);
  
  useEffect(() => {
    fetch('https://api.example.com/users')
      .then(response => response.json())
      .then(data => {
        setUsers(data);
        setLoading(false);
      })
      .catch(error => {
        console.error('Error:', error);
        setLoading(false);
      });
  }, []);
  
  if (loading) return <div>Loading...</div>;
  
  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

Multiple useEffects:

javascript
function UserProfile({ userId }) {
  const [user, setUser] = useState(null);
  const [posts, setPosts] = useState([]);
  
  // Fetch user data
  useEffect(() => {
    fetch(`/api/users/${userId}`)
      .then(r => r.json())
      .then(setUser);
  }, [userId]);
  
  // Fetch user posts
  useEffect(() => {
    fetch(`/api/users/${userId}/posts`)
      .then(r => r.json())
      .then(setPosts);
  }, [userId]);
  
  // Update document title
  useEffect(() => {
    if (user) {
      document.title = user.name;
    }
  }, [user]);
  
  return (
    <div>
      {user && <h1>{user.name}</h1>}
      {posts.map(post => (
        <div key={post.id}>{post.title}</div>
      ))}
    </div>
  );
}

Event Handling

Handling Events in React

Event handling is crucial in this ReactJS tutorial.

Basic Event Handling:

javascript
function Button() {
  const handleClick = () => {
    alert('Button clicked!');
  };
  
  return (
    <button onClick={handleClick}>
      Click Me
    </button>
  );
}

Inline Event Handlers:

javascript
function InlineEvents() {
  return (
    <div>
      <button onClick={() => alert('Clicked!')}>
        Click Me
      </button>
      
      <button onClick={() => console.log('Logged!')}>
        Log Me
      </button>
    </div>
  );
}

Event Object:

javascript
function EventObject() {
  const handleClick = (event) => {
    console.log('Event type:', event.type);
    console.log('Target:', event.target);
    console.log('Current target:', event.currentTarget);
  };
  
  return (
    <button onClick={handleClick}>
      Click for Event Info
    </button>
  );
}

Common Events:

javascript
function Events() {
  return (
    <div>
      {/* Click events */}
      <button onClick={() => console.log('Clicked')}>Click</button>
      <button onDoubleClick={() => console.log('Double clicked')}>
        Double Click
      </button>
      
      {/* Mouse events */}
      <div 
        onMouseEnter={() => console.log('Mouse entered')}
        onMouseLeave={() => console.log('Mouse left')}
      >
        Hover me
      </div>
      
      {/* Form events */}
      <input 
        onChange={(e) => console.log('Input:', e.target.value)}
        onFocus={() => console.log('Focused')}
        onBlur={() => console.log('Blurred')}
      />
      
      <form onSubmit={(e) => {
        e.preventDefault();
        console.log('Form submitted');
      }}>
        <button type="submit">Submit</button>
      </form>
      
      {/* Keyboard events */}
      <input 
        onKeyDown={(e) => console.log('Key down:', e.key)}
        onKeyUp={(e) => console.log('Key up:', e.key)}
        onKeyPress={(e) => console.log('Key press:', e.key)}
      />
    </div>
  );
}

Form Handling

Forms are essential in any ReactJS tutorial.

Controlled Input:

javascript
function ControlledInput() {
  const [value, setValue] = useState('');
  
  return (
    <div>
      <input 
        type="text"
        value={value}
        onChange={(e) => setValue(e.target.value)}
      />
      <p>You typed: {value}</p>
    </div>
  );
}

Complete Form:

javascript
function ContactForm() {
  const [formData, setFormData] = useState({
    name: '',
    email: '',
    message: ''
  });
  
  const handleChange = (e) => {
    const { name, value } = e.target;
    setFormData(prev => ({
      ...prev,
      [name]: value
    }));
  };
  
  const handleSubmit = (e) => {
    e.preventDefault();
    console.log('Form submitted:', formData);
    // Reset form
    setFormData({ name: '', email: '', message: '' });
  };
  
  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label>Name:</label>
        <input 
          type="text"
          name="name"
          value={formData.name}
          onChange={handleChange}
          required
        />
      </div>
      
      <div>
        <label>Email:</label>
        <input 
          type="email"
          name="email"
          value={formData.email}
          onChange={handleChange}
          required
        />
      </div>
      
      <div>
        <label>Message:</label>
        <textarea 
          name="message"
          value={formData.message}
          onChange={handleChange}
          required
        />
      </div>
      
      <button type="submit">Submit</button>
    </form>
  );
}

Checkbox and Radio:

javascript
function FormInputs() {
  const [checked, setChecked] = useState(false);
  const [selected, setSelected] = useState('');
  const [gender, setGender] = useState('');
  
  return (
    <div>
      {/* Checkbox */}
      <label>
        <input 
          type="checkbox"
          checked={checked}
          onChange={(e) => setChecked(e.target.checked)}
        />
        Accept terms
      </label>
      
      {/* Select dropdown */}
      <select 
        value={selected}
        onChange={(e) => setSelected(e.target.value)}
      >
        <option value="">Choose...</option>
        <option value="option1">Option 1</option>
        <option value="option2">Option 2</option>
      </select>
      
      {/* Radio buttons */}
      <div>
        <label>
          <input 
            type="radio"
            value="male"
            checked={gender === 'male'}
            onChange={(e) => setGender(e.target.value)}
          />
          Male
        </label>
        
        <label>
          <input 
            type="radio"
            value="female"
            checked={gender === 'female'}
            onChange={(e) => setGender(e.target.value)}
          />
          Female
        </label>
      </div>
    </div>
  );
}

Form Validation:

javascript
function ValidatedForm() {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [errors, setErrors] = useState({});
  
  const validate = () => {
    const newErrors = {};
    
    if (!email) {
      newErrors.email = 'Email is required';
    } else if (!/\S+@\S+\.\S+/.test(email)) {
      newErrors.email = 'Email is invalid';
    }
    
    if (!password) {
      newErrors.password = 'Password is required';
    } else if (password.length < 6) {
      newErrors.password = 'Password must be at least 6 characters';
    }
    
    return newErrors;
  };
  
  const handleSubmit = (e) => {
    e.preventDefault();
    
    const validationErrors = validate();
    
    if (Object.keys(validationErrors).length > 0) {
      setErrors(validationErrors);
      return;
    }
    
    // Submit form
    console.log('Form is valid!', { email, password });
    setErrors({});
  };
  
  return (
    <form onSubmit={handleSubmit}>
      <div>
        <input 
          type="email"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
          placeholder="Email"
        />
        {errors.email && <span className="error">{errors.email}</span>}
      </div>
      
      <div>
        <input 
          type="password"
          value={password}
          onChange={(e) => setPassword(e.target.value)}
          placeholder="Password"
        />
        {errors.password && <span className="error">{errors.password}</span>}
      </div>
      
      <button type="submit">Submit</button>
    </form>
  );
}

Advanced Hooks

useContext: Global State Management

This ReactJS tutorial covers context for avoiding prop drilling.

Creating Context:

javascript
import { createContext, useContext, useState } from 'react';

// Create context
const ThemeContext = createContext();

// Provider component
function ThemeProvider({ children }) {
  const [theme, setTheme] = useState('light');
  
  const toggleTheme = () => {
    setTheme(prev => prev === 'light' ? 'dark' : 'light');
  };
  
  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      {children}
    </ThemeContext.Provider>
  );
}

// Custom hook for using theme
function useTheme() {
  const context = useContext(ThemeContext);
  if (!context) {
    throw new Error('useTheme must be used within ThemeProvider');
  }
  return context;
}

// Component using context
function ThemedButton() {
  const { theme, toggleTheme } = useTheme();
  
  return (
    <button 
      onClick={toggleTheme}
      style={{ 
        background: theme === 'light' ? '#fff' : '#333',
        color: theme === 'light' ? '#333' : '#fff'
      }}
    >
      Current theme: {theme}
    </button>
  );
}

// App
function App() {
  return (
    <ThemeProvider>
      <ThemedButton />
    </ThemeProvider>
  );
}

User Authentication Example:

javascript
const AuthContext = createContext();

function AuthProvider({ children }) {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);
  
  useEffect(() => {
    // Check if user is logged in
    const token = localStorage.getItem('token');
    if (token) {
      // Validate token and get user
      fetchUser(token).then(setUser);
    }
    setLoading(false);
  }, []);
  
  const login = async (email, password) => {
    const response = await fetch('/api/login', {
      method: 'POST',
      body: JSON.stringify({ email, password })
    });
    const data = await response.json();
    setUser(data.user);
    localStorage.setItem('token', data.token);
  };
  
  const logout = () => {
    setUser(null);
    localStorage.removeItem('token');
  };
  
  return (
    <AuthContext.Provider value={{ user, login, logout, loading }}>
      {children}
    </AuthContext.Provider>
  );
}

function useAuth() {
  return useContext(AuthContext);
}

// Using auth context
function UserProfile() {
  const { user, logout } = useAuth();
  
  return (
    <div>
      <h2>Welcome, {user.name}!</h2>
      <button onClick={logout}>Logout</button>
    </div>
  );
}

useReducer: Complex State Logic

useReducer manages complex state in this ReactJS tutorial.

Basic useReducer:

javascript
import { useReducer } from 'react';

function reducer(state, action) {
  switch (action.type) {
    case 'INCREMENT':
      return { count: state.count + 1 };
    case 'DECREMENT':
      return { count: state.count - 1 };
    case 'RESET':
      return { count: 0 };
    default:
      throw new Error('Unknown action');
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, { count: 0 });
  
  return (
    <div>
      <p>Count: {state.count}</p>
      <button onClick={() => dispatch({ type: 'INCREMENT' })}>+</button>
      <button onClick={() => dispatch({ type: 'DECREMENT' })}>-</button>
      <button onClick={() => dispatch({ type: 'RESET' })}>Reset</button>
    </div>
  );
}

Todo App with useReducer:

javascript
const initialState = {
  todos: [],
  filter: 'all'
};

function todoReducer(state, action) {
  switch (action.type) {
    case 'ADD_TODO':
      return {
        ...state,
        todos: [...state.todos, {
          id: Date.now(),
          text: action.payload,
          completed: false
        }]
      };
      
    case 'TOGGLE_TODO':
      return {
        ...state,
        todos: state.todos.map(todo =>
          todo.id === action.payload
            ? { ...todo, completed: !todo.completed }
            : todo
        )
      };
      
    case 'DELETE_TODO':
      return {
        ...state,
        todos: state.todos.filter(todo => todo.id !== action.payload)
      };
      
    case 'SET_FILTER':
      return {
        ...state,
        filter: action.payload
      };
      
    default:
      return state;
  }
}

function TodoApp() {
  const [state, dispatch] = useReducer(todoReducer, initialState);
  const [input, setInput] = useState('');
  
  const addTodo = () => {
    if (input.trim()) {
      dispatch({ type: 'ADD_TODO', payload: input });
      setInput('');
    }
  };
  
  const filteredTodos = state.todos.filter(todo => {
    if (state.filter === 'completed') return todo.completed;
    if (state.filter === 'active') return !todo.completed;
    return true;
  });
  
  return (
    <div>
      <input 
        value={input}
        onChange={(e) => setInput(e.target.value)}
        onKeyPress={(e) => e.key === 'Enter' && addTodo()}
      />
      <button onClick={addTodo}>Add</button>
      
      <div>
        <button onClick={() => dispatch({ type: 'SET_FILTER', payload: 'all' })}>
          All
        </button>
        <button onClick={() => dispatch({ type: 'SET_FILTER', payload: 'active' })}>
          Active
        </button>
        <button onClick={() => dispatch({ type: 'SET_FILTER', payload: 'completed' })}>
          Completed
        </button>
      </div>
      
      <ul>
        {filteredTodos.map(todo => (
          <li key={todo.id}>
            <input 
              type="checkbox"
              checked={todo.completed}
              onChange={() => dispatch({ type: 'TOGGLE_TODO', payload: todo.id })}
            />
            <span style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}>
              {todo.text}
            </span>
            <button onClick={() => dispatch({ type: 'DELETE_TODO', payload: todo.id })}>
              Delete
            </button>
          </li>
        ))}
      </ul>
    </div>
  );
}

useRef: References and DOM Access

useRef is important in this ReactJS tutorial for accessing DOM and persisting values.

Accessing DOM Elements:

import { useRef, useEffect } from 'react';

function AutoFocusInput() {
  const inputRef = useRef(null);
  
  useEffect(() => {
    inputRef.current.focus();
  }, []);
  
  return <input ref={inputRef} />;
}

Storing Mutable Values:

javascript
function Timer() {
  const [seconds, setSeconds] = useState(0);
  const intervalRef = useRef(null);
  
  const startTimer = () => {
    intervalRef.current = setInterval(() => {
      setSeconds(prev => prev + 1);
    }, 1000);
  };
  
  const stopTimer = () => {
    clearInterval(intervalRef.current);
  };
  
  useEffect(() => {
    return () => clearInterval(intervalRef.current);
  }, []);
  
  return (
    <div>
      <p>Seconds: {seconds}</p>
      <button onClick={startTimer}>Start</button>
      <button onClick={stopTimer}>Stop</button>
    </div>
  );
}

Tracking Previous Values:

javascript
function usePrevious(value) {
  const ref = useRef();
  
  useEffect(() => {
    ref.current = value;
  }, [value]);
  
  return ref.current;
}

function Counter() {
  const [count, setCount] = useState(0);
  const prevCount = usePrevious(count);
  
  return (
    <div>
      <p>Current: {count}</p>
      <p>Previous: {prevCount}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

useMemo and useCallback: Performance Optimization

These hooks optimize performance in this ReactJS tutorial.

useMemo – Memoizing Values:

javascript
import { useMemo } from 'react';

function ExpensiveComponent({ numbers }) {
  const sum = useMemo(() => {
    console.log('Calculating sum...');
    return numbers.reduce((acc, num) => acc + num, 0);
  }, [numbers]);
  
  return <div>Sum: {sum}</div>;
}

useCallback – Memoizing Functions:

javascript
import { useCallback } from 'react';

function ParentComponent() {
  const [count, setCount] = useState(0);
  const [text, setText] = useState('');
  
  // Without useCallback, new function created every render
  const handleClick = useCallback(() => {
    console.log('Button clicked!');
  }, []); // Empty deps - function never changes
  
  return (
    <div>
      <input value={text} onChange={(e) => setText(e.target.value)} />
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <ChildComponent onClick={handleClick} />
    </div>
  );
}

const ChildComponent = React.memo(({ onClick }) => {
  console.log('Child rendered');
  return <button onClick={onClick}>Click Me</button>;
});

Practical Example:

javascript
function SearchComponent() {
  const [query, setQuery] = useState('');
  const [filter, setFilter] = useState('all');
  const [data, setData] = useState([]);
  
  // Expensive filtering operation
  const filteredData = useMemo(() => {
    console.log('Filtering data...');
    return data
      .filter(item => item.name.toLowerCase().includes(query.toLowerCase()))
      .filter(item => filter === 'all' || item.category === filter);
  }, [data, query, filter]);
  
  // Memoized callback
  const handleItemClick = useCallback((id) => {
    console.log('Item clicked:', id);
  }, []);
  
  return (
    <div>
      <input 
        value={query}
        onChange={(e) => setQuery(e.target.value)}
        placeholder="Search..."
      />
      
      <select value={filter} onChange={(e) => setFilter(e.target.value)}>
        <option value="all">All</option>
        <option value="electronics">Electronics</option>
        <option value="books">Books</option>
      </select>
      
      <ul>
        {filteredData.map(item => (
          <li key={item.id} onClick={() => handleItemClick(item.id)}>
            {item.name}
          </li>
        ))}
      </ul>
    </div>
  );
}

Custom Hooks

Creating reusable logic with custom hooks—advanced topic in this ReactJS tutorial.

useLocalStorage Hook:

javascript
function useLocalStorage(key, initialValue) {
  const [value, setValue] = useState(() => {
    const stored = localStorage.getItem(key);
    return stored ? JSON.parse(stored) : initialValue;
  });
  
  useEffect(() => {
    localStorage.setItem(key, JSON.stringify(value));
  }, [key, value]);
  
  return [value, setValue];
}

// Usage
function App() {
  const [name, setName] = useLocalStorage('name', '');
  
  return (
    <input 
      value={name}
      onChange={(e) => setName(e.target.value)}
    />
  );
}

useFetch Hook:

javascript
function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  
  useEffect(() => {
    setLoading(true);
    fetch(url)
      .then(response => response.json())
      .then(data => {
        setData(data);
        setLoading(false);
      })
      .catch(error => {
        setError(error);
        setLoading(false);
      });
  }, [url]);
  
  return { data, loading, error };
}

// Usage
function UserList() {
  const { data, loading, error } = useFetch('https://api.example.com/users');
  
  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;
  
  return (
    <ul>
      {data.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

useToggle Hook:

javascript
function useToggle(initialValue = false) {
  const [value, setValue] = useState(initialValue);
  
  const toggle = useCallback(() => {
    setValue(prev => !prev);
  }, []);
  
  return [value, toggle];
}

// Usage
function ToggleComponent() {
  const [isOn, toggle] = useToggle(false);
  
  return (
    <div>
      <p>Status: {isOn ? 'ON' : 'OFF'}</p>
      <button onClick={toggle}>Toggle</button>
    </div>
  );
}

useDebounce Hook:

javascript
function useDebounce(value, delay) {
  const [debouncedValue, setDebouncedValue] = useState(value);
  
  useEffect(() => {
    const timer = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);
    
    return () => clearTimeout(timer);
  }, [value, delay]);
  
  return debouncedValue;
}

// Usage
function SearchInput() {
  const [searchTerm, setSearchTerm] = useState('');
  const debouncedSearchTerm = useDebounce(searchTerm, 500);
  
  useEffect(() => {
    if (debouncedSearchTerm) {
      // Perform search
      console.log('Searching for:', debouncedSearchTerm);
    }
  }, [debouncedSearchTerm]);
  
  return (
    <input 
      value={searchTerm}
      onChange={(e) => setSearchTerm(e.target.value)}
      placeholder="Search..."
    />
  );
}

Building Real Projects

Project 1: Todo List Application

Let’s build a complete todo app in this ReactJS tutorial.

javascript
import { useState } from 'react';
import './TodoApp.css';

function TodoApp() {
  const [todos, setTodos] = useState([]);
  const [input, setInput] = useState('');
  const [filter, setFilter] = useState('all');
  
  const addTodo = () => {
    if (input.trim()) {
      setTodos([...todos, {
        id: Date.now(),
        text: input,
        completed: false,
        createdAt: new Date()
      }]);
      setInput('');
    }
  };
  
  const toggleTodo = (id) => {
    setTodos(todos.map(todo =>
      todo.id === id ? { ...todo, completed: !todo.completed } : todo
    ));
  };
  
  const deleteTodo = (id) => {
    setTodos(todos.filter(todo => todo.id !== id));
  };
  
  const editTodo = (id, newText) => {
    setTodos(todos.map(todo =>
      todo.id === id ? { ...todo, text: newText } : todo
    ));
  };
  
  const clearCompleted = () => {
    setTodos(todos.filter(todo => !todo.completed));
  };
  
  const filteredTodos = todos.filter(todo => {
    if (filter === 'active') return !todo.completed;
    if (filter === 'completed') return todo.completed;
    return true;
  });
  
  const stats = {
    total: todos.length,
    active: todos.filter(t => !t.completed).length,
    completed: todos.filter(t => t.completed).length
  };
  
  return (
    <div className="todo-app">
      <h1>My Todo List</h1>
      
      <div className="todo-input">
        <input 
          value={input}
          onChange={(e) => setInput(e.target.value)}
          onKeyPress={(e) => e.key === 'Enter' && addTodo()}
          placeholder="What needs to be done?"
        />
        <button onClick={addTodo}>Add</button>
      </div>
      
      <div className="todo-filters">
        <button 
          className={filter === 'all' ? 'active' : ''}
          onClick={() => setFilter('all')}
        >
          All ({stats.total})
        </button>
        <button 
          className={filter === 'active' ? 'active' : ''}
          onClick={() => setFilter('active')}
        >
          Active ({stats.active})
        </button>
        <button 
          className={filter === 'completed' ? 'active' : ''}
          onClick={() => setFilter('completed')}
        >
          Completed ({stats.completed})
        </button>
      </div>
      
      <ul className="todo-list">
        {filteredTodos.map(todo => (
          <TodoItem
            key={todo.id}
            todo={todo}
            onToggle={toggleTodo}
            onDelete={deleteTodo}
            onEdit={editTodo}
          />
        ))}
      </ul>
      
      {stats.completed > 0 && (
        <button onClick={clearCompleted} className="clear-completed">
          Clear Completed
        </button>
      )}
    </div>
  );
}

function TodoItem({ todo, onToggle, onDelete, onEdit }) {
  const [isEditing, setIsEditing] = useState(false);
  const [editText, setEditText] = useState(todo.text);
  
  const handleEdit = () => {
    if (editText.trim()) {
      onEdit(todo.id, editText);
      setIsEditing(false);
    }
  };
  
  return (
    <li className={`todo-item ${todo.completed ? 'completed' : ''}`}>
      <input 
        type="checkbox"
        checked={todo.completed}
        onChange={() => onToggle(todo.id)}
      />
      
      {isEditing ? (
        <input 
          value={editText}
          onChange={(e) => setEditText(e.target.value)}
          onBlur={handleEdit}
          onKeyPress={(e) => e.key === 'Enter' && handleEdit()}
          autoFocus
        />
      ) : (
        <span onDoubleClick={() => setIsEditing(true)}>
          {todo.text}
        </span>
      )}
      
      <button onClick={() => onDelete(todo.id)}>Delete</button>
    </li>
  );
}

export default TodoApp;

Project 2: Weather App

A weather application demonstrating API integration in this ReactJS tutorial.

javascript
import { useState } from 'react';

function WeatherApp() {
  const [city, setCity] = useState('');
  const [weather, setWeather] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);
  
  const API_KEY = 'your_api_key_here';
  
  const fetchWeather = async () => {
    if (!city.trim()) return;
    
    setLoading(true);
    setError(null);
    
    try {
      const response = await fetch(
        `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${API_KEY}&units=metric`
      );
      
      if (!response.ok) {
        throw new Error('City not found');
      }
      
      const data = await response.json();
      setWeather(data);
    } catch (err) {
      setError(err.message);
      setWeather(null);
    } finally {
      setLoading(false);
    }
  };
  
  const handleSubmit = (e) => {
    e.preventDefault();
    fetchWeather();
  };
  
  return (
    <div className="weather-app">
      <h1>Weather App</h1>
      
      <form onSubmit={handleSubmit}>
        <input 
          type="text"
          value={city}
          onChange={(e) => setCity(e.target.value)}
          placeholder="Enter city name"
        />
        <button type="submit">Get Weather</button>
      </form>
      
      {loading && <div className="loading">Loading...</div>}
      
      {error && <div className="error">{error}</div>}
      
      {weather && (
        <div className="weather-card">
          <h2>{weather.name}, {weather.sys.country}</h2>
          <div className="temperature">
            {Math.round(weather.main.temp)}°C
          </div>
          <div className="description">
            {weather.weather[0].description}
          </div>
          <div className="details">
            <div>Feels like: {Math.round(weather.main.feels_like)}°C</div>
            <div>Humidity: {weather.main.humidity}%</div>
            <div>Wind: {weather.wind.speed} m/s</div>
          </div>
        </div>
      )}
    </div>
  );
}

export default WeatherApp;

Project 3: E-commerce Product List

A product listing with cart functionality in this ReactJS tutorial.

javascript
import { useState, createContext, useContext } from 'react';

// Context for cart
const CartContext = createContext();

function CartProvider({ children }) {
  const [cart, setCart] = useState([]);
  
  const addToCart = (product) => {
    setCart(prev => {
      const existing = prev.find(item => item.id === product.id);
      if (existing) {
        return prev.map(item =>
          item.id === product.id
            ? { ...item, quantity: item.quantity + 1 }
            : item
        );
      }
      return [...prev, { ...product, quantity: 1 }];
    });
  };
  
  const removeFromCart = (id) => {
    setCart(prev => prev.filter(item => item.id !== id));
  };
  
  const updateQuantity = (id, quantity) => {
    if (quantity === 0) {
      removeFromCart(id);
      return;
    }
    setCart(prev => prev.map(item =>
      item.id === id ? { ...item, quantity } : item
    ));
  };
  
  const total = cart.reduce((sum, item) => sum + (item.price * item.quantity), 0);
  
  return (
    <CartContext.Provider value={{ cart, addToCart, removeFromCart, updateQuantity, total }}>
      {children}
    </CartContext.Provider>
  );
}

function useCart() {
  return useContext(CartContext);
}

// Product Component
function ProductCard({ product }) {
  const { addToCart } = useCart();
  
  return (
    <div className="product-card">
      <img src={product.image} alt={product.name} />
      <h3>{product.name}</h3>
      <p className="price">${product.price.toFixed(2)}</p>
      <p className="description">{product.description}</p>
      <button onClick={() => addToCart(product)}>
        Add to Cart
      </button>
    </div>
  );
}

// Cart Component
function Cart() {
  const { cart, removeFromCart, updateQuantity, total } = useCart();
  
  if (cart.length === 0) {
    return <div className="cart">Your cart is empty</div>;
  }
  
  return (
    <div className="cart">
      <h2>Shopping Cart</h2>
      {cart.map(item => (
        <div key={item.id} className="cart-item">
          <img src={item.image} alt={item.name} />
          <div className="cart-item-details">
            <h3>{item.name}</h3>
            <p>${item.price.toFixed(2)}</p>
          </div>
          <div className="cart-item-actions">
            <button onClick={() => updateQuantity(item.id, item.quantity - 1)}>-</button>
            <span>{item.quantity}</span>
            <button onClick={() => updateQuantity(item.id, item.quantity + 1)}>+</button>
            <button onClick={() => removeFromCart(item.id)}>Remove</button>
          </div>
        </div>
      ))}
      <div className="cart-total">
        <h3>Total: ${total.toFixed(2)}</h3>
        <button className="checkout-btn">Checkout</button>
      </div>
    </div>
  );
}

// Main App
function ShopApp() {
  const [showCart, setShowCart] = useState(false);
  
  const products = [
    { id: 1, name: 'Laptop', price: 999.99, image: '/laptop.jpg', description: 'Powerful laptop' },
    { id: 2, name: 'Phone', price: 699.99, image: '/phone.jpg', description: 'Latest smartphone' },
    { id: 3, name: 'Headphones', price: 199.99, image: '/headphones.jpg', description: 'Noise-cancelling' },
  ];
  
  return (
    <CartProvider>
      <div className="shop-app

Leave a Reply

Your email address will not be published. Required fields are marked *