Tag: useState

  • 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.

  • Understanding the useState Hook in React

    What is useState?

    useState is a React hook that allows functional components to manage state. Unlike class components, which use this.state and setState, functional components didn’t originally have a way to handle state until hooks were introduced in React 16.8.

    useState provides a way to declare state variables and update them while ensuring React re-renders the component when state changes.


    How to use useState

    To implement useState in a component, first import it from React and then call it inside a functional component. Here’s an example:

    import { useState } from "react";
    
    function Form() {
      const [inputValue, setInputValue] = useState("");
    
      return (
        <div>
          <input
            type="text"
            value={inputValue}
            onChange={(e) => setInputValue(e.target.value)}
          />
          <p>Entered text: {inputValue}</p>
        </div>
      );
    }

    Here:

    • inputValue is the state variable.
    • setInputValue is the function used to update inputValue.
    • useState("") initializes the state with an empty string.

    As the user types in the input field, setInputValue updates the state, causing the component to re-render with the new value.


    What useState returns

    useState returns an array with two elements:

    1. The current state value.
    2. A function to update the state.

    This is why array destructuring is used to extract these values.

    const [state, setState] = useState(initialValue);

    React ensures that when setState is called, the component re-renders with the new state value.


    Storing different types of values in useState

    useState can hold different types of values, including strings, objects, arrays, and even functions.

    Example with a boolean:

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

    Example with an object:

    const [user, setUser] = useState({ name: "Alice", age: 25 });
    
    const updateAge = () => {
      setUser(prevUser => ({ ...prevUser, age: prevUser.age + 1 }));
    };

    When updating objects, use the spread operator (...prevUser) to ensure existing properties aren’t lost.


    Does useState update state immediately?

    State updates in React are asynchronous. When setState is called, React schedules a re-render, but the state change isn’t reflected immediately in the current execution cycle.

    const [inputValue, setInputValue] = useState("");
    
    const handleChange = (e) => {
      setInputValue(e.target.value);
      console.log(inputValue); // Might still log the old value!
    };

    To ensure working with the latest state, use a function inside setState:

    setInputValue(prevValue => e.target.value);

    This ensures the latest state value is used.


    Handling multiple state updates

    React batches state updates in event handlers for performance optimization. If multiple updates happen like this:

    setInputValue("Hello");
    setInputValue("World");

    React may only apply the last one because inputValue isn’t updated immediately. To correctly apply updates, use functional updates:

    setInputValue(prevValue => prevValue + "!");

    This ensures each update works on the latest value.


    Updating state with the same value

    If setState is called with the same value as the current state, React will skip re-rendering the component.

    const [inputValue, setInputValue] = useState("");
    setInputValue("");

    React detects that the new state is the same as the previous state and does not trigger a re-render.


    Initializing state with a function

    To optimize state initialization when working with expensive calculations, pass a function to useState. This function runs only once, during the initial render.

    const [data, setData] = useState(() => {
      console.log("Expensive calculation running...");
      return computeExpensiveData();
    });

    This prevents unnecessary calculations on every re-render.


    When to use useState vs useReducer

    useState is great for managing simple state, like toggles, form inputs, or visibility toggles. However, if state logic is complex (e.g., managing multiple state transitions or dependent updates), useReducer is a better choice.

    For example, a simple form input can use useState, but a more complex state like a form reducer should use useReducer.

    const [state, dispatch] = useReducer(reducerFunction, initialState);

    In summary:

    • useState is used to manage local state in functional components.
    • It returns a state variable and an updater function.
    • Updates are asynchronous and can be batched.
    • Use functional updates when dealing with previous state values.
    • React avoids unnecessary re-renders when the new state is the same as the old state.

    Mastering useState is crucial for React development, and understanding how it behaves under different conditions will make development more efficient.