惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Cisco Talos Blog
Cisco Talos Blog
Martin Fowler
Martin Fowler
A
About on SuperTechFans
H
Help Net Security
F
Full Disclosure
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
IT之家
IT之家
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
阮一峰的网络日志
阮一峰的网络日志
WordPress大学
WordPress大学
H
Heimdal Security Blog
博客园_首页
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
T
Tailwind CSS Blog
Recent Announcements
Recent Announcements
B
Blog RSS Feed
Last Week in AI
Last Week in AI
V2EX - 技术
V2EX - 技术
The Register - Security
The Register - Security
Security Archives - TechRepublic
Security Archives - TechRepublic
G
GRAHAM CLULEY
美团技术团队
S
Securelist
MyScale Blog
MyScale Blog
Vercel News
Vercel News
L
LINUX DO - 最新话题
Hacker News: Ask HN
Hacker News: Ask HN
W
WeLiveSecurity
M
MIT News - Artificial intelligence
宝玉的分享
宝玉的分享
月光博客
月光博客
Attack and Defense Labs
Attack and Defense Labs
大猫的无限游戏
大猫的无限游戏
博客园 - Franky
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Microsoft Security Blog
Microsoft Security Blog
I
InfoQ
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Forbes - Security
Forbes - Security
罗磊的独立博客
O
OpenAI News
AI
AI
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
雷峰网
雷峰网
S
Security @ Cisco Blogs
MongoDB | Blog
MongoDB | Blog
Schneier on Security
Schneier on Security
P
Proofpoint News Feed
Webroot Blog
Webroot Blog
V
Visual Studio Blog

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
React Hooks
Humais Ali · 2026-05-13 · via DEV Community
{
  "title": "Introduction to React Hooks",
  "published": true,
  "tags": ["react", "javascript", "webdev", "frontend", "hooks", "usestate", "useeffect", "programming", "beginners"]
}

Enter fullscreen mode Exit fullscreen mode

Introduction to React Hooks: Mastering State and Side Effects for Beginners

Hey there, fellow developers and aspiring React enthusiasts! 👋 Are you ready to dive into one of the most powerful and transformative features introduced in React? If you've ever felt overwhelmed by this in class components, struggled with managing complex component lifecycles, or wished for a simpler way to reuse logic across your React applications, then you're in the right place.

React Hooks, introduced in React 16.8, revolutionized how we write React components by allowing us to use state and other React features without writing a class. They bring the elegance and simplicity of functional components to the forefront, enabling cleaner, more readable, and more maintainable code.

In this comprehensive, beginner-friendly guide, we're going to demystify React Hooks. We'll focus on the two foundational hooks that you'll use almost every day: useState for managing component state and useEffect for handling side effects like data fetching, subscriptions, and manual DOM manipulations. By the end of this article, you'll not only understand how these hooks work but also feel confident enough to start using them in your own projects.

So, buckle up! Let's unlock the power of React Hooks together.

Who is This Guide For?

This article is tailored for:

  • Beginners in React: If you're new to React and want to learn the modern way of building components.
  • Developers transitioning from class components: If you've worked with class components and want to understand the functional alternative.
  • Anyone curious about React Hooks: If you want a clear, practical explanation of useState and useEffect.

A basic understanding of JavaScript (ES6+ features like arrow functions, destructuring) and fundamental React concepts (components, props) will be beneficial, but I'll do my best to explain everything in detail.

What Exactly Are React Hooks?

Before Hooks, if you needed state or lifecycle methods (like componentDidMount, componentDidUpdate, componentWillUnmount) in a React component, you had to use a class component. Functional components were often referred to as "stateless functional components" because they couldn't hold their own state or perform side effects directly.

React Hooks change this paradigm entirely. They are functions that let you "hook into" React state and lifecycle features from functional components. This means you can now write almost all of your React components as functions, which are generally easier to read, test, and reason about.

Think of Hooks as special JavaScript functions that connect your functional components to React's core features.

The Golden Rules of Hooks

