const EnhancedComponent = higherOrderComponent(WrappedComponent);
class CommentList extends React.Component {constructor(props) {super(props);this.handleChange = this.handleChange.bind(this);this.state = {// 假设 "DataSource" 是个全局范围内的数据源变量,来自外部,自身带有很多方法comments: DataSource.getComments() //假设getComments()这个方法可以获取所有的评论};}componentDidMount() {// 订阅更改;监听 DataSource ,发生变化时更新数据DataSource.addChangeListener(this.handleChange);}componentWillUnmount() {// 清除订阅DataSource.removeChangeListener(this.handleChange);}handleChange() {// 当数据源更新时,更新组件状态this.setState({comments: DataSource.getComments() //假设getComments()这个方法可以获取所有的评论});}render() {return ({this.state.comments.map((comment) => (comment} key={comment.id} />))} );}}// 假设 DataSource:来自外部;它自身有很多方法,如:getComments(),addChangeListener,removeChangeListener 等
// 假设 是子组件,父组件 CommentList 需要将 comment 、key 传递给它
class BlogPost extends React.Component {constructor(props) {super(props);this.handleChange = this.handleChange.bind(this);this.state = {blogPost: DataSource.getBlogPost(props.id)};}componentDidMount() {DataSource.addChangeListener(this.handleChange);}componentWillUnmount() {DataSource.removeChangeListener(this.handleChange);}handleChange() {this.setState({blogPost: DataSource.getBlogPost(this.props.id)});}render() {return this.state.blogPost} />;}
}
const CommentListWithSubscription = withSubscription(CommentList,(DataSource) => DataSource.getComments());const BlogPostWithSubscription = withSubscription(BlogPost,(DataSource, props) => DataSource.getBlogPost(props.id));
//以上写法相当于高级组件的调用,withSubscription为自定义的高阶组件;CommentList:被包装的子组件;CommentListWithSubscription:返回的包装后的组件
// 此函数接收一个组件...
function withSubscription(WrappedComponent, selectData) {// ...并返回另一个组件...return class extends React.Component {constructor(props) {super(props);this.handleChange = this.handleChange.bind(this);this.state = {data: selectData(DataSource, props)};}componentDidMount() {// ...负责订阅相关的操作...DataSource.addChangeListener(this.handleChange);}componentWillUnmount() {DataSource.removeChangeListener(this.handleChange);}handleChange() {this.setState({data: selectData(DataSource, this.props)});}render() {// ... 并使用新数据渲染被包装的组件!// 请注意,我们可能还会传递其他属性return this.state.data} {...this.props} />;}};
}
function logProps(InputComponent) {InputComponent.prototype.componentDidUpdate = function(prevProps) {console.log('Current props: ', this.props);console.log('Previous props: ', prevProps);};// 返回原始的 input 组件,暗示它已经被修改。return InputComponent;
}// 每次调用 logProps 时,增强组件都会有 log 输出。
const EnhancedComponent = logProps(InputComponent)//上面这种写法会造成另一个同样会修改componentDidUpate的HOC增强它,那么前面的HOC就会失效。
function logProps(WrappedComponent) {return class extends React.Component {componentDidUpdate(prevProps) {console.log('Current props: ', this.props);console.log('Previous props: ', prevProps);}render() {// 将 input 组件包装在容器中,而不对其进行修改。Good!return ...this.props} />;}}}
render() {// 过滤掉非此 HOC 额外的 props,且不要进行透传const { extraProp, ...passThroughProps } = this.props;// 将 props 注入到被包装的组件中。// 通常为 state 的值或者实例方法。const injectedProp = someStateOrInstanceMethod;// 将 props 传递给被包装组件return (injectedProp}{...passThroughProps}/>);
}
const NavbarWithRouter = withRouter(Navbar);
const CommentWithRelay = Relay.createContainer(Comment, config);
// React Redux 的 `connect` 函数
const ConnectedComment = connect(commentSelector, commentActions)(CommentList);
// connect 是一个函数,它的返回值为另外一个函数。const enhance = connect(commentListSelector, commentListActions)// 返回值为 HOC,它会返回已经连接 Redux store 的组件const ConnectedComment = enhance(CommentList);
function withSubscription(WrappedComponent) {class WithSubscription extends React.Component {/* ... */}WithSubscription.displayName = `WithSubscription(${getDisplayName(WrappedComponent)})`;return WithSubscription;
}function getDisplayName(WrappedComponent) {return WrappedComponent.displayName || WrappedComponent.name || 'Component';
}
render() {// 每次调用 render 函数都会创建一个新的 EnhancedComponent// EnhancedComponent1 !== EnhancedComponent2const EnhancedComponent = enhance(MyComponent);// 这将导致子树每次渲染都会进行卸载,和重新挂载的操作!return ;
}
// 定义静态函数WrappedComponent.staticMethod = function() {/*...*/}// 现在使用 HOCconst EnhancedComponent = enhance(WrappedComponent);// 增强组件没有 staticMethodtypeof EnhancedComponent.staticMethod === 'undefined' // true//为了解决这个问题,你可以在返回之前把这些方法拷贝到容器组件上:
function enhance(WrappedComponent) {class Enhance extends React.Component {/*...*/}// 必须准确知道应该拷贝哪些方法 :(Enhance.staticMethod = WrappedComponent.staticMethod;return Enhance}
上一篇:基础会计学知识点汇总
下一篇:即时通讯sdk哪一个好?