引言:掌握Props与State,解锁React开发精髓
在React开发中,Props和State是两个最核心、最基础的概念,它们构成了React组件间通信和状态管理的基石。准确理解这两者的区别与联系,是成为一名优秀React开发者的必经之路。
开发者痛点:很多初学者常常混淆Props和State的使用场景,导致组件设计不合理、数据流混乱,甚至引发难以调试的bug。本文将深入剖析两者的本质区别,通过实际案例帮助你建立清晰的使用思维模型。
01|Props:组件间的信使
Props的本质特征
Props(Properties的缩写)是React组件的只读属性,它们从父组件传递到子组件,构成了React单向数据流的基础。
// 父组件传递props
function ParentComponent() {
return <ChildComponent name="张三" age={25} hobbies={['coding', 'reading']} />;
}
// 子组件接收props
function ChildComponent(props) {
// Props是只读的,不能直接修改
// props.name = "李四"; // ❌ 错误:不能修改props
return <div>姓名:{props.name},年龄:{props.age}</div>;
}Props的核心特点
- 单向数据流:数据只能从父组件流向子组件
- 只读性:子组件不能修改接收到的props
- 可验证性:通过PropTypes进行类型检查
- 默认值支持:可为props设置默认值
import PropTypes from 'prop-types';
function UserCard({ name, age, avatar = 'default-avatar.jpg' }) {
return (
<div className="user-card">
<img src={avatar} alt={name} />
<h3>{name}</h3>
<p>年龄:{age}</p>
</div>
);
}
UserCard.propTypes = {
name: PropTypes.string.isRequired,
age: PropTypes.number.isRequired,
avatar: PropTypes.string
};02|State:组件的记忆
State的本质特征
State是组件的私有状态,它属于组件自身,可以被组件自由修改。State的变化会触发组件的重新渲染。
import { useState } from 'react';
function Counter() {
// State:组件的内部状态
const [count, setCount] = useState(0);
const increment = () => {
// State可以被修改
setCount(count + 1); // ✅ 正确:使用setter函数修改state
};
return (
<div>
<p>当前计 数:{count}</p>
<button onClick={increment}>增加</button>
</div>
);
}State的核心特点
- 私有性:State只属于当前组件
- 可变性:可以通过setter函数修改state
- 异步更新:setState是异步操作
- 触发重渲染:state变化会导致组件重新渲染
function TodoList() {
const [todos, setTodos] = useState([]);
const [inputValue, setInputValue] = useState('');
const addTodo = () => {
if (inputValue.trim()) {
// 使用函数式更新确保状态正确性
setTodos(prevTodos => [...prevTodos, {
id: Date.now(),
text: inputValue,
completed: false
}]);
setInputValue('');
}
};
const toggleTodo = (id) => {
setTodos(prevTodos =>
prevTodos.map(todo =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
)
);
};
return (
<div>
<input
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
placeholder="添加待办事项"
/>
<button onClick={addTodo}>添加</button>
<ul>
{todos.map(todo => (
<li key={todo.id} onClick={() => toggleTodo(todo.id)}>
<span style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}>
{todo.text}
</span>
</li>
))}
</ul>
</div>
);
}