返回教程列表
教程 React 快速入门 第 3 节
进阶
20 分钟

Props 和 State

理解 React 中的数据流,掌握 props 和 state 的使用

CodeGogo

Props 和 State 概述

React 组件通过 props(属性)和 state(状态)来管理和传递数据。理解它们的区别是掌握 React 的关键。

Props(属性)

Props 是什么

Props 是从父组件传递给子组件的数据。Props 是只读的,子组件不能修改接收到的 props。

传递 Props

// 父组件
function App() {
  const userData = {
    name: '张三',
    age: 25,
    city: '北京'
  };

  return (
    <UserProfile
      name={userData.name}
      age={userData.age}
      city={userData.city}
    />
  );
}

// 子组件
function UserProfile({ name, age, city }) {
  return (
    <div>
      <h2>用户信息</h2>
      <p>姓名:{name}</p>
      <p>年龄:{age}</p>
      <p>城市:{city}</p>
    </div>
  );
}

Props 的默认值

function Button({ label, type = 'button', disabled = false }) {
  return (
    <button type={type} disabled={disabled}>
      {label}
    </button>
  );
}

// 使用
<Button label="提交" />
<Button label="禁用按钮" disabled={true} />

Props 验证(PropTypes)

import PropTypes from 'prop-types';

function UserProfile({ name, age, city }) {
  return (
    <div>
      <h2>{name}</h2>
      <p>{age}岁</p>
      <p>来自{city}</p>
    </div>
  );
}

UserProfile.propTypes = {
  name: PropTypes.string.isRequired,
  age: PropTypes.number,
  city: PropTypes.string
};

UserProfile.defaultProps = {
  age: 18,
  city: '未知'
};

State(状态)

State 是什么

State 是组件内部管理的动态数据。当 state 改变时,组件会重新渲染。

使用 useState Hook

import { useState } from 'react';

function Counter() {
  // 声明一个叫 count 的 state 变量,初始值为 0
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>你点击了 {count} 次</p>
      <button onClick={() => setCount(count + 1)}>
        点击我
      </button>
    </div>
  );
}

多个 State 变量

function UserForm() {
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  const [age, setAge] = useState(18);

  const handleSubmit = () => {
    console.log({ name, email, age });
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        value={name}
        onChange={(e) => setName(e.target.value)}
        placeholder="姓名"
      />
      <input
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        placeholder="邮箱"
      />
      <input
        type="number"
        value={age}
        onChange={(e) => setAge(Number(e.target.value))}
      />
      <button type="submit">提交</button>
    </form>
  );
}

Props vs State

特性PropsState
来源从父组件接收组件内部管理
可变性只读(不能修改)可变(可以修改)
作用域父组件控制组件内部控制
用途传递数据、回调管理组件内部状态

数据流

单向数据流

React 遵循单向数据流原则:数据只能从父组件流向子组件。

// 父组件
function Parent() {
  const [message, setMessage] = useState('Hello from Parent');

  return (
    <div>
      <Child message={message} onUpdate={setMessage} />
    </div>
  );
}

// 子组件
function Child({ message, onUpdate }) {
  return (
    <div>
      <p>{message}</p>
      <button onClick={() => onUpdate('Updated from Child')}>
        更新消息
      </button>
    </div>
  );
}

状态提升

当多个组件需要共享状态时,将状态提升到它们最近的共同父组件。

// 状态提升前(不好)
function CelsiusInput({ value, onChange }) {
  return (
    <fieldset>
      <legend>摄氏度</legend>
      <input
        value={value}
        onChange={(e) => onChange(e.target.value)}
      />
    </fieldset>
  );
}

function FahrenheitInput({ value, onChange }) {
  return (
    <fieldset>
      <legend>华氏度</legend>
      <input
        value={value}
        onChange={(e) => onChange(e.target.value)}
      />
    </fieldset>
  );
}

// 状态提升后(好)
function TemperatureCalculator() {
  const [temperature, setTemperature] = useState('');
  const [scale, setScale] = useState('c');

  const handleCelsiusChange = (value) => {
    setTemperature(value);
    setScale('c');
  };

  const handleFahrenheitChange = (value) => {
    setTemperature(value);
    setScale('f');
  };

  const celsius =
    scale === 'f' ? tryConvert(temperature, toCelsius) : temperature;
  const fahrenheit =
    scale === 'c' ? tryConvert(temperature, toFahrenheit) : temperature;

  return (
    <div>
      <CelsiusInput
        value={celsius}
        onChange={handleCelsiusChange}
      />
      <FahrenheitInput
        value={fahrenheit}
        onChange={handleFahrenheitChange}
      />
    </div>
  );
}

💡 最佳实践

  1. Props 命名清晰:使用有意义的 prop 名称
  2. 避免过度提升状态:只在需要共享时才提升
  3. 保持 state 简单:避免冗余的 state
  4. 使用默认值:为可选 props 提供合理的默认值

🎯 练习

  1. 创建一个用户信息卡片组件,使用 props 传递数据
  2. 实现一个计数器组件,使用 state 管理计数
  3. 创建一个待办事项列表,练习状态提升

下一节我们将学习 组件生命周期和 useEffect Hook

觉得这个教程有帮助?

继续学习更多教程,掌握编程技能

查看更多教程