1、分割 render 函数
示例1:
class Panel extends React.Component {
renderHeading() {
// ...
}
renderBody() {
// ...
}
render() {
return (
<div>
{this.renderHeading()}
{this.renderBody()}
</div>
);
}
}示例2:
const PanelHeader = (props) => (
// ...
);
const PanelBody = (props) => (
// ...
);
class Panel extends React.Component {
render() {
return (
<div>
<PanelHeader title={this.props.title}/>
<PanelBody content={this.props.content}/>
</div>
);
}
}2、用 props 传递元素
示例:
// 子组件
class CommentTemplate extends React.Component {
static propTypes = {
metadata: PropTypes.node,
actions: PropTypes.node,
};
render() {
return (
<div>
<CommentHeading>
<Avatar user={...}/>
<span>{this.props.metadata}</span>
</CommentHeading>
<CommentBody/>
<CommentFooter>
<Timestamp time={...}/>
<span>{this.props.actions}</span>
</CommentFooter>
</div>
);
}
}
// 父组件
class Comment extends React.Component {
render() {
const metadata = this.props.publishTime ? <PublishTime time={this.props.publishTime} /> : <span>Saving...</span>;
const actions = [];
if (this.props.isSignedIn) {
actions.push(<LikeAction />);
actions.push(<ReplyAction />);
}
if (this.props.isAuthor) {
actions.push(<DeleteAction />);
}
return <CommentTemplate metadata={metadata} actions={actions} />;
}
}3、使用高阶组件
示例:
// 高阶组件
const withLinkAnalytics = (mapPropsToData, WrappedComponent) => {
class LinkAnalyticsWrapper extends React.Component {
componentDidMount() {
ReactDOM.findDOMNode(this).addEventListener('click', this.onClick);
}
componentWillUnmount() {
ReactDOM.findDOMNode(this).removeEventListener('click', this.onClick);
}
onClick = (e) => {
if (e.target.tagName === 'A') {
const data = mapPropsToData ? mapPropsToData(this.props) : {};
sendAnalytics('link clicked', data);
}
};
render() {
return <WrappedComponent {...this.props} />;
}
}
return LinkAnalyticsWrapper;
};
// 普通组件
class Document extends React.Component {
componentDidMount() {
ReactDOM.findDOMNode(this).addEventListener('click', this.onClick);
}
componentWillUnmount() {
ReactDOM.findDOMNode(this).removeEventListener('click', this.onClick);
}
onClick = (e) => {
if (e.target.tagName === 'A') {
sendAnalytics('link clicked', {
documentId: this.props.documentId
});
}
};
render() {
// ...
}
}
// 使用高阶组件
export default withLinkAnalytics((props) => ({
documentId: props.documentId
}), Document);4、巧妙利用children()传值
示例:
// Query.js
export default class QueryRenderer extends Component {
// .......
render() {
const { data, children } = this.props;
return children ? children(data) : null;
}
}
// 使用
import Query from './Query.js';
<Query name="listMetrics" fetch={this.listMetrics} params={{ productId }}>
{({ data }) => {
// ......
return (
<MyComponent data={data} />
);
}}
</Query>