React 入门到实战:组件、状态与 Hooks

FreeGuideOnline 最新 2026-06-15

React 入门到实战:组件、状态与 Hooks

1. 认识 React

React 是由 Facebook 开发的用于构建用户界面的 JavaScript 库。它的核心理念是 组件化:将 UI 拆分为独立、可复用的模块,每个模块管理自己的状态和渲染逻辑。React 使用 声明式 写法,只需描述界面应该长什么样,React 负责高效更新 DOM。

现代 React 开发以 函数组件 + Hooks 为主,我们将围绕这一范式进行学习。

2. 开发环境准备

推荐使用 Vite 快速初始化项目。在终端中运行:

npm create vite@latest react-tutorial -- --template react
cd react-tutorial
npm install
npm run dev

浏览器访问 http://localhost:5173 即可看到默认页面。

3. 第一个函数组件与 JSX

3.1 JSX 语法

JSX 是 JavaScript 的语法扩展,看起来像 HTML,但最终会被编译为 React.createElement 调用。它允许你在 JavaScript 中直接书写 UI 结构。

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

3.2 JSX 规则速览

  • 返回单个根元素:必须用 <div> 或空标签 <>...</> 包裹多个元素。
  • 使用 {} 嵌入表达式:可以插入变量、函数调用等。
  • 属性命名class 写成 classNamefor 写成 htmlFor
  • 自闭合标签必须闭合<br /><input />

3.3 组件导出与使用

组件文件通常使用默认导出:

// Welcome.jsx
export default function Welcome({ name }) {
  return <h2>欢迎{name}</h2>;
}

在其他组件中导入并使用:

import Welcome from './Welcome';

function App() {
  return (
    <div>
      <Welcome name="小明" />
      <Welcome name="小红" />
    </div>
  );
}

4. Props:父子组件通信

Props 是父组件传递给子组件的只读数据。在函数组件中通过第一个参数接收。

function UserCard({ avatar, name, bio }) {
  return (
    <div className="card">
      <img src={avatar} alt={name} />
      <h3>{name}</h3>
      <p>{bio}</p>
    </div>
  );
}

传递 Props 时,可以传递字符串、数字、对象、函数等任意 JavaScript 类型。如果 Prop 没有被传递,可以设置默认值:

function UserCard({ name = '匿名用户' }) { ... }

5. 状态管理:useState Hook

Hook 是 React 16.8 引入的特性,让你在函数组件中使用 state 和其他 React 功能。useState 是最基础的 Hook。

5.1 声明状态

import { useState } from 'react';

function Counter() {
  // count 是当前状态值,setCount 是更新函数
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>当前计数{count}</p>
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  );
}
  • useState(初始值) 返回一个数组,使用解构赋值命名。
  • 状态更新后,组件会重新渲染。
  • 状态是异步更新的:如果需要根据前一个状态计算新值,应该使用函数式更新:setCount(prev => prev + 1)

5.2 对象或数组状态

当状态是对象或数组时,必须 替换而不是修改 原值,以保持不可变性。

const [user, setUser] = useState({ name: '', age: 0 });

// 正确更新方式
setUser({ ...user, name: '张三' });

// 数组同理
const [list, setList] = useState([]);
setList([...list, newItem]);

6. 处理副作用:useEffect Hook

useEffect 让你在组件渲染后执行副作用操作(如数据获取、订阅、手动修改 DOM 等)。

6.1 基本用法

import { useState, useEffect } from 'react';

function Timer() {
  const [seconds, setSeconds] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      setSeconds(s => s + 1);
    }, 1000);

    // 清理函数:组件卸载或依赖变化时执行
    return () => clearInterval(interval);
  }, []); // 空依赖数组 → 只在挂载时运行一次

  return <div>运行时间{seconds} 秒</div>;
}
  • 第一个参数是回调函数,在 DOM 更新后执行。
  • 第二个参数是 依赖数组
    • 若不传,每次渲染后都执行(少用)。
    • 空数组 [],仅在首次渲染(挂载)时执行一次。
    • 传入特定值 [count],仅在 count 变化时执行。

6.2 常见场景:数据请求

