在 React 中,state 和 props 是管理数据的两个核心概念,它们都用于控制组件的渲染,但在来源、可变性、作用范围和使用场景上有本质区别。
核心区别速查表
| 特性 | state | props |
|---|---|---|
| 来源 | 组件内部定义和管理 | 由父组件传递 |
| 可变性 | ✅ 可变(通过 setState / useState) | ❌ 不可变(只读) |
| 作用范围 | 组件自身的状态 | 组件的输入(类似函数参数) |
| 初始化 | 在组件内部设置初始值 | 由父组件在使用时提供 |
| 更新方式 | 调用 setState 或状态更新函数 | 父组件重新渲染并传递新 props |
| 主要用途 | 存储会变化的数据(如用户输入、计数器) | 配置组件、传递数据和回调函数 |
1. props:组件的“输入”或“配置”
props(properties 的缩写)是父组件传递给子组件的数据,类似于函数的参数。
特点:
- 只读性:子组件不能直接修改
props。如果尝试修改,React 会报错(在开发模式下)。 - 单向流动:数据从父组件流向子组件。
- 传递函数:父组件可以将函数作为
props传递给子组件,实现“子组件通知父组件”的通信。
示例:
// 子组件:接收 props
function Welcome(props) {
// ❌ 错误:不要这样做
// props.name = 'Bob'; // React 会警告
return <h1>Hello, {props.name}</h1>;
}
// 父组件:传递 props
function App() {
return <Welcome name="Alice" />;
}
2. state:组件的“私有记忆”
state 是组件内部的状态,用于存储那些会随时间变化的数据。它是组件“记忆”过去事件(如用户交互)的方式。
特点:
- 可变性:组件可以通过特定方法(如
setState或useState的更新函数)来修改自己的state。 - 私有性:
state是组件私有的,其他组件无法直接访问或修改。 - 触发更新:当
state改变时,组件会自动重新渲染。
示例(类组件):
class Counter extends React.Component {
constructor(props) {
super(props);
// 初始化 state
this.state = { count: 0 };
}
render() {
return (
<div>
<p>计数: {this.state.count}</p>
{/* 调用 setState 更新 state */}
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
增加
</button>
</div>
);
}
}
示例(函数组件 + Hooks):
import React, { useState } from 'react';
function Counter() {
// 使用 useState Hook 声明 state
const [count, setCount] = useState(0);
return (
<div>
<p>计数: {count}</p>
{/* 调用 setCount 更新 state */}
<button onClick={() => setCount(count + 1)}>
增加
</button>
</div>
);
}
3. props 和 state 的协同工作
它们通常一起工作,形成 React 的数据流。
经典模式:状态提升 (Lifting State Up)
当多个组件需要共享状态时,将状态提升到它们最近的共同父组件中管理。
// 子组件:接收 value 和 onChange 作为 props
function InputField({ value, onChange, label }) {
return (
<div>
<label>{label}</label>
<input value={value} onChange={onChange} />
</div>
);
}
// 父组件:管理 state,并通过 props 传递给子组件
function Form() {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
return (
<form>
{/* 父组件的 state 作为 props 传给子组件 */}
<InputField
label="姓名"
value={name}
// 传递回调函数,子组件调用时更新父组件的 state
onChange={(e) => setName(e.target.value)}
/>
<InputField
label="邮箱"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</form>
);
}
在这个例子中:
Form组件的state(name,email)存储了表单数据。- 这些
state通过props传递给InputField组件进行显示。 InputField组件通过props中的onChange回调函数“通知”Form组件更新其state。
总结
| 比喻 | props | state |
|---|---|---|
| 类比 | 函数的参数 | 类的成员变量 |
| 控制权 | 由父组件控制 | 由组件自身控制 |
| 变化驱动 | 父组件重新渲染 | 组件内部事件(点击、输入等) |
| 生命周期 | 每次父组件渲染都可能变化 | 仅在 setState 被调用时变化 |
一句话概括:
props是组件的输入(从外部来),state是组件的记忆(在内部存)。props决定组件的配置,state决定组件的动态行为。
THE END