There are two fundamental rules you must follow when using Hooks:

  1. Only call Hooks at the top level: Don't call Hooks inside loops, conditions, or nested functions. Hooks should always be called at the top level of your React function component. This ensures that Hooks are called in the same order each time a component renders, which is crucial for React to correctly associate local state with each Hook.
  2. Only call Hooks from React functions: You can call Hooks from React function components or from custom Hooks (which we won't cover in depth here, but are just functions that use other Hooks). You cannot call Hooks from regular JavaScript functions.

Adhering to these rules helps React maintain the internal state and behavior of your components reliably.

Let's dive into our first and perhaps most frequently used Hook!


useState: Managing Component State

In React, "state" refers to data that can change over time and influences what is rendered on the screen. For example, the count in a counter app, the text in an input field, or whether a modal is open or closed are all examples of state.

The useState Hook allows functional components to have their own internal state. It's the equivalent of this.state and this.setState in class components, but much simpler and cleaner.

How useState Works

The useState Hook returns an array with two elements:

  1. The current state value.
  2. A function that lets you update the state value.

You typically use array destructuring to get these two values.

Syntax:

import React, { useState } from 'react';

function MyComponent() {
  const [stateVariable, setStateVariable] = useState(initialValue);
  // ... rest of your component logic
}

Enter fullscreen mode Exit fullscreen mode

  • stateVariable: This is the current value of your state.
  • setStateVariable: This is a function that you call to update stateVariable. When setStateVariable is called, React will re-render the component.
  • initialValue: This is the value stateVariable will have on the initial render of the component. It can be a number, string, boolean, object, array, or null.

Let's look at some practical examples.

Example 1: A Simple Counter

Imagine we want to create a component that displays a number and has a button to increment it.

import React, { useState } from 'react';

function Counter() {
  // Declare a state variable called 'count' and a function 'setCount' to update it.
  // The initial value of 'count' is 0.
  const [count, setCount] = useState(0);

  const increment = () => {
    setCount(count + 1); // Update the 'count' state
  };

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={increment}>
        Click me
      </button>
    </div>
  );
}

export default Counter;

Enter fullscreen mode Exit fullscreen mode

Explanation:

  1. We import useState from React.
  2. Inside Counter, we call useState(0). This initializes count to 0.
  3. useState returns [count, setCount]. count is the current value, and setCount is the function to update it.
  4. The increment function calls setCount(count + 1). When setCount is called, React re-renders the Counter component with the new count value.

Example 2: Managing Text Input

Let's create a component with an input field that updates a paragraph in real-time.

import React, { useState } from 'react';

function TextInput() {
  const [text, setText] = useState(''); // Initialize with an empty string

  const handleChange = (event) => {
    setText(event.target.value); // Update 'text' state with input value
  };

  return (
    <div>
      <input
        type="text"
        value={text} // The input value is controlled by our 'text' state
        onChange={handleChange}
        placeholder="Type something..."
      />
      <p>You typed: {text}</p>
    </div>
  );
}

export default TextInput;

Enter fullscreen mode Exit fullscreen mode

Explanation:

  1. We initialize text state as an empty string.
  2. The <input> element's value prop is bound to our text state, making it a "controlled component."
  3. Whenever the input value changes (onChange), handleChange is triggered, which calls setText with the new input value (event.target.value).
  4. This updates the text state, causing the component to re-render and display the updated text in the paragraph.

Important Considerations for useState

  • State Updates are Asynchronous: React often batches state updates for performance reasons. This means setCount(count + 1) doesn't immediately change count. If you need to use the new state immediately after setting it, consider using the functional update form or useEffect.
  • Functional Updates: When your new state depends on the previous state, it's safer and recommended to pass a function to your setter:

    setCount(prevCount => prevCount + 1); // Ensures you're working with the most up-to-date state
    
  • Immutability for Objects/Arrays: When dealing with object or array state, always create a new object or array when updating. Modifying the existing state object directly can lead to subtle bugs because React performs shallow comparisons to detect changes.

    const [user, setUser] = useState({ name: 'Alice', age: 30 });
    
    const updateAge = () => {
      // BAD: Mutates the existing object directly
      // user.age = user.age + 1;
      // setUser(user);
    
      // GOOD: Creates a new object
      setUser(prevUser => ({
        ...prevUser, // Copy all existing properties
        age: prevUser.age + 1 // Override the age property
      }));
    };
    

useEffect: Handling Side Effects

