Tag: Performance Optimization

  • Visualizing common React useEffect use cases

    Visualizing common React useEffect use cases

    The useEffect hook is crucial in React for handling side effects, such as data fetching, subscriptions, timers, or manually changing the DOM. This guide covers useEffect with practical examples.


    🛠️ Understanding useEffect

    The useEffect hook allows you to perform side effects in functional components. It runs after the render cycle and can be controlled using dependencies.

    Basic Syntax:

    useEffect(() => {
      // Side effect logic
      return () => {
        // Cleanup (if needed)
      };
    }, [dependencies]);
    • Runs on Mount (Empty dependency array [])
    • Runs on Update (List dependencies [state, props])
    • Runs on Unmount (Cleanup function inside return)

    Visualizing useEffect

    1️⃣ Fetching Data

    Fetching User Profile (Social Media App)

    import { useEffect, useState } from "react";
    
    function UserProfile({ userId }) {
      const [user, setUser] = useState(null);
    
      useEffect(() => {
        fetch(`https://api.example.com/users/${userId}`)
          .then((res) => res.json())
          .then((result) => setUser(result));
      }, [userId]);
    
      return user ? <h2>{user.name}</h2> : <p>Loading...</p>;
    }

    Fetching Product List (E-Commerce Site)

    function ProductList() {
      const [products, setProducts] = useState([]);
    
      useEffect(() => {
        fetch("https://api.example.com/products")
          .then((res) => res.json())
          .then((data) => setProducts(data));
      }, []);
    
      return (
        <ul>
          {products.map((product) => (
            <li key={product.id}>{product.name}</li>
          ))}
        </ul>
      );
    }

    2️⃣ Subscriptions & Event Listeners

    Live Chat Listener (Messaging App)

    function ChatComponent({ chatId }) {
      useEffect(() => {
        const socket = new WebSocket(`wss://chat.example.com/${chatId}`);
        socket.onmessage = (event) => console.log("New message: ", event.data);
    
        return () => socket.close(); // Cleanup on unmount
      }, [chatId]);
    
      return <p>Chat Active</p>;
    }

    Listening for Window Resize (Responsive UI)

    function WindowSize() {
      const [width, setWidth] = useState(window.innerWidth);
    
      useEffect(() => {
        const handleResize = () => setWidth(window.innerWidth);
        window.addEventListener("resize", handleResize);
    
        return () => window.removeEventListener("resize", handleResize);
      }, []);
    
      return <p>Window Width: {width}px</p>;
    }

    3️⃣ Managing Timers & Intervals

    Auto-Logout Timer (Banking App)

    function AutoLogout({ logout }) {
      useEffect(() => {
        const timer = setTimeout(() => {
          logout();
        }, 300000); // 5 minutes
    
        return () => clearTimeout(timer); // Cleanup on user activity
      }, []);
    
      return <p>Auto logout enabled</p>;
    }

    Countdown Timer (Auction App)

    function CountdownTimer({ initialTime }) {
      const [timeLeft, setTimeLeft] = useState(initialTime);
    
      useEffect(() => {
        if (timeLeft <= 0) return;
        const timer = setInterval(() => {
          setTimeLeft((prev) => prev - 1);
        }, 1000);
    
        return () => clearInterval(timer);
      }, [timeLeft]);
    
      return <p>Time left: {timeLeft}s</p>;
    }

    4️⃣ Synchronizing with State Changes

    Theme Toggle (E-Commerce Site)

    function ThemeToggle({ theme }) {
      useEffect(() => {
        document.body.className = theme;
      }, [theme]);
    
      return <p>Current Theme: {theme}</p>;
    }

    Syncing Cart with Local Storage (Shopping Cart App)

    function ShoppingCart({ cartItems }) {
      useEffect(() => {
        localStorage.setItem("cart", JSON.stringify(cartItems));
      }, [cartItems]);
    
      return <p>Cart Updated</p>;
    }

    5️⃣ Cleanup Effects

    Music Player (Streaming App)

    function MusicPlayer({ trackUrl }) {
      useEffect(() => {
        const audio = new Audio(trackUrl);
        audio.play();
    
        return () => {
          audio.pause();
          audio.src = "";
        };
      }, [trackUrl]);
    
      return <p>Playing music...</p>;
    }

    Removing Event Listeners (Dashboard App)

    function Dashboard() {
      useEffect(() => {
        const handleScroll = () => console.log("User is scrolling");
        window.addEventListener("scroll", handleScroll);
    
        return () => window.removeEventListener("scroll", handleScroll);
      }, []);
    
      return <p>Scroll to see effect in console</p>;
    }

    📈 Summary

    Understanding useEffect is essential for managing side effects, event listeners, API calls, and subscriptions in React. By structuring effects into data fetching, subscriptions, timers, synchronization, and cleanup, you can build real-world applications efficiently.

  • Understanding the useEffect Hook in React

    What is useEffect?

    useEffect is a React hook that lets functional components perform actions after rendering. These actions can include fetching data, updating the DOM, setting up timers, or handling events. Before hooks, class components used lifecycle methods like componentDidMount and componentWillUnmount to do this.

    With useEffect, all these behaviors can be managed inside a functional component without needing a class.


    How to use useEffect

    To use useEffect, first import it from React and then call it inside your component:

    Example: Fetching Data

    import { useEffect, useState } from "react";
    
    function FetchData() {
      const [data, setData] = useState(null);
    
      useEffect(() => {
        fetch("https://jsonplaceholder.typicode.com/posts/1")
          .then((response) => response.json())
          .then((json) => setData(json));
      }, []);
    
      return (
        <div>
          <h3>Post:</h3>
          <p>{data ? data.title : "Loading..."}</p>
        </div>
      );
    }

    What happens here?

    • useEffect runs when the component first appears on the screen.
    • The empty [] means it only runs once.
    • The effect fetches data and updates the state with setData.

    When does useEffect run?

    The second argument of useEffect is called the dependency array. It tells React when to run the effect.

    1. Updating Document Title

    import { useEffect, useState } from "react";
    
    function TitleUpdater() {
      const [title, setTitle] = useState("React App");
    
      useEffect(() => {
        document.title = title;
      }, [title]);
    
      return (
        <input 
          type="text" 
          value={title} 
          onChange={(e) => setTitle(e.target.value)} 
          placeholder="Update page title" 
        />
      );
    }
    • The document title updates every time title changes.

    2. Auto-Saving Form Input

    import { useEffect, useState } from "react";
    
    function AutoSaveForm() {
      const [input, setInput] = useState("");
    
      useEffect(() => {
        const timeout = setTimeout(() => {
          console.log("Auto-saving input:", input);
        }, 1000);
    
        return () => clearTimeout(timeout);
      }, [input]);
    
      return (
        <input 
          type="text" 
          value={input} 
          onChange={(e) => setInput(e.target.value)} 
          placeholder="Type something..." 
        />
      );
    }
    • Waits 1 second after typing to “auto-save” (simulated with console.log).

    Cleaning up Effects

    Some effects need cleanup, like event listeners and timers. We return a function inside useEffect to clean up.

    Example: Handling Window Resize

    useEffect(() => {
      const handleResize = () => {
        document.body.style.backgroundColor = window.innerWidth > 800 ? "lightblue" : "lightcoral";
      };
    
      window.addEventListener("resize", handleResize);
      handleResize();
    
      return () => {
        window.removeEventListener("resize", handleResize);
      };
    }, []);
    • Dynamically changes the background color based on window width.

    Example: Pausing Background Music

    useEffect(() => {
      const audio = new Audio("/background-music.mp3");
      audio.play();
    
      return () => {
        audio.pause();
      };
    }, []);
    • Plays background music when mounted and pauses when unmounted.

    Common Mistakes with useEffect

    1. Forgetting Dependencies

    useEffect(() => {
      fetchData();
    }, []); // fetchData is missing in dependencies!

    If fetchData depends on props or state, it should be in the dependency array.

    2. Causing an Infinite Loop

    useEffect(() => {
      setCount(count + 1); // Triggers re-render forever!
    }, [count]);

    This keeps updating count, causing an endless loop.

    3. Not Cleaning Up

    useEffect(() => {
      window.addEventListener("scroll", handleScroll);
    }, []);

    If not removed, this event listener stays in memory forever, leading to performance issues.


    useEffect vs. useLayoutEffect

    • useEffect runs after the screen updates (good for data fetching and timers).
    • useLayoutEffect runs before the screen updates (good for layout changes).

    Example:

    useLayoutEffect(() => {
      document.body.style.opacity = "1";
    });

    Most of the time, useEffect is the better choice.


    Summary

    • useEffect handles side effects in functional components.
    • Runs after every render, once on mount, or when dependencies change.
    • Cleanup prevents memory leaks and unnecessary operations.
    • Avoid missing dependencies and infinite loops.

  • Visualizing common React useState use cases

    useState is essential for managing state in React. This guide covers its use with primitives, objects, arrays, and computed values through practical examples.


    🛠️ Understanding useState

    The useState hook is a fundamental tool for managing state in React components. It allows you to store and update values, triggering re-renders when state changes. Here’s a breakdown of common use cases.

    Basic Syntax:

    const [state, setState] = useState(initialValue);
    • state: Current state value
    • setState(newValue): Function to update the state and trigger re-render
    • initialValue: Default state value

    Visualizing useEffect

    1️⃣ Primitive State (Numbers, Strings, Booleans)

    Counter (Numbers)

    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>
      );
    }

    Toggle Button (Boolean)

    function ThemeToggle() {
      const [isDarkMode, setIsDarkMode] = useState(false);
    
      return (
        <button onClick={() => setIsDarkMode(!isDarkMode)}>
          {isDarkMode ? "🌙 Dark Mode" : "☀️ Light Mode"}
        </button>
      );
    }

    Input Fields (Strings)

    function InputField() {
      const [username, setUsername] = useState("");
    
      return (
        <input
          type="text"
          value={username}
          onChange={(e) => setUsername(e.target.value)}
          placeholder="Enter username"
        />
      );
    }

    2️⃣ Object & Array State

    Form State (Object)

    function FormExample() {
      const [form, setForm] = useState({ name: "", email: "" });
    
      return (
        <div>
          <input
            type="text"
            value={form.name}
            onChange={(e) => setForm({ ...form, name: e.target.value })}
            placeholder="Name"
          />
          <input
            type="email"
            value={form.email}
            onChange={(e) => setForm({ ...form, email: e.target.value })}
            placeholder="Email"
          />
        </div>
      );
    }

    To-Do List (Array)

    function TodoList() {
      const [todos, setTodos] = useState([{ id: 1, text: "Learn React", completed: false }]);
    
      const addTodo = () => {
        setTodos([...todos, { id: Date.now(), text: "New Task", completed: false }]);
      };
    
      return (
        <div>
          <ul>
            {todos.map(todo => (
              <li key={todo.id}>{todo.text}</li>
            ))}
          </ul>
          <button onClick={addTodo}>Add Task</button>
        </div>
      );
    }

    3️⃣ Derived & Computed State

    Filtering & Sorting Data

    function FilterList() {
      const [query, setQuery] = useState("");
      const items = ["Apple", "Banana", "Cherry", "Date"];
    
      const filteredItems = items.filter(item => item.toLowerCase().includes(query.toLowerCase()));
    
      return (
        <div>
          <input type="text" placeholder="Search..." onChange={(e) => setQuery(e.target.value)} />
          <ul>
            {filteredItems.map(item => <li key={item}>{item}</li>)}
          </ul>
        </div>
      );
    }

    4️⃣ UI & Interaction State

    Modals & Popups

    function ModalExample() {
      const [isOpen, setIsOpen] = useState(false);
    
      return (
        <div>
          <button onClick={() => setIsOpen(true)}>Open Modal</button>
          {isOpen && (
            <div className="modal">
              <p>Modal Content</p>
              <button onClick={() => setIsOpen(false)}>Close</button>
            </div>
          )}
        </div>
      );
    }

    5️⃣ Performance & Optimization

    Debounced State

    function DebouncedSearch() {
      const [query, setQuery] = useState("");
      const [debouncedQuery, setDebouncedQuery] = useState("");
    
      useEffect(() => {
        const timeout = setTimeout(() => setDebouncedQuery(query), 500);
        return () => clearTimeout(timeout);
      }, [query]);
    
      return (
        <input type="text" onChange={(e) => setQuery(e.target.value)} placeholder="Debounced Search..." />
      );
    }

    📈 Summary

    Mastering useState is essential for building interactive React applications. By structuring state into primitives, objects, computed values, UI state, and performance optimizations, you can create efficient and scalable applications.