定义:高阶组件就是一个函数,且该函数接收一个组件作为参数,并返回一个新的组件。
(上一篇已经说过了高阶组件可以用来解决交叉问题)
一、不要改变原始组件,使用组合
class A extends React.PureComponent{ constructor(props){ super(props); this.state={ content:"我是A" } } componentWillReceiveProps(nextProps){ this.setState({ content:nextProps.content }) } componentDidMount(){ console.log("a挂载完毕") } render(){ return( <p>{this.state.content}</p> ) } } class B extends React.PureComponent{ constructor(props){ super(props) this.state={ content:'我是B' } } componentDidMount(){ console.log("b挂载完毕") } render(){ return( <button style={{color:'red'}}>{this.state.content}</button> ) } } function initContent(Aa){ // Aa.prototype.componentDidMount=function(){ // console.log("我先挂载好的") // } return class K extends React.Component{ constructor(props){ super(props); this.state={ content:"我是高阶组件生成的" } } componentDidMount(){ this.setState({ content:"我现在为C" }) console.log("c挂载完毕") } render(){ return( <Aa content={this.state.content} /> ) } } } const A1 = initContent(A); const B1 = initContent(B) ReactDOM.render(<div><B1></B1><A1></A1></div>, document.getElementById("root"));
若放开上面代码中的注释,那么包裹组件该方法原有的逻辑将被重写,可能会引起冲突。
二、约定:将不相关的props属性传递给包裹组件
render() { // 过滤掉与高阶函数功能相关的props属性, // 不再传递 const { extraProp, ...passThroughProps } = this.props; // 向包裹组件注入props属性,一般都是高阶组件的state状态 // 或实例方法 const injectedProp = someStateOrInstanceMethod; // 向包裹组件传递props属性 return ( <WrappedComponent injectedProp={injectedProp} {...passThroughProps} /> ); }
三、约定:最大使用组合
const ConnectedComment = connect(commentSelector, commentActions)(Comment); 等于下面 // connect是一个返回函数的函数(译者注:就是个高阶函数) const enhance = connect(commentListSelector, commentListActions); // 返回的函数就是一个高阶组件,该高阶组件返回一个与Redux store // 关联起来的新组件 const ConnectedComment = enhance(CommentList);
这个有点类似于jq中的链式调用
四、约定:包装显示名字以便于调试
注意事项
一、不在render函数中使用高阶组件
简单来说react使用差异算法,当再render中使用高阶组件时,每次render返回的高阶组件都是新创建的,与原来的一定不一致,所以每次都要重新渲染,
这里产生的问题不仅仅是性能问题 —— 还有,重新加载一个组件会引起原有组件的所有状态和子组件丢失。
二、必须将静态方法做拷贝
这里我只介绍一个方法
function enhance(WrappedComponent) { class Enhance extends React.Component {/*...*/} // 必须得知道要拷贝的方法 :( Enhance.staticMethod = WrappedComponent.staticMethod; return Enhance; }
三、refs属性不能传递
参考:https://doc.react-china.org/docs/higher-order-components.html