While useState helps manage data within your component, useEffect helps you deal with everything else – tasks that interact with the outside world or need to happen after your component has rendered. These are known as "side effects."

Common side effects include:

  • Data Fetching: Making API calls.
  • DOM Manipulation: Manually changing the document title, adding event listeners.
  • Subscriptions: Setting up subscriptions to external data sources.
  • Timers: setTimeout or setInterval.

In class components, you'd typically handle these using lifecycle methods like componentDidMount, componentDidUpdate, and componentWillUnmount. useEffect provides a single, unified API to handle all these scenarios.

How useEffect Works

The useEffect Hook takes two arguments:

  1. A callback function: This is where you put your side effect code.
  2. An optional dependency array: This array tells React when to re-run the effect.

Syntax:

import React, { useEffect } from 'react';

function MyComponent() {
  useEffect(() => {
    // Your side effect code goes here

    // Optional: Return a cleanup function
    return () => {
      // This runs when the component unmounts or before the effect re-runs
      // e.g., unsubscribing, clearing timers
    };
  }, [dependency1, dependency2]); // Dependency array
}

Enter fullscreen mode Exit fullscreen mode

Let's explore the dependency array, as it's crucial for controlling when your effects run.

Understanding the Dependency Array

The second argument to useEffect is an array of values that the effect depends on.

  • No dependency array (omitted): The effect runs after every render of the component. This is rarely what you want for performance-intensive operations like data fetching.
  • Empty dependency array ([]): The effect runs only once after the initial render (like componentDidMount). The cleanup function (if any) runs only when the component unmounts (like componentWillUnmount). This is perfect for initial data fetching.
  • Dependency array with values ([propA, stateB]): The effect runs after the initial render, and then again whenever any of the values in the dependency array change. The cleanup function runs before the effect re-runs and when the component unmounts. This is similar to componentDidUpdate combined with componentWillUnmount.

Let's see some examples.

Example 3: Data Fetching (Runs Once)

Fetching data is a classic side effect. We want to fetch data when the component mounts and only once.

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

function DataFetcher() {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    // This effect runs once after the initial render because of the empty dependency array []
    console.log('Effect for data fetching ran!');

    const fetchData = async () => {
      try {
        const response = await fetch('https://jsonplaceholder.typicode.com/posts/1');
        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }
        const result = await response.json();
        setData(result);
      } catch (err) {
        setError(err);
      } finally {
        setLoading(false);
      }
    };

    fetchData(); // Call the async function

  }, []); // Empty dependency array means this effect runs only once on mount

  if (loading) return <p>Loading data...</p>;
  if (error) return <p>Error: {error.message}</p>;

  return (
    <div>
      <h2>Fetched Data:</h2>
      <p><strong>Title:</strong> {data?.title}</p>
      <p><strong>Body:</strong> {data?.body}</p>
    </div>
  );
}

export default DataFetcher;

Enter fullscreen mode Exit fullscreen mode

Explanation:

  1. We use useState to manage data, loading, and error states.
  2. Inside useEffect, we define an async function fetchData to make an API call.
  3. We immediately call fetchData().
  4. The [] (empty dependency array) ensures that this useEffect runs only once after the initial render, just like componentDidMount. It will not re-run on subsequent renders unless the component is unmounted and then re-mounted.

Example 4: Updating Document Title (Runs on Dependency Change)

Let's make the document title reflect the counter from our first example.

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

function TitleUpdater() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    // This effect runs after initial render AND whenever 'count' changes
    console.log('Effect for title update ran!');
    document.title = `You clicked ${count} times`;
  }, [count]); // Dependency array includes 'count'

  const increment = () => {
    setCount(prevCount => prevCount + 1);
  };

  return (
    <div>
      <p>Look at your browser tab title!</p>
      <p>You clicked {count} times</p>
      <button onClick={increment}>
        Click me
      </button>
    </div>
  );
}

export default TitleUpdater;

Enter fullscreen mode Exit fullscreen mode

Explanation:

  1. We have a count state.
  2. The useEffect here has [count] as its dependency array. This means:
    • It runs after the initial render.
    • It runs again every time the count state changes.
  3. Each time it runs, it updates document.title to reflect the current count.

Example 5: Event Listener with Cleanup (Runs on Mount/Unmount)

