Skip to content

React 组件基础

组件是 React 的核心概念之一,它允许我们将 UI 拆分为独立、可复用的部分。本章节将介绍 React 组件的基本概念和使用方法。

6.1 什么是组件?

组件的定义

组件是 React 应用的基本构建块,它是一个可以接收输入(props)并返回 React 元素的函数或类。

组件的作用

  • 代码复用:可以在多个地方使用同一个组件
  • 逻辑封装:将相关的 UI 和逻辑封装在一起
  • 可维护性:使代码结构更清晰,易于维护
  • 可测试性:便于单元测试

组件的优势

  • 模块化:每个组件都有明确的职责
  • 可组合性:组件可以嵌套和组合
  • 可重用性:可以在不同的项目中使用

6.2 组件的两种类型

函数组件(推荐)

函数组件是 React 16.8+ 推荐的组件类型,它是一个简单的 JavaScript 函数,接收 props 作为参数并返回 React 元素。

jsx
// 函数组件
function Greeting({ name }) {
  return <h1>Hello, {name}!</h1>;
}

类组件

类组件是传统的组件类型,它是一个继承自 React.Component 的 JavaScript 类。

jsx
// 类组件
class Greeting extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}!</h1>;
  }
}

新手建议

  • 优先使用函数组件:函数组件更简洁,易于理解和测试
  • 了解类组件:在维护旧项目时可能会遇到类组件

6.3 组件的定义、导入与使用

定义组件

jsx
// src/components/Greeting.jsx
function Greeting({ name }) {
  return <h1>Hello, {name}!</h1>;
}

export default Greeting;

导入组件

jsx
// src/App.jsx
import Greeting from './components/Greeting';

function App() {
  return (
    <div>
      <Greeting name="React" />
    </div>
  );
}

export default App;

使用组件

jsx
// 基本使用
<Greeting name="React" />

// 嵌套使用
function App() {
  return (
    <div>
      <Header>
        <Greeting name="React" />
      </Header>
    </div>
  );
}

6.4 组件 props

props 的传递与接收

传递 props

jsx
<Greeting name="React" age={10} isActive={true} />

接收 props

jsx
// 解构赋值
function Greeting({ name, age, isActive }) {
  return (
    <div>
      <h1>Hello, {name}!</h1>
      <p>年龄:{age}</p>
      <p>状态:{isActive ? '活跃' : '非活跃'}</p>
    </div>
  );
}

// 传统方式
function Greeting(props) {
  return (
    <div>
      <h1>Hello, {props.name}!</h1>
      <p>年龄:{props.age}</p>
      <p>状态:{props.isActive ? '活跃' : '非活跃'}</p>
    </div>
  );
}

props 类型限制

使用 PropTypes 来限制 props 的类型:

jsx
import PropTypes from 'prop-types';

function Greeting({ name, age, isActive }) {
  return (
    <div>
      <h1>Hello, {name}!</h1>
      <p>年龄:{age}</p>
      <p>状态:{isActive ? '活跃' : '非活跃'}</p>
    </div>
  );
}

Greeting.propTypes = {
  name: PropTypes.string.isRequired,
  age: PropTypes.number,
  isActive: PropTypes.bool
};

export default Greeting;

props 默认值设置

jsx
function Greeting({ name, age = 10, isActive = true }) {
  return (
    <div>
      <h1>Hello, {name}!</h1>
      <p>年龄:{age}</p>
      <p>状态:{isActive ? '活跃' : '非活跃'}</p>
    </div>
  );
}

// 或使用 defaultProps
Greeting.defaultProps = {
  age: 10,
  isActive: true
};

props 不可修改原则

重要原则:props 是只读的,不能在组件内部修改 props。

jsx
// 错误
function Greeting({ name }) {
  name = 'Modified'; // 不能修改 props
  return <h1>Hello, {name}!</h1>;
}

// 正确
function Greeting({ name }) {
  const modifiedName = `Hello, ${name}!`;
  return <h1>{modifiedName}</h1>;
}

6.5 组件状态

useState Hook

useState 是 React 提供的一个 Hook,用于在函数组件中管理状态。

基本使用

jsx
import { useState } from 'react';

function Counter() {
  // 声明一个名为 count 的状态变量,初始值为 0
  // setCount 是更新 count 的函数
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>计数:{count}</p>
      <button onClick={() => setCount(count + 1)}>增加</button>
      <button onClick={() => setCount(count - 1)}>减少</button>
      <button onClick={() => setCount(0)}>重置</button>
    </div>
  );
}

状态修改的注意事项

  • 不能直接修改状态:必须使用 setter 函数
  • 状态更新是异步的:React 可能会批量更新状态
  • 状态更新会触发组件重新渲染
jsx
// 错误
function Counter() {
  const [count, setCount] = useState(0);

  function increment() {
    count++; // 直接修改状态,不会触发重新渲染
  }

  return (
    <div>
      <p>计数:{count}</p>
      <button onClick={increment}>增加</button>
    </div>
  );
}

// 正确
function Counter() {
  const [count, setCount] = useState(0);

  function increment() {
    setCount(count + 1); // 使用 setter 函数
  }

  return (
    <div>
      <p>计数:{count}</p>
      <button onClick={increment}>增加</button>
    </div>
  );
}

复杂状态管理

对象类型状态

jsx
import { useState } from 'react';

function UserProfile() {
  const [user, setUser] = useState({
    name: '张三',
    age: 20,
    email: 'zhangsan@example.com'
  });

  function updateName(name) {
    setUser(prevUser => ({
      ...prevUser,
      name
    }));
  }

  return (
    <div>
      <h1>{user.name}</h1>
      <p>年龄:{user.age}</p>
      <p>邮箱:{user.email}</p>
      <input
        type="text"
        value={user.name}
        onChange={e => updateName(e.target.value)}
      />
    </div>
  );
}

数组类型状态

jsx
import { useState } from 'react';

function TodoList() {
  const [todos, setTodos] = useState(['学习 React', '练习编程', '阅读文档']);
  const [inputValue, setInputValue] = useState('');

  function addTodo() {
    if (inputValue) {
      setTodos(prevTodos => [...prevTodos, inputValue]);
      setInputValue('');
    }
  }

  function removeTodo(index) {
    setTodos(prevTodos => prevTodos.filter((_, i) => i !== index));
  }

  return (
    <div>
      <input
        type="text"
        value={inputValue}
        onChange={e => setInputValue(e.target.value)}
      />
      <button onClick={addTodo}>添加</button>
      <ul>
        {todos.map((todo, index) => (
          <li key={index}>
            {todo}
            <button onClick={() => removeTodo(index)}>删除</button>
          </li>
        ))}
      </ul>
    </div>
  );
}

实战练习

练习1:基本组件

jsx
// src/components/Button.jsx
function Button({ text, onClick, className }) {
  return (
    <button className={className} onClick={onClick}>
      {text}
    </button>
  );
}

Button.propTypes = {
  text: PropTypes.string.isRequired,
  onClick: PropTypes.func,
  className: PropTypes.string
};

export default Button;

// 使用
import Button from './components/Button';

function App() {
  function handleClick() {
    console.log('Button clicked!');
  }

  return (
    <div>
      <Button text="点击我" onClick={handleClick} className="primary" />
    </div>
  );
}

练习2:状态管理

jsx
import { useState } from 'react';

function Toggle() {
  const [isOn, setIsOn] = useState(false);

  return (
    <div>
      <p>状态:{isOn ? '开' : '关'}</p>
      <button onClick={() => setIsOn(!isOn)}>
        {isOn ? '关闭' : '打开'}
      </button>
    </div>
  );
}

练习3:复杂状态

jsx
import { useState } from 'react';

function Form() {
  const [formData, setFormData] = useState({
    name: '',
    email: '',
    password: ''
  });

  function handleChange(e) {
    const { name, value } = e.target;
    setFormData(prevData => ({
      ...prevData,
      [name]: value
    }));
  }

  function handleSubmit(e) {
    e.preventDefault();
    console.log('表单数据:', formData);
  }

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label>姓名:</label>
        <input
          type="text"
          name="name"
          value={formData.name}
          onChange={handleChange}
        />
      </div>
      <div>
        <label>邮箱:</label>
        <input
          type="email"
          name="email"
          value={formData.email}
          onChange={handleChange}
        />
      </div>
      <div>
        <label>密码:</label>
        <input
          type="password"
          name="password"
          value={formData.password}
          onChange={handleChange}
        />
      </div>
      <button type="submit">提交</button>
    </form>
  );
}

通过本章节的学习,你已经掌握了 React 组件的基本概念和使用方法。组件是 React 开发的核心,掌握好组件的使用对于学习 React 至关重要。

© 2026 编程马·菜鸟教程 版权所有