yaofly2012 / note

Personal blog
https://github.com/yaofly2012/note/issues
44 stars 5 forks source link

Reactjs-HOC & Render Props #74

Open yaofly2012 opened 5 years ago

yaofly2012 commented 5 years ago

HOC

一、概述

是React的一种编程模式,解决横切关注点问题(复用代码逻辑)。

const EnhancedComponent = higherOrderComponent(WrappedComponent);
  1. WrappedComponent增加额外对功能,而这些额外的功能具有公用性(即需要复用对逻辑部分);
  2. HOC就像个组件工厂,把原材料WrappedComponent增强后产生个新组件。

二、使用

2.1 参数化的HOC

HOC只是个模式,可以有不同的写法,有种场景是通过一个配置参数控制HOC的行为,即参数化的HOC。

const ContainerComponent = genHOC(option)(WrappedConponent)

genHOC函数根据返回个HOC,并且根据传入的option参数来定制返回的HOC。

2.2 习惯

  1. 把传给EnhancedComponent的属性都传给WrappedComponent;
  2. HOC函数一般以withXXX命名;
  3. 尽量保证WrappedConponentEnhancedComponent 行为类似;

三、进阶

3.1 如何解决横切关注点问题

把公共逻辑写在父组件里(即高阶组件),利用组件组合构建新的组件。

3.2 缺点

  1. 增加组件的深度,存在命名冲突问题; 即传给EnhancedComponent组件的属性有些是HOC处理的,有些则[再传给WrappedComponent](Convention: Pass Unrelated Props Through to the Wrapped Component),难免两者存在同名的属性。

  2. 静态组合 HOC是一种静态组合模式(即一般都需要提前定义好EnhancedComponent),并且不适合动态组合。 当然了如果能保证EnhancedComponent只会被创建一次,HOC也可以实现动态组合。

  3. 规范的HOC实现遵循的规则挺多的,比如:

  4. ref的结合也不友好。

3.3 注意:

  1. HOC必须是个纯函数,不能修改传入的组件;
  2. 不要在render方法中使用HOC;
  3. HOC还是得多写,多想,多Review,这样才能有所感悟。

参考

  1. 深入理解 React 高阶组件
yaofly2012 commented 5 years ago

Render Props

一、概述

Render Props也是解决横切关注点问题的一种编程方式,并且是作为HOC的替代品。

二、使用

2.1 Render Props一种模式

  1. 有时候为了书写方便,可以使用children属性传递渲染函数(即Function as Child Component)。

2.2 优点

React官方推荐使用Render Props代替HOC,好些库(如Formik)也在使用。 Render Props作为HOC的替代品解决了HOC存在的缺点。

  1. 更直观是传值; 组合组件的开发可以直接给组件传入props,而不是像HOC那样由高阶组件的开发转发props;
  2. 不存在属性命名冲突;
  3. 可更方便的实现动态组合,不必事先定义高阶组件。

2.3 缺点

  1. 大部分情况下我们为了方便都是用局部函数作为render props,因为每次render都是一个新函数这会带来性能问题。
  2. Function as Child Components Are an Anti-Pattern 博文里还指出另外一个缺点:

    re-purposing children goes against one of the most basic things we’re taught in Computer Science; that is, “Choose meaningful names for your variables.”

“There are only two hard things in Computer Science: cache invalidation and naming things.”

– Popularly attributed to Phil Karlton

FaCC会导致函数命名不够语义化。

三、进阶

3.1 如何解决横切关注点问题

公共逻辑部分抽离成组件,特例组件的渲染逻辑(函数)通过props(一般取名为render)传给公共逻辑组件,由公共逻辑组件调用渲染函数属性渲染具体的UI。

参考

  1. React Render Props
  2. Use a Render Prop!
  3. Function as Child Components Are an Anti-Pattern
yaofly2012 commented 5 years ago

HOCRender Props对比

HOCRender Props都是为了解决Reactjs代码复用问题的编程模式。

1. 静态组合&动态组合

使用HOC时,都要针对每个特例组件定义一个新组件,这是一种静态组合(static compostition)。但有时特例组件的是无限个(即具体特例组件无法确定),此时使用Render Props方式(动态组合, dynamic composiiton)更合适。

ReactDOM.render(
  <Router>
    <Route path="/home" render={() => <div>Home</div>} />
  </Router>,
  node
);

2. HOC是新的mixins ?!

Use a Render Prop!做了总结:

Mixins HOCs Render Props
ES6 class语法是否支持 No Yes Yes
直观性 不直观 不直观 直观
命名冲突问题 Yes Yes No
  1. HOC视为ES6 class语法支持的Mixins; HOC比Mixins写法优雅些
  2. HOC的实现需要一些条条框框,比如尽量跟传入组件行为保持一致等;
  3. Render Props在写法上更简单(看起来很屌丝),不存在悄咪咪的state, props。

总结下来:建议使用Render Props 代替HOCs。

参考

  1. Use a Render Prop!