关于渲染道具的常见问题的答案

46 阅读3分钟

在我准备这篇文章的时候,我正准备给一家当地公司的工程师做培训。他们在 egghead.io 上看到了我的Advanced React Component Patterns 课程,想更深入地了解 Render Props 模式。(如果你不熟悉Render Props模式,我建议你现在停止阅读,阅读"使用Render Prop "或观看"不要再写HoC"(两者都是由杰出的Michael Jackson所写),然后回来继续)。

在准备这次培训的过程中(除了创作这个),我在推特上提出了这个问题

twitter.com/kentcdodds/…

我得到了不少很好的回应,在今天的通讯中,我想我将分享其中的三个问题和简单的例子来回答。

问题1:性能?

这是迄今为止我在谈论Render Props时得到的最常见的问题(我的推特上有几个询问性能的回复)。我对这个问题的回答很简单。"这是一个非常普遍的问题。所以我很高兴Ryan Florence在一篇很好的博文中回答了这个问题!阅读"React, Inline Functions, and Performance"。"综上所述"(引用该文章。

  • 自然地写你的代码,根据设计写代码。
  • 只有在需要时才使用PureComponentshouldComponentUpdate ,跳过道具函数(除非它们被用于生命周期钩子的副作用)。

如果你真的相信过早优化是不好的做法,那么你就不需要证明内联函数是快的,你需要证明它们是慢的。

我应该补充一点。如果你真的担心内联你的渲染道具函数和perf的影响,那么就不要内联这个函数!:)

class MyComp extends React.Component {
  renderDownshift = downshift => <div>{/* Your UI stuff here */}</div>
  render() {
    return <Downshift>{this.renderDownshift}</Downshift>
  }
}

问题2:混乱的渲染!?

马克是正确的。我所看到的几乎所有的渲染道具的例子也只是显示了渲染函数中的所有逻辑。它通常是一个隐含的返回,然后是一个巨大的表达式。我曾经对巨大的渲染函数感到厌烦,但我已经对它们感到温暖,因为我意识到我不喜欢它们的唯一原因是我认为它们很复杂......🤔 🤓

在任何情况下,因为渲染道具从字面上看只是带着参数被调用的函数,你可以对它们做任何你想做的事情。所以我为马克做了这两个例子。下面是这个概念的一个小版本。

function JustARegularFunctionComponent(props) {
  // do whatever you want in here
  return <div>{/* your stuff */}</div>
}

function App() {
  return (
    <div>
      <div>With a totally different component. Thanks React composibility!</div>
      <RenderPropComp
        render={arg => <JustARegularFunctionComponent {...arg} />}
      />
      <hr />
      <div>
        Inline! You don't have to make it an implicit return arrow function 😉
      </div>
      <RenderPropComp
        render={arg => {
          // <-- notice the curly brace!
          // do whatever you want in here
          return <div>{/* your stuff */}</div>
        }}
      />
    </div>
  )
}

问题3:生命周期钩子?

另一个相当普遍的问题是如何在生命周期钩子中获得对渲染道具参数的访问(因为你的渲染道具函数是在你的组件的render 的上下文中调用的,你如何把它弄到componentDidMount是由@SavePointSam 提出的。

这个问题的答案其实有点隐藏在上面对Mark问题的回答中。请注意,由于React的可组合性,我们可以创建一个单独的组件,并简单地将参数转发给我们组件的props。像这样

class RegularClassComponent extends React.Component {
  componentDidUpdate() {
    // here you are :)
    console.log(this.props.whatever)
  }
  render() {
    return <div>{/* your ui */}</div>
  }
}

function App() {
  return <RenderPropComp render={arg => <RegularClassComponent {...arg} />} />
}

如果我不提出他喜欢的组件注入模式,我的朋友Donavon会很伤心。有了组件注入,你可以更干净地做到这一点。

class RegularClassComponent extends React.Component {
  componentDidUpdate() {
    // here you are :)
    console.log(this.props.whatever)
  }
  render() {
    return <div>{/* your ui */}</div>
  }
}

function App() {
  return <CompInjectionComp component={RegularClassComponent} />
}

我将把实现细节留给读者练习......或者你可以看看Donavon在这次谈话后创建的新库,他是在飞机上发表的,✈️在3万英尺的高空!。

结论

渲染道具图案是很好的。我期待着看到更多的项目加入到Jared Palmer的awesome-react-render-props我喜欢Render Prop模式的原因是,它可以在不牺牲标记的可定制性和简单性的情况下封装组件的逻辑。 我想,更多令人敬畏的东西会出现......祝您好运!👍