Some side effects, like adding event listeners or setting up subscriptions, require a "cleanup" mechanism to prevent memory leaks or unwanted behavior when the component unmounts or when the effect re-runs. useEffect handles this beautifully with its optional return function.

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

function MouseTracker() {
  const [position, setPosition] = useState({ x: 0, y: 0 });

  useEffect(() => {
    console.log('Effect: Event listener added!');

    const handleMouseMove = (event) => {
      setPosition({ x: event.clientX, y: event.clientY });
    };

    // Add event listener when component mounts
    window.addEventListener('mousemove', handleMouseMove);

    // This is the cleanup function!
    return () => {
      console.log('Cleanup: Event listener removed!');
      // Remove event listener when component unmounts or before effect re-runs
      window.removeEventListener('mousemove', handleMouseMove);
    };
  }, []); // Empty dependency array: runs once on mount, cleans up on unmount

  return (
    <div>
      <h2>Mouse Position:</h2>
      <p>X: {position.x}, Y: {position.y}</p>
      <small>(Move your mouse over this component)</small>
    </div>
  );
}

export default MouseTracker;

Enter fullscreen mode Exit fullscreen mode

Explanation:

  1. We have a position state to store mouse coordinates.
  2. Inside useEffect, we define handleMouseMove to update the position.
  3. We add a mousemove event listener to the window.
  4. Crucially, we return a function from useEffect. This return function is the cleanup function.
  5. With an empty dependency array []:
    • The useEffect callback runs once after the initial render (adds the listener).
    • The cleanup function runs once when the component is unmounted from the DOM (removes the listener), preventing memory leaks.
    • If the dependency array contained values, the cleanup would run before the effect re-runs with new dependencies, and also when the component unmounts.

Important Considerations for useEffect

  • Separate Concerns: You can use multiple useEffect calls in a single component to separate different concerns. For example, one useEffect for data fetching, another for subscriptions, and another for document title updates. This makes your code more organized and easier to understand than a single monolithic componentDidMount.
  • Be Mindful of Dependencies: Always include all values from your component's scope (props, state, functions) that your useEffect uses in its dependency array. If you omit a dependency, your effect might run with stale values, leading to bugs. ESLint rules (like eslint-plugin-react-hooks) can help you enforce this.
  • Effects vs. Render Logic: useEffect is for side effects, not for changing state that directly affects the next render. If you need to update state immediately after a render, and that update is synchronous, you might reconsider if useEffect is the right tool or if a state update function within an event handler is more appropriate.

The Power of Hooks: A Recap

By now, you should have a solid grasp of useState and useEffect, the cornerstones of modern React development. Let's quickly summarize why they're so impactful:

  • Simpler State Management: useState eliminates the need for this.state and this.setState, making state management in functional components intuitive.
  • Unified Side Effect Handling: useEffect consolidates the logic previously spread across componentDidMount, componentDidUpdate, and componentWillUnmount into a single, cohesive API with powerful control over execution through its dependency array and cleanup mechanism.
  • Improved Readability and Reusability: Functional components with Hooks are often shorter and easier to read. The ability to extract stateful logic into custom Hooks (a more advanced topic) dramatically improves code reuse.
  • Less Boilerplate: Say goodbye to class syntax, constructor bindings, and verbose lifecycle methods. Hooks lead to less code overall.

Conclusion

Congratulations! You've successfully navigated the exciting world of React Hooks. You now understand the fundamental principles behind useState for managing component-specific data and useEffect for handling crucial side effects like data fetching, DOM interactions, and setting up cleanups.

These two hooks alone will empower you to build robust, efficient, and clean React applications without relying on class components. They are the backbone of functional component development in React and mastering them is a huge step forward in your journey as a React developer.

As you continue to build, you'll discover other powerful built-in hooks like useContext, useReducer, useRef, and the immense flexibility of creating your own custom hooks. But for now, take pride in your understanding of useState and useEffect – they are the essential tools you'll reach for daily.

Now, go forth and build amazing things with React Hooks! Experiment with the examples, build your own small components, and don't hesitate to refer back to this guide or the official React documentation as you learn.

What are your thoughts on Hooks? Have you started transitioning your older components? Share your experiences in the comments below!


Further Reading: