什么是渲染道具,它与高阶组件有什么不同?

时间:2018-01-28 22:08:28

标签: reactjs render

到目前为止,似乎render props还没有得到足够的牵引力,但它被久负盛名的反应库广泛使用,如react-router 4react motion等。有一个专门的部分,这个出现的模式的任何原因,如何与众所周知的HOC(高阶组件)模式进行比较?

1 个答案:

答案 0 :(得分:9)

为我的研究,不同答案和答案留下答案。讨论非常欢迎!

HOC借鉴High Order Function

的概念
  

高阶函数(也是函数,函数形式或函子)是至少执行以下任一操作的函数:

     
      
  • 将一个或多个函数作为参数(即程序参数),
  •   
  • 返回一个函数作为结果。[争议 - 讨论]
  •   

HOC

  

高阶组件(HOC)是React中用于重用组件逻辑的高级技术。

源于此Gist

此模式与 STATIC 组成有关。核心/可重用逻辑封装在HOC中,同时将移动部件留给组件。

以反应路由器的withRouter为例:

  

withRouter会在呈现时将更新的匹配,位置和历史道具传递给包装组件。

     

//这会绕过shouldComponentUpdate

     

withRouter(连接(...)(MyComponent的))

现在你得到一个增强的MyComponent,它具有路由器HOC传递的{ history, match, location, ...connectProps, ...ownProps }的道具。

一种常见的方法是

compose(
  connect( ... ),
  enhance( ... ),
  withRouter( ... ),
  lifecycle( ... ),
  somethingElse( ... )
)(MyComponent);  

最重要的是,您可以使用compose utility无限地组合这些HOC以获得组件的最终增强版本,并且您的组件将获得有关从返回的新组件注入的redux存储,反应路由器等的知识由HOC。

该方法的缺点是:

  1. 组件的行为是在运行时之前定义的,因此失去了反应的渲染生命周期的力量,比如说你不能这样做:

    compose(
      this.state.shouldConnect && connect( ... ),
      this.state.shouldEnhance && enhance( ... ),
      this.state.shouldWithRouter && withRouter( ... ),
      ...
    )(MyComponent); 
    

    因为state / props在您的代码运行之前不可用。

  2. 间接&命名冲突。

  3.   

    使用带有ES6类的HOC会产生许多与mixin对createClass相同的问题,只是重新安排了一下。

         

    HOCs引入了很多仪式,因为它们包装组件并创建新组件而不是混合到现有组件中。

    渲染道具

      

    渲染道具是一个组件用来知道渲染内容的函数道具。

    react-motion首次采用,早在第一次提交redux之前的几个星期Dan's Gist就已经看到了。

    此模式与 DYNAMIC 组成有关。核心/可重用逻辑保留在组件中,而移动部件作为回调道具传递。

    您可以通过渲染道具创建HOC。

    仍以withRouter为例:

    const withRouter = Component => {
      const C = props => {
        const { wrappedComponentRef, ...remainingProps } = props;
        return (
          <Route
            render={routeComponentProps => (
              <Component
                {...remainingProps}
                {...routeComponentProps}
                ref={wrappedComponentRef}
              />
            )}
          />
        );
      };
      ...
      return hoistStatics(C, Component);
    }; 
    

    虽然情况恰恰相反。

    <Connect render={connectPropsMergedWithState => {
      <Enhance render={enhancePropsMergedWithState => {
        <WithRouter render={routerPropsMergedWithState => {
          <Lifecycle render={lifecyclePropsMergedWithState => {
            <SomethingElse render={somethingElsePropsMergedWithState => {
              ...
            }/>
            ...
          }/>
          ...
        }/>
        ...
      }/>
      ...
    }/>
    

    虽然看起来不太好,但它有很多收获。

    1. 它具有更好的显性,因为我们可以看到完全作为参数传递给渲染道具的内容。
    2. 由于1,它使我们免于潜在的道具碰撞
    3. 它充满活力,我们可以传递任何我们喜欢的东西(包括state / props)来渲染道具。
    4. 众所周知的缺点是performance optimization is tricky,因为要接收的道具被推迟到运行时。并且进行任何过早优化可能不是一个好主意,但这可能是另一个主题。

      如果你同意反应路由器的方向从3移动到4,渲染道具可能就是你的堵塞。

      参考文献:

      1. https://cdb.reacttraining.com/use-a-render-prop-50de598f11ce
      2. https://reactrocket.com/post/turn-your-hocs-into-render-prop-components