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 (<MouseTrackerrender={({ 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 进行类型检查
- 合理设置默认值
- 注意性能优化
- 遵循命名约定
- 使用解构提高代码可读性
选择类组件还是函数组件时考虑:
- 项目需求和复杂度
- 团队熟悉度
- 性能要求
- 代码可维护性
- 是否需要使用生命周期方法