🎯 What Are Multiple States & Fragments?

Imagine you're controlling a smart home system:

SINGLE STATE (One Light Switch):
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  πŸ’‘ ONE LIGHT SWITCH                    β”‚
β”‚                                         β”‚
β”‚  State: light = true (ON)               β”‚
β”‚                                         β”‚
β”‚  [ON] ← [Switch]                        β”‚
β”‚                                         β”‚
β”‚  Problem: What about the TV?            β”‚
β”‚  What about the curtains?               β”‚
β”‚  One switch can't control everything!   β”‚
β”‚                                         β”‚
β”‚  In React:                              β”‚
β”‚  const [light, setLight] = useState(true);β”‚
β”‚  // Only controls one thing!            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

MULTIPLE STATES (Full Smart Home):
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  🏠 SMART HOME CONTROL PANEL            β”‚
β”‚                                         β”‚
β”‚  Light:    [ON]  ← state 1              β”‚
β”‚  TV:       [OFF] ← state 2              β”‚
β”‚  Curtains: [OPEN]← state 3              β”‚
β”‚                                         β”‚
β”‚  Each switch is INDEPENDENT!            β”‚
β”‚  Turning off TV doesn't affect light!   β”‚
β”‚                                         β”‚
β”‚  In React:                              β”‚
β”‚  const [light, setLight] = useState(true);  β”‚
β”‚  const [tv, setTv] = useState(false);        β”‚
β”‚  const [curtains, setCurtains] = useState(true);β”‚
β”‚  // Each controls its own thing!        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

FRAGMENTS (Invisible Container):
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  πŸ“¦ REGULAR CONTAINER                   β”‚
β”‚                                         β”‚
β”‚  <div>                                  β”‚
β”‚   <button>X</button>                    β”‚
β”‚   <div>Content</div>                    β”‚
β”‚  </div>                                 β”‚
β”‚                                         β”‚
β”‚  Result in DOM:                         β”‚
β”‚  <div>                                  β”‚
β”‚   <button>X</button>                    β”‚
β”‚   <div>Content</div>                    β”‚
β”‚  </div>                                 β”‚
β”‚  ↑ Extra div wrapper!                   β”‚
β”‚                                         β”‚
β”‚  FRAGMENT:                              β”‚
β”‚  <>                                     β”‚
β”‚   <button>X</button>                    β”‚
β”‚   <div>Content</div>                    β”‚
β”‚  </>                                    β”‚
β”‚                                         β”‚
β”‚  Result in DOM:                         β”‚
β”‚  <button>X</button>                     β”‚
β”‚  <div>Content</div>                     β”‚
β”‚  ↑ No extra wrapper! Clean!             β”‚
β”‚                                         β”‚
β”‚  In React:                              β”‚
β”‚  <> ... </>  or  <React.Fragment> ... </React.Fragment>β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

KEY INSIGHT:
Multiple states = "Each piece of data gets its own memory slot"
Fragments = "Invisible wrapper that doesn't add extra HTML"

⚠️ The Big Problem: "How Do I Show/Hide Things?"

// ==========================================
// THE "ALWAYS VISIBLE" TRAP
// ==========================================

// ❌ WRONG: Component always shows, can't hide
function Steps() {
  const [step, setStep] = useState(1);

  return (
    <div>
      {/* This ALWAYS shows! No way to hide it! */}
      <div className="steps">
        <div className="numbers">...</div>
        <p className="message">...</p>
        <div className="buttons">...</div>
      </div>
    </div>
  );
}

// Problem: What if user wants to minimize/collapse?
// What if we want a close button?
// The component is ALWAYS there!

// ==========================================
// THE SOLUTION: State + Conditional Rendering
// ==========================================

// βœ… CORRECT: Use state to control visibility
function Steps() {
  const [step, setStep] = useState(1);
  const [isOpen, setIsOpen] = useState(true);  // NEW STATE!

  return (
    <div>
      {/* Close button ALWAYS visible */}
      <button className="close" onClick={() => setIsOpen(!isOpen)}>
        &times;  {/* X symbol */}
      </button>

      {/* Panel only shows when isOpen is true! */}
      {isOpen && (
        <div className="steps">
          <div className="numbers">...</div>
          <p className="message">...</p>
          <div className="buttons">...</div>
        </div>
      )}
    </div>
  );
}

// What happens:
// isOpen = true:
//    {true && <div...>} β†’ <div...> renders!
//    Panel is VISIBLE!
//
// Click X button:
//    setIsOpen(!true) β†’ setIsOpen(false)
//    React re-renders!
//
// isOpen = false:
//    {false && <div...>} β†’ false (React ignores)
//    Panel is HIDDEN!
//
// Click X button again:
//    setIsOpen(!false) β†’ setIsOpen(true)
//    Panel is VISIBLE again!

πŸ“‹ Complete Visual Examples

