React Props 完整使用指南
1. 类组件中的 Props
1.1 基本使用
// 父组件
class ParentComponent extends React.Component {
render() {
return (
<ChildComponent
name="John"
age={25}
isStudent={true}
hobbies={['reading', 'swimming']}
/>
);
}
}
// 子组件
class ChildComponent extends React.Component {
render() {
const { name, age, isStudent, hobbies } = this.props;
return (
<div>
<h2>Name: {name}</h2>
<p>Age: {age}</p>
<p>Is Student: {isStudent ? 'Yes' : 'No'}</p>
<ul>
{hobbies.map(hobby => (
<li key={hobby}>{hobby}</li>
))}
</ul>
</div>
);
}
}
1.2 默认 Props
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
Welcome.defaultProps = {
name: 'Guest'
};
// 或者使用静态属性
class Welcome extends React.Component {
static defaultProps = {
name: 'Guest'
};
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
1.3 Props 类型检查
import PropTypes from 'prop-types';
class User extends React.Component {
render() {
return (
<div>
<h1>{this.props.name}</h1>
<p>Age: {this.props.age}</p>
</div>
);
}
}
User.propTypes = {
name: PropTypes.string.isRequired,
age: PropTypes.number,
email: PropTypes.string,
friends: PropTypes.arrayOf(PropTypes.string),
address: PropTypes.shape({
street: PropTypes.string,
city: PropTypes.string
})
};
1.4 Props 作为方法传递
class ParentComponent extends React.Component {
handleClick = (data) => {
console.log('Clicked:', data);
}
render() {
return <ChildComponent onClick={this.handleClick} />;
}
}
class ChildComponent extends React.Component {
render() {
return (
<button onClick={() => this.props.onClick('Hello')}>
Click me
</button>
);
}
}
2. 函数组件中的 Props
2.1 基本使用
// 解构方式接收 props
function Welcome({ name, age }) {
return (
<div>
<h1>Hello, {name}</h1>
<p>Age: {age}</p>
</div>
);
}
// 直接接收 props 对象
function Welcome(props) {
return (
<div>
<h1>Hello, {props.name}</h1>
<p>Age: {props.age}</p>
</div>
);
}
// 使用组件
function App() {
return <Welcome name="John" age={25} />;
}
2.2 默认 Props
// 使用默认参数
function Welcome({ name = 'Guest' }) {
return <h1>Hello, {name}</h1>;
}
// 或者使用 defaultProps
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
Welcome.defaultProps = {
name: 'Guest'
};
2.3 Props 类型检查
import PropTypes from 'prop-types';
function User({ name, age, email, friends, address }) {
return (
<div>
<h1>{name}</h1>
<p>Age: {age}</p>
<p>Email: {email}</p>
<ul>
{friends.map(friend => (
<li key={friend}>{friend}</li>
))}
</ul>
<p>
Address: {address.street}, {address.city}
</p>
</div>
);
}
User.propTypes = {
name: PropTypes.string.isRequired,
age: PropTypes.number,
email: PropTypes.string,
friends: PropTypes.arrayOf(PropTypes.string),
address: PropTypes.shape({
street: PropTypes.string,
city: PropTypes.string
})
};
2.4 Props 作为回调函数
function ParentComponent() {
const handleClick = (data) => {
console.log('Clicked:', data);
};
return <ChildComponent onClick={handleClick} />;
}
function ChildComponent({ onClick }) {
return (
<button onClick={() => onClick('Hello')}>
Click me
</button>
);
}
3. Props 高级用法
3.1 Children Props
// 类组件
class Container extends React.Component {
render() {
return (
<div className="container">
{this.props.children}
</div>
);
}
}
// 函数组件
function Container({ children }) {
return (
<div className="container">
{children}
</div>
);
}
// 使用
function App() {
return (
<Container>
<h1>Title</h1>
<p>Content</p>
</Container>
);
}
3.2 Render Props
class MouseTracker extends React.Component {
state = { x: 0, y: 0 };
handleMouseMove = (event) => {
this.setState({
x: event.clientX,
y: event.clientY
});
};
render() {
return (
<div onMouseMove={this.handleMouseMove}>
{this.props.render(this.state)}
</div>
);
}
}
// 使用
function App() {
return (
<MouseTracker
render={({ x, y }) => (
<h1>鼠标位置: {x}, {y}</h1>
)}
/>
);
}
3.3 Props 转发
// 使用 React.forwardRef
const FancyButton = React.forwardRef((props, ref) => (
<button ref={ref} className="fancy-button">
{props.children}
</button>
));
// 使用组件
function App() {
const buttonRef = React.useRef();
return <FancyButton ref={buttonRef}>Click me!</FancyButton>;
}
4. Props 最佳实践
4.1 命名约定
- 使用驼峰命名法
- 布尔值 props 使用 is/has 前缀
- 事件处理函数使用 handle/on 前缀
function UserProfile({
isActive,
hasPermission,
onNameChange,
handleSubmit
}) {
// ...
}
4.2 解构和默认值
function UserCard({
name = 'Guest',
age = 0,
avatar = 'default.png',
...otherProps
}) {
return (
<div {...otherProps}>
<img src={avatar} alt={name} />
<h2>{name}</h2>
<p>Age: {age}</p>
</div>
);
}
4.3 TypeScript 中的 Props
interface UserProps {
name: string;
age: number;
email?: string;
onUpdate: (id: number) => void;
}
// 函数组件
function User({ name, age, email, onUpdate }: UserProps) {
return (
<div>
<h1>{name}</h1>
<p>Age: {age}</p>
{email && <p>Email: {email}</p>}
<button onClick={() => onUpdate(1)}>Update</button>
</div>
);
}
// 类组件
class User extends React.Component<UserProps> {
render() {
const { name, age, email, onUpdate } = this.props;
return (
<div>
<h1>{name}</h1>
<p>Age: {age}</p>
{email && <p>Email: {email}</p>}
<button onClick={() => onUpdate(1)}>Update</button>
</div>
);
}
}
5. 性能优化
5.1 React.memo
const MemoizedComponent = React.memo(function MyComponent(props) {
// 只在 props 改变时重新渲染
return (
<div>{props.value}</div>
);
});
5.2 shouldComponentUpdate
class OptimizedComponent extends React.Component {
shouldComponentUpdate(nextProps) {
return this.props.value !== nextProps.value;
}
render() {
return <div>{this.props.value}</div>;
}
}
6. 总结
Props 使用要点:
- 保持单向数据流
- 适当使用 PropTypes 或 TypeScript 进行类型检查
- 合理设置默认值
- 注意性能优化
- 遵循命名约定
- 使用解构提高代码可读性
选择类组件还是函数组件时考虑:
- 项目需求和复杂度
- 团队熟悉度
- 性能要求
- 代码可维护性
- 是否需要使用生命周期方法