function UserList() {
  const [users, setUsers] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    async function fetchUsers() {
      try {
        const res = await fetch('https://jsonplaceholder.typicode.com/users');
        const data = await res.json();
        setUsers(data);
      } catch (error) {
        console.error('请求失败', error);
      } finally {
        setLoading(false);
      }
    }
    fetchUsers();
  }, []);

  if (loading) return <p>加载中...</p>;

  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

7. 实战项目:任务待办清单

我们将综合运用组件、Props、useState 和 useEffect 构建一个简单的 Todo 应用。

7.1 应用结构

  • App:主组件,管理任务列表状态。
  • AddTodo:输入框与添加按钮。
  • TodoList:展示任务列表。
  • TodoItem:单个任务,支持完成状态切换和删除。

7.2 完整代码

// App.jsx
import { useState } from 'react';
import AddTodo from './AddTodo';
import TodoList from './TodoList';

function App() {
  const [todos, setTodos] = useState([]);

  const addTodo = (text) => {
    const newTodo = {
      id: Date.now(),
      text,
      completed: false,
    };
    setTodos([...todos, newTodo]);
  };

  const toggleTodo = (id) => {
    setTodos(todos.map(todo =>
      todo.id === id ? { ...todo, completed: !todo.completed } : todo
    ));
  };

  const deleteTodo = (id) => {
    setTodos(todos.filter(todo => todo.id !== id));
  };

  return (
    <div style={{ maxWidth: 400, margin: '0 auto' }}>
      <h1>待办事项</h1>
      <AddTodo onAdd={addTodo} />
      <TodoList
        todos={todos}
        onToggle={toggleTodo}
        onDelete={deleteTodo}
      />
    </div>
  );
}

export default App;
// AddTodo.jsx
import { useState } from 'react';

export default function AddTodo({ onAdd }) {
  const [text, setText] = useState('');

  const handleSubmit = (e) => {
    e.preventDefault();
    if (text.trim()) {
      onAdd(text.trim());
      setText('');
    }
  };

  return (
    <form onSubmit={handleSubmit} style={{ marginBottom: 16 }}>
      <input
        type="text"
        value={text}
        onChange={(e) => setText(e.target.value)}
        placeholder="输入新任务..."
      />
      <button type="submit">添加</button>
    </form>
  );
}
// TodoList.jsx
import TodoItem from './TodoItem';

export default function TodoList({ todos, onToggle, onDelete }) {
  if (todos.length === 0) return <p>暂无任务</p>;

  return (
    <ul>
      {todos.map(todo => (
        <TodoItem
          key={todo.id}
          todo={todo}
          onToggle={onToggle}
          onDelete={onDelete}
        />
      ))}
    </ul>
  );
}
// TodoItem.jsx
export default function TodoItem({ todo, onToggle, onDelete }) {
  return (
    <li
      style={{
        textDecoration: todo.completed ? 'line-through' : 'none',
        cursor: 'pointer',
        marginBottom: 8,
      }}
    >
      <span onClick={() => onToggle(todo.id)}>{todo.text}</span>
      <button
        onClick={() => onDelete(todo.id)}
        style={{ marginLeft: 12 }}
      >
        删除
      </button>
    </li>
  );
}

运行项目后,你可以添加任务、标记完成和删除任务。所有状态管理都集中在 App 组件中,子组件通过 Props 呈现和回调通信。

8. 进阶方向建议

掌握上述基础后,你可以进一步探索:

  • useReducer:复杂状态逻辑管理。
  • useContext:跨组件共享数据(避免 Props 层层传递)。
  • 自定义 Hook:封装可复用的状态逻辑。
  • React Router:单页应用路由。
  • 状态管理库:Redux、Zustand 等。
  • 性能优化:React.memo、useMemo、useCallback。

9. 总结

通过这篇教程,你应当理解了 React 的核心概念:

  • 组件 是 UI 的积木块,通过 Props 传递数据。
  • useState 为组件添加可交互的状态。
  • useEffect 管理渲染之外的副作用操作。

实战中的 Todo 应用完整展示了这几部分如何协同工作。React 的世界远不止于此,但坚实的组件、状态与 Hooks 基础是建造任何复杂应用的基石。继续实践,不断构建项目,你的 React 技能会日益精进。