Create file: react-multiple-state-fragments.js

// ==========================================
// MULTIPLE STATES & FRAGMENTS - Complete Guide
// ==========================================

/*
MULTIPLE STATES PATTERN:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Each independent piece of data gets    β”‚
β”‚  its own useState() call                β”‚
β”‚                                          β”‚
β”‚  const [step, setStep] = useState(1);   β”‚
β”‚  const [isOpen, setIsOpen] = useState(true);β”‚
β”‚  const [theme, setTheme] = useState('light');β”‚
β”‚                                          β”‚
β”‚  These states are COMPLETELY INDEPENDENT!β”‚
β”‚  Changing one doesn't affect the others  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

FRAGMENTS PATTERN:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  When you need to return multiple        β”‚
β”‚  elements without a wrapper div:         β”‚
β”‚                                          β”‚
β”‚  <>                                     β”‚
β”‚   <button>X</button>                   β”‚
β”‚   <div>Content</div>                    β”‚
β”‚  </>                                    β”‚
β”‚                                          β”‚
β”‚  No extra DOM element created!          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
*/

// ==========================================
// EXAMPLE 1: Steps Component with Open/Close
// ==========================================

import { useState } from 'react';

function App() {
  // STATE 1: Which step we're on
  const [step, setStep] = useState(1);
  
  // STATE 2: Whether panel is open or closed
  const [isOpen, setIsOpen] = useState(true);

  const messages = [
    "Learn React βš›οΈ",
    "Apply for jobs πŸ’Ό",
    "Invest your new income πŸ€‘"
  ];

  function handlePrevious() {
    if (step > 1) setStep(step - 1);
  }

  function handleNext() {
    if (step < 3) setStep(step + 1);
  }

  return (
    // FRAGMENT: Returns multiple elements without wrapper div!
    <>
      {/* Close/Open button - ALWAYS visible */}
      <button className="close" onClick={() => setIsOpen(!isOpen)}>
        &times;
      </button>

      {/* Steps panel - ONLY shows when isOpen is true! */}
      {isOpen && (
        <div className="steps">
          <div className="numbers">
            <div className={step >= 1 ? 'active' : ''}>1</div>
            <div className={step >= 2 ? 'active' : ''}>2</div>
            <div className={step >= 3 ? 'active' : ''}>3</div>
          </div>

          <p className="message">
            Step {step}: {messages[step - 1]}
          </p>

          <div className="buttons">
            <button onClick={handlePrevious}>Previous</button>
            <button onClick={handleNext}>Next</button>
          </div>
        </div>
      )}
    </>
  );
}

// Visual Flow:
// INITIAL STATE:
// step = 1, isOpen = true
//    ↓
// Shows: [X button] + [Step 1 panel]

// CLICK X BUTTON:
// setIsOpen(!true) β†’ setIsOpen(false)
// React re-renders!
//    ↓
// step = 1, isOpen = false
//    ↓
// Shows: [X button] only
// Panel hidden! {false && ...} β†’ nothing

// CLICK X BUTTON AGAIN:
// setIsOpen(!false) β†’ setIsOpen(true)
// React re-renders!
//    ↓
// step = 1, isOpen = true
//    ↓
// Shows: [X button] + [Step 1 panel]
// Panel back! step still remembers 1!

// CLICK NEXT (while open):
// setStep(2)
// React re-renders!
//    ↓
// step = 2, isOpen = true
//    ↓
// Shows: [X button] + [Step 2 panel]

// CLICK X BUTTON:
// setIsOpen(!true) β†’ setIsOpen(false)
//    ↓
// step = 2, isOpen = false
// Panel hidden, but step REMEMBERS 2!

// CLICK X BUTTON AGAIN:
// step = 2, isOpen = true
// Panel shows Step 2 (not Step 1!)
// State persisted while hidden!

// ==========================================
// EXAMPLE 2: Multiple Independent States
// ==========================================

function Dashboard() {
  // State 1: User name
  const [name, setName] = useState("Alice");
  
  // State 2: Notification count
  const [notifications, setNotifications] = useState(5);
  
  // State 3: Dark mode toggle
  const [isDarkMode, setIsDarkMode] = useState(false);
  
  // State 4: Sidebar collapsed
  const [isSidebarOpen, setIsSidebarOpen] = useState(true);

  // Each state is INDEPENDENT!
  // Changing notifications doesn't affect dark mode!
  // Changing name doesn't affect sidebar!

  return (
    <div className={isDarkMode ? 'dark' : 'light'}>
      <header>
        <h1>Welcome, {name}</h1>
        <span>πŸ”” {notifications}</span>
        <button onClick={() => setIsDarkMode(!isDarkMode)}>
          {isDarkMode ? 'β˜€οΈ' : 'πŸŒ™'}
        </button>
      </header>
      
      {isSidebarOpen && <Sidebar />}
      
      <main>
        <button onClick={() => setNotifications(n => n + 1)}>
          Add Notification
        </button>
        <button onClick={() => setName(name === "Alice" ? "Bob" : "Alice")}>
          Switch User
        </button>
        <button onClick={() => setIsSidebarOpen(!isSidebarOpen)}>
          Toggle Sidebar
        </button>
      </main>
    </div>
  );
}

// ==========================================
// EXAMPLE 3: Inline Event Handler (Simple Cases)
// ==========================================

function ToggleExample() {
  const [isVisible, setIsVisible] = useState(true);

  return (
    <div>
      {/* Inline arrow function - good for simple logic! */}
      <button onClick={() => setIsVisible(!isVisible)}>
        {isVisible ? 'Hide' : 'Show'}
      </button>

      {isVisible && <p>This text can be hidden!</p>}
    </div>
  );
}

// When to use inline vs separate function:
// INLINE: Simple one-liners
//   onClick={() => setIsOpen(!isOpen)}
//
// SEPARATE: Complex logic
//   function handleSubmit() {
//     validate();
//     saveToDatabase();
//     setSubmitted(true);
//   }

// ==========================================
// EXAMPLE 4: The && Operator for Conditional Rendering
// ==========================================

function ConditionalRendering() {
  const [isLoggedIn, setIsLoggedIn] = useState(false);
  const [showDetails, setShowDetails] = useState(false);

  return (
    <div>
      {/* && Operator: Show only if condition is true */}
      {isLoggedIn && <WelcomeMessage />}
      {/* If false, React renders nothing! */}

      {showDetails && (
        <div className="details">
          <p>Extra information here!</p>
          <p>More details...</p>
        </div>
      )}

      {/* Toggle buttons */}
      <button onClick={() => setIsLoggedIn(!isLoggedIn)}>
        {isLoggedIn ? 'Logout' : 'Login'}
      </button>
      
      <button onClick={() => setShowDetails(!showDetails)}>
        {showDetails ? 'Hide Details' : 'Show Details'}
      </button>
    </div>
  );
}

// How && works:
// true && <Component />  β†’ <Component /> renders
// false && <Component /> β†’ false (React ignores, renders nothing)

// ==========================================
// EXAMPLE 5: Fragments in Action
// ==========================================

function FragmentExample() {
  const [items, setItems] = useState(['Apple', 'Banana', 'Cherry']);

  return (
    // Using Fragment <>...</> instead of <div>...</div>
    <>
      <h1>Fruit List</h1>
      <ul>
        {items.map(item => <li key={item}>{item}</li>)}
      </ul>
      <button onClick={() => setItems([...items, 'Date'])}>
        Add Fruit
      </button>
    </>
  );
}

// WITHOUT Fragment:
// <div>
//   <h1>Fruit List</h1>
//   <ul>...</ul>
//   <button>...</button>
// </div>
// Result: Extra wrapper div in DOM

// WITH Fragment:
// <>
//   <h1>Fruit List</h1>
//   <ul>...</ul>
//   <button>...</button>
// </>
// Result: No wrapper! Clean DOM:
// <h1>Fruit List</h1>
// <ul>...</ul>
// <button>...</button>

πŸš€ Interactive React Usage Examples

Complete React File: MultipleStateFragmentsMasterClass.jsx

import React, { useState } from 'react';

// ==========================================
// INTERACTIVE MULTIPLE STATES & FRAGMENTS DEMO
// ==========================================

function MultipleStateFragmentsMasterClass() {
  const [activeDemo, setActiveDemo] = useState('steps');

  const demos = {
    steps: { title: 'Steps + Open/Close', component: <StepsDemo /> },
    multiple: { title: 'Multiple States', component: <MultipleStatesDemo /> },
    fragment: { title: 'Fragments', component: <FragmentDemo /> },
    inline: { title: 'Inline Handlers', component: <InlineHandlerDemo /> }
  };

  return (
    <div style={{ maxWidth: '900px', margin: '0 auto', padding: '20px', fontFamily: 'Arial, sans-serif' }}>
      <header style={{ background: '#e9c46a', color: '#264653', padding: '30px', borderRadius: '10px', marginBottom: '30px' }}>
        <h1 style={{ margin: 0 }}>🧩 Multiple States & Fragments</h1>
        <p style={{ margin: '10px 0 0 0', opacity: 0.9 }}>Independent State & Invisible Wrappers</p>
      </header>

      <nav style={{ display: 'flex', gap: '10px', marginBottom: '30px', flexWrap: 'wrap' }}>
        {Object.entries(demos).map(([key, { title }]) => (
          <button
            key={key}
            onClick={() => setActiveDemo(key)}
            style={{
              padding: '12px 24px',
              fontSize: '16px',
              border: 'none',
              borderRadius: '8px',
              cursor: 'pointer',
              backgroundColor: activeDemo === key ? '#264653' : '#e0e0e0',
              color: activeDemo === key ? 'white' : '#333',
              fontWeight: activeDemo === key ? 'bold' : 'normal'
            }}
          >
            {title}
          </button>
        ))}
      </nav>

      <main style={{ background: '#f8f9fa', padding: '30px', borderRadius: '10px', minHeight: '400px' }}>
        {demos[activeDemo].component}
      </main>
    </div>
  );
}

// ==========================================
// DEMO 1: Steps with Open/Close
// ==========================================

function StepsDemo() {
  const [step, setStep] = useState(1);
  const [isOpen, setIsOpen] = useState(true);

  const messages = [
    "Learn React βš›οΈ",
    "Apply for jobs πŸ’Ό",
    "Invest your new income πŸ€‘"
  ];

  return (
    <div>
      <h2>Steps Component with Open/Close</h2>
      
      <div style={{ marginBottom: '20px', padding: '15px', background: '#e3f2fd', borderRadius: '8px' }}>
        <h4>Two Independent States:</h4>
        <ul>
          <li><code>step</code>: Current step number (1-3)</li>
          <li><code>isOpen</code>: Whether panel is visible (true/false)</li>
        </ul>
      </div>

      {/* FRAGMENT: No wrapper div! */}
      <>
        {/* Close button - ALWAYS visible */}
        <button
          onClick={() => setIsOpen(!isOpen)}
          style={{
            float: 'right',
            padding: '5px 15px',
            fontSize: '20px',
            background: 'none',
            border: 'none',
            cursor: 'pointer',
            color: '#666'
          }}
        >
          {isOpen ? 'βœ•' : '☰'}
        </button>

        {/* Steps panel - CONDITIONALLY rendered */}
        {isOpen && (
          <div style={{
            padding: '30px',
            background: 'white',
            borderRadius: '10px',
            boxShadow: '0 2px 10px rgba(0,0,0,0.1)',
            marginTop: '40px'
          }}>
            {/* Step numbers */}
            <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '30px' }}>
              {[1, 2, 3].map(num => (
                <div key={num} style={{
                  width: '40px',
                  height: '40px',
                  borderRadius: '50%',
                  display: 'flex',
                  alignItems: 'center',
                  justifyContent: 'center',
                  fontWeight: 'bold',
                  backgroundColor: step >= num ? '#7950f2' : '#e0e0e0',
                  color: step >= num ? 'white' : '#333',
                  transition: 'all 0.3s'
                }}>
                  {num}
                </div>
              ))}
            </div>

            {/* Message */}
            <p style={{ textAlign: 'center', fontSize: '20px', marginBottom: '30px' }}>
              Step {step}: {messages[step - 1]}
            </p>

            {/* Buttons */}
            <div style={{ display: 'flex', justifyContent: 'space-between' }}>
              <button
                onClick={() => setStep(s => Math.max(1, s - 1))}
                disabled={step === 1}
                style={{
                  padding: '10px 20px',
                  backgroundColor: step === 1 ? '#ccc' : '#7950f2',
                  color: 'white',
                  border: 'none',
                  borderRadius: '5px',
                  cursor: step === 1 ? 'not-allowed' : 'pointer'
                }}
              >
                Previous
              </button>
              <button
                onClick={() => setStep(s => Math.min(3, s + 1))}
                disabled={step === 3}
                style={{
                  padding: '10px 20px',
                  backgroundColor: step === 3 ? '#ccc' : '#7950f2',
                  color: 'white',
                  border: 'none',
                  borderRadius: '5px',
                  cursor: step === 3 ? 'not-allowed' : 'pointer'
                }}
              >
                Next
              </button>
            </div>
          </div>
        )}
      </>

      <div style={{ marginTop: '20px', padding: '15px', background: '#fff3e0', borderRadius: '8px' }}>
        <h4>🧠 Try This:</h4>
        <ol>
          <li>Click "Next" to go to Step 2 or 3</li>
          <li>Click "βœ•" to close the panel</li>
          <li>Click "☰" to open it again</li>
          <li>Notice: Step number is REMEMBERED!</li>
        </ol>
      </div>
    </div>
  );
}

// ==========================================
// DEMO 2: Multiple Independent States
// ==========================================

function MultipleStatesDemo() {
  const [count, setCount] = useState(0);
  const [name, setName] = useState("Alice");
  const [color, setColor] = useState("blue");

  return (
    <div>
      <h2>Three Independent States</h2>
      
      <div style={{ display: 'grid', gap: '20px', gridTemplateColumns: '1fr 1fr 1fr' }}>
        {/* State 1: Counter */}
        <div style={{ padding: '20px', background: 'white', borderRadius: '8px', border: '2px solid #e0e0e0' }}>
          <h3>State 1: Count</h3>
          <div style={{ fontSize: '36px', fontWeight: 'bold', color: '#7950f2' }}>{count}</div>
          <button 
            onClick={() => setCount(c => c + 1)}
            style={{ padding: '8px 16px', background: '#7950f2', color: 'white', border: 'none', borderRadius: '5px' }}
          >
            Increment
          </button>
        </div>

        {/* State 2: Name */}
        <div style={{ padding: '20px', background: 'white', borderRadius: '8px', border: '2px solid #e0e0e0' }}>
          <h3>State 2: Name</h3>
          <div style={{ fontSize: '24px', fontWeight: 'bold', color: '#2196f3' }}>{name}</div>
          <button 
            onClick={() => setName(name === "Alice" ? "Bob" : "Alice")}
            style={{ padding: '8px 16px', background: '#2196f3', color: 'white', border: 'none', borderRadius: '5px' }}
          >
            Toggle Name
          </button>
        </div>

        {/* State 3: Color */}
        <div style={{ padding: '20px', background: 'white', borderRadius: '8px', border: '2px solid #e0e0e0' }}>
          <h3>State 3: Color</h3>
          <div style={{ 
            width: '50px', 
            height: '50px', 
            borderRadius: '50%', 
            backgroundColor: color,
            margin: '0 auto 10px'
          }} />
          <button 
            onClick={() => setColor(color === "blue" ? "red" : "blue")}
            style={{ padding: '8px 16px', background: '#f44336', color: 'white', border: 'none', borderRadius: '5px' }}
          >
            Toggle Color
          </button>
        </div>
      </div>

      <div style={{ marginTop: '20px', padding: '15px', background: '#e8f5e9', borderRadius: '8px' }}>
        <h4>βœ… Key Observation:</h4>
        <p>Clicking any button only updates ONE state!</p>
        <p>The other two states stay exactly the same!</p>
        <p>Each <code>useState()</code> creates independent memory!</p>
      </div>
    </div>
  );
}

// ==========================================
// DEMO 3: Fragments
// ==========================================

function FragmentDemo() {
  const [useFragment, setUseFragment] = useState(true);

  return (
    <div>
      <h2>React Fragments</h2>
      
      <div style={{ marginBottom: '20px' }}>
        <button 
          onClick={() => setUseFragment(!useFragment)}
          style={{ padding: '10px 20px', background: '#7950f2', color: 'white', border: 'none', borderRadius: '5px' }}
        >
          Toggle: {useFragment ? 'Using Fragment' : 'Using div'}
        </button>
      </div>

      <div style={{ display: 'grid', gap: '20px', gridTemplateColumns: '1fr 1fr' }}>
        {/* Code View */}
        <div style={{ padding: '20px', background: 'white', borderRadius: '8px', border: '2px solid #e0e0e0' }}>
          <h3>Code:</h3>
          {useFragment ? (
            <pre style={{ background: '#1e1e1e', color: '#d4d4d4', padding: '15px', borderRadius: '4px', fontSize: '13px' }}>
{`// Using Fragment (<>...</>)
<>
  <h3>Title</h3>
  <p>Content</p>
  <button>Action</button>
</>`}
            </pre>
          ) : (
            <pre style={{ background: '#1e1e1e', color: '#d4d4d4', padding: '15px', borderRadius: '4px', fontSize: '13px' }}>
{`// Using div
<div>
  <h3>Title</h3>
  <p>Content</p>
  <button>Action</button>
</div>`}
            </pre>
          )}
        </div>

        {/* DOM Result */}
        <div style={{ padding: '20px', background: 'white', borderRadius: '8px', border: '2px solid #e0e0e0' }}>
          <h3>DOM Result:</h3>
          {useFragment ? (
            <div style={{ background: '#e8f5e9', padding: '15px', borderRadius: '4px' }}>
              <pre style={{ margin: 0, fontSize: '14px' }}>
{`<h3>Title</h3>
<p>Content</p>
<button>Action</button>`}
              </pre>
              <p style={{ color: '#2e7d32', fontSize: '14px' }}>βœ… No wrapper element!</p>
            </div>
          ) : (
            <div style={{ background: '#ffebee', padding: '15px', borderRadius: '4px' }}>
              <pre style={{ margin: 0, fontSize: '14px' }}>
{`<div>
  <h3>Title</h3>
  <p>Content</p>
  <button>Action</button>
</div>`}
              </pre>
              <p style={{ color: '#c62828', fontSize: '14px' }}>❌ Extra div wrapper!</p>
            </div>
          )}
        </div>
      </div>

      <div style={{ marginTop: '20px', padding: '15px', background: '#fff3e0', borderRadius: '8px' }}>
        <h4>When to Use Fragments:</h4>
        <ul>
          <li>When you need to return multiple elements</li>
          <li>When a wrapper div would break styling</li>
          <li>When you want cleaner DOM structure</li>
          <li>Inside table elements (tr, td, etc.)</li>
        </ul>
      </div>
    </div>
  );
}

// ==========================================
// DEMO 4: Inline vs Separate Handlers
// ==========================================

function InlineHandlerDemo() {
  const [count, setCount] = useState(0);
  const [message, setMessage] = useState("");

  // Separate function for complex logic
  function handleComplexUpdate() {
    const newCount = count + 1;
    setCount(newCount);
    
    if (newCount % 5 === 0) {
      setMessage("Multiple of 5! πŸŽ‰");
    } else {
      setMessage("");
    }
  }

  return (
    <div>
      <h2>Inline vs Separate Event Handlers</h2>
      
      <div style={{ display: 'grid', gap: '20px', gridTemplateColumns: '1fr 1fr' }}>
        {/* Inline Handler */}
        <div style={{ padding: '20px', background: 'white', borderRadius: '8px', border: '2px solid #e0e0e0' }}>
          <h3>Inline Handler (Simple)</h3>
          <pre style={{ background: '#1e1e1e', color: '#d4d4d4', padding: '15px', borderRadius: '4px', fontSize: '13px' }}>
{`<button onClick={() => setCount(count + 1)}>
  Increment
</button>`}
          </pre>
          <button 
            onClick={() => setCount(count + 1)}
            style={{ padding: '10px 20px', background: '#4caf50', color: 'white', border: 'none', borderRadius: '5px' }}
          >
            Increment (Inline)
          </button>
          <p style={{ fontSize: '14px', color: '#666', marginTop: '10px' }}>
            <em>Good for: Simple one-line updates</em>
          </p>
        </div>

        {/* Separate Handler */}
        <div style={{ padding: '20px', background: 'white', borderRadius: '8px', border: '2px solid #e0e0e0' }}>
          <h3>Separate Handler (Complex)</h3>
          <pre style={{ background: '#1e1e1e', color: '#d4d4d4', padding: '15px', borderRadius: '4px', fontSize: '13px' }}>
{`function handleComplexUpdate() {
  const newCount = count + 1;
  setCount(newCount);
  if (newCount % 5 === 0) {
    setMessage("Multiple of 5!");
  }
}`}
          </pre>
          <button 
            onClick={handleComplexUpdate}
            style={{ padding: '10px 20px', background: '#2196f3', color: 'white', border: 'none', borderRadius: '5px' }}
          >
            Complex Update
          </button>
          <p style={{ fontSize: '14px', color: '#666', marginTop: '10px' }}>
            <em>Good for: Multiple state updates, conditions</em>
          </p>
        </div>
      </div>

      <div style={{ marginTop: '20px', textAlign: 'center', padding: '20px', background: '#f5f5f5', borderRadius: '8px' }}>
        <div style={{ fontSize: '36px', fontWeight: 'bold', color: '#7950f2' }}>{count}</div>
        {message && <p style={{ color: '#4caf50', fontSize: '18px' }}>{message}</p>}
      </div>
    </div>
  );
}

export default MultipleStateFragmentsMasterClass;

🧠 Memory Aids for Poor Logic Thinking

The "Multiple Memory Slots" Analogy

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  MULTIPLE useState = MULTIPLE MEMORY SLOTS        β”‚
β”‚                                                 β”‚
β”‚  Component = Person with multiple pockets         β”‚
β”‚                                                 β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  πŸ‘€ COMPONENT PERSON                    β”‚    β”‚
β”‚  β”‚                                          β”‚    β”‚
β”‚  β”‚  Pocket 1: [step = 2]                   β”‚    β”‚
β”‚  β”‚     ↑ useState(1)                       β”‚    β”‚
β”‚  β”‚                                          β”‚    β”‚
β”‚  β”‚  Pocket 2: [isOpen = true]              β”‚    β”‚
β”‚  β”‚     ↑ useState(true)                    β”‚    β”‚
β”‚  β”‚                                          β”‚    β”‚
β”‚  β”‚  Pocket 3: [name = "Alice"]             β”‚    β”‚
β”‚  β”‚     ↑ useState("Alice")                 β”‚    β”‚
β”‚  β”‚                                          β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                                                 β”‚
β”‚  Each pocket is INDEPENDENT!                    β”‚
β”‚  Taking something from Pocket 1                β”‚
β”‚  doesn't affect Pocket 2!                       β”‚
β”‚                                                 β”‚
β”‚  In React:                                      β”‚
β”‚  const [step, setStep] = useState(1);          β”‚
β”‚  const [isOpen, setIsOpen] = useState(true);    β”‚
β”‚  const [name, setName] = useState("Alice");     β”‚
β”‚                                                 β”‚
β”‚  setStep(3) β†’ Only step changes!                β”‚
β”‚  isOpen and name stay the same!                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

The "Light Switch" Analogy for &&

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  && OPERATOR = LIGHT SWITCH                     β”‚
β”‚                                                 β”‚
β”‚  {isOpen && <Panel />}                          β”‚
β”‚                                                 β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  isOpen = true                          β”‚    β”‚
β”‚  β”‚                                          β”‚    β”‚
β”‚  β”‚  true && <Panel />                      β”‚    β”‚
β”‚  β”‚     ↑                                    β”‚    β”‚
β”‚  β”‚  Switch is ON β†’ Electricity flows!    β”‚    β”‚
β”‚  β”‚  β†’ <Panel /> renders!                   β”‚    β”‚
β”‚  β”‚                                          β”‚    β”‚
β”‚  β”‚  Result: Panel is VISIBLE               β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                                                 β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  isOpen = false                         β”‚    β”‚
β”‚  β”‚                                          β”‚    β”‚
β”‚  β”‚  false && <Panel />                     β”‚    β”‚
β”‚  β”‚      ↑                                   β”‚    β”‚
β”‚  β”‚  Switch is OFF β†’ Electricity stops!     β”‚    β”‚
β”‚  β”‚  β†’ false (React ignores)                β”‚    β”‚
β”‚  β”‚                                          β”‚    β”‚
β”‚  β”‚  Result: Panel is HIDDEN                β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                                                 β”‚
β”‚  MEMORY TRICK:                                   β”‚
β”‚  && = "AND" = "Both sides must be true"         β”‚
β”‚  If first is false, second doesn't matter!        β”‚
β”‚  (Short circuiting!)                              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

The "Packing Boxes" Analogy for Fragments

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  FRAGMENTS = INVISIBLE PACKAGING                 β”‚
β”‚                                                 β”‚
β”‚  SCENARIO: Shipping three items                   β”‚
β”‚                                                 β”‚
β”‚  WITH BOX (div wrapper):                          β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  πŸ“¦ SHIPPING BOX                        β”‚    β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”                            β”‚    β”‚
β”‚  β”‚  β”‚ πŸ“± Phoneβ”‚                            β”‚    β”‚
β”‚  β”‚  β”‚ 🎧 Buds β”‚                            β”‚    β”‚
β”‚  β”‚  β”‚ πŸ”Œ Cableβ”‚                            β”‚    β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                            β”‚    β”‚
β”‚  β”‚                                          β”‚    β”‚
β”‚  β”‚  Customer receives:                     β”‚    β”‚
β”‚  β”‚  "Why is there an empty box?"           β”‚    β”‚
β”‚  β”‚  (Extra div in DOM)                     β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                                                 β”‚
β”‚  WITHOUT BOX (Fragment):                          β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  πŸ“± Phone                               β”‚    β”‚
β”‚  β”‚  🎧 Buds                                β”‚    β”‚
β”‚  β”‚  πŸ”Œ Cable                               β”‚    β”‚
β”‚  β”‚                                          β”‚    β”‚
β”‚  β”‚  Customer receives:                     β”‚    β”‚
β”‚  β”‚  Just the items! No extra packaging!    β”‚    β”‚
β”‚  β”‚  (No extra div in DOM)                  β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                                                 β”‚
β”‚  In React:                                      β”‚
β”‚  // With wrapper (extra div)                  β”‚
β”‚  <div>                                         β”‚
β”‚    <button>X</button>                         β”‚
β”‚    <div>Content</div>                         β”‚
β”‚  </div>                                        β”‚
β”‚                                                 β”‚
β”‚  // With Fragment (no extra element)          β”‚
β”‚  <>                                            β”‚
β”‚    <button>X</button>                         β”‚
β”‚    <div>Content</div>                         β”‚
β”‚  </>                                           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

The "Toggle Switch" Pattern

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  TOGGLE PATTERN (Very Common!)                    β”‚
β”‚                                                 β”‚
β”‚  const [isOpen, setIsOpen] = useState(true);      β”‚
β”‚                                                 β”‚
β”‚  Toggle function:                                 β”‚
β”‚  setIsOpen(!isOpen)                               β”‚
β”‚      ↑                                            β”‚
β”‚  "Set to the OPPOSITE of current"               β”‚
β”‚                                                 β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  Current: isOpen = true                 β”‚    β”‚
β”‚  β”‚  !true = false                          β”‚    β”‚
β”‚  β”‚  setIsOpen(false) β†’ Now closed!          β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                      ↓                          β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  Current: isOpen = false                β”‚    β”‚
β”‚  β”‚  !false = true                          β”‚    β”‚
β”‚  β”‚  setIsOpen(true) β†’ Now open!            β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                                                 β”‚
β”‚  INLINE VERSION:                                  β”‚
β”‚  <button onClick={() => setIsOpen(!isOpen)}>   β”‚
β”‚    {isOpen ? 'Close' : 'Open'}                 β”‚
β”‚  </button>                                      β”‚
β”‚                                                 β”‚
β”‚  SEPARATE FUNCTION VERSION:                       β”‚
β”‚  function handleToggle() {                      β”‚
β”‚    setIsOpen(!isOpen);                          β”‚
β”‚  }                                               β”‚
β”‚  <button onClick={handleToggle}>               β”‚
β”‚    {isOpen ? 'Close' : 'Open'}                 β”‚
β”‚  </button>                                      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸŽ“ Practice Exercises

Exercise 1: Create a Toggle Panel

Create a panel that shows/hides content when clicking a button:

function TogglePanel() {
  // TODO: Add state for visibility
  // TODO: Show "Show" or "Hide" based on state
  // TODO: Conditionally render content
  
  return (
    <div>
      <button>{/* Toggle text */}</button>
      {/* Content here */}
    </div>
  );
}

Solution:

import { useState } from 'react';

function TogglePanel() {
  const [isVisible, setIsVisible] = useState(false);

  return (
    <div>
      <button onClick={() => setIsVisible(!isVisible)}>
        {isVisible ? 'Hide' : 'Show'} Content
      </button>
      
      {isVisible && (
        <div style={{ padding: '20px', background: '#f5f5f5', marginTop: '10px' }}>
          <p>This content can be shown or hidden!</p>
        </div>
      )}
    </div>
  );
}

Exercise 2: Multiple Independent Counters

Create two counters that work independently:

function DualCounter() {
  // TODO: Two separate count states
  // TODO: Each with its own increment button
  
  return (
    <div>
      {/* Counter A */}
      {/* Counter B */}
    </div>
  );
}

Solution:

import { useState } from 'react';

function DualCounter() {
  const [countA, setCountA] = useState(0);
  const [countB, setCountB] = useState(0);

  return (
    <div style={{ display: 'flex', gap: '20px' }}>
      <div style={{ padding: '20px', border: '2px solid #ccc', borderRadius: '8px' }}>
        <h3>Counter A</h3>
        <p>{countA}</p>
        <button onClick={() => setCountA(countA + 1)}>+</button>
      </div>
      
      <div style={{ padding: '20px', border: '2px solid #ccc', borderRadius: '8px' }}>
        <h3>Counter B</h3>
        <p>{countB}</p>
        <button onClick={() => setCountB(countB + 1)}>+</button>
      </div>
    </div>
  );
}

Exercise 3: Fix the Fragment Bug

This code throws an error. Fix it:

function App() {
  const [show, setShow] = useState(true);

  return {
    <button onClick={() => setShow(!show)}>Toggle</button>
    {show && <p>Content</p>}
  };
}

Bug: Using { } instead of ( ) for JSX return, and multiple elements without wrapper.

Solution:

import { useState } from 'react';

function App() {
  const [show, setShow] = useState(true);

  return (
    <>  {/* Fragment wrapper */}
      <button onClick={() => setShow(!show)}>Toggle</button>
      {show && <p>Content</p>}
    </>
  );
}

πŸ’‘ Key Takeaways

ConceptWhat It MeansExample
Multiple StatesEach piece of data gets own useStateconst [a, setA] = useState(0); const [b, setB] = useState("")
IndependentChanging one doesn't affect otherssetA(5) doesn't change b
&& OperatorShow element only if condition true{isOpen && <Panel />}
FragmentWrapper that doesn't create DOM element<>...</> or <React.Fragment>...</React.Fragment>
Toggle PatternFlip boolean with !setIsOpen(!isOpen)
Inline HandlerSimple logic directly in JSXonClick={() => setX(!x)}

The Multiple State Pattern:

function Component() {
  // Each independent piece of data = separate useState
  const [step, setStep] = useState(1);
  const [isOpen, setIsOpen] = useState(true);
  
  return (
    <>
      {/* Fragment: no extra wrapper */}
      <button onClick={() => setIsOpen(!isOpen)}>
        {isOpen ? 'Close' : 'Open'}
      </button>
      
      {isOpen && (
        <div>
          <p>Step: {step}</p>
          <button onClick={() => setStep(step + 1)}>Next</button>
        </div>
      )}
    </>
  );
}

Golden Rules:

  1. One useState per independent data - Don't cram unrelated data together
  2. && for conditional rendering - {condition && <Element />}
  3. Fragments for multiple roots - <>...</> instead of unnecessary <div>...</div>
  4. Toggle with ! - setValue(!value) flips boolean
  5. Inline for simple, separate for complex - Match handler style to logic complexity

One Sentence Summary: > "Use multiple useState calls for independent pieces of data, wrap multiple JSX elements in fragments (<>...</>) to avoid unnecessary DOM wrappers, and use the && operator with a boolean state to conditionally show or hide entire sections of your UI - remembering that each state persists independently even when the component re-renders!"