专栏名称: FateRiddle
目录
相关文章推荐
山西省商务厅  ·  山西省商务厅关于2025年商务事业发展专项资 ... ·  17 小时前  
山西省教育厅  ·  今天起山西高考生可模拟填报志愿 ·  2 天前  
山西省教育厅  ·  今天起山西高考生可模拟填报志愿 ·  2 天前  
51好读  ›  专栏  ›  FateRiddle

React拾遗:Render Props及其使用场景

FateRiddle  · 掘金  ·  · 2018-06-27 02:15

正文

React拾遗:Render Props及其使用场景

什么是 Render Props?

新的context api使用了 render props

<ThemeContext.Consumer>
  {theme => (
    <button
      {...props}
      style={{backgroundColor: theme.background}}
    />
  )}
</ThemeContext.Consumer>

第一次见到这个语法时,大多会很惊讶,因为日常代码里 props.children 必然是字符串或者元素。但事实上 props.children 可以是函数,只要最终生成的render的返回值是dom元素就行。例如:

// chilren props
const Test = props => props.children('hello world')
const App = () => (
    <Test>
        {text => <div>{text}</div>}
    </Test>
)

ReactDOM.render((<App />, root)  // 返回<div>hello world</div>

虽然没有实际意义,但这即是一个 render props 。当然 render props 最初的意思是: 组件不自己定义render函数,而是通过一个名为 render props 将外部定义的render函数传入使用。 以上例来说,会是这样:

// render props
const Test = props => props.render('hello world')
const App = () => (
    <Test
      render={text => <div>{text}</div>}
    />
)

ReactDOM.render((<App />, root)  // 返回<div>hello world</div>

因为现实中render函数很庞大,为了代码整洁多半会使用 children 而不是自定义的 render 来接收外部的render函数。所以这一技巧也可以称为 children props (相对于 render props 更加不知所云的名称),但一般统称 render props

为何要使用如此怪异的语法呢?

为了重用性。React的组件化就是为了方便重用。大多数场景我们需要重用的是UI(例如文章列表,侧栏),但也有少数情况需要重用的是功能和状态(例如context)。

如果说React的核心是 State => UI , 普通的组件是UI重用,那么 render props 就是为了State重用而应运而生的。

Render Props 小史

在 Demo 展开前插播一段 render props 的趣史。

  • 最早引人关注是从 Facebook 的 Cheng Lou 写的 React Motion 动画库。
import { Motion, spring } from 'react-motion';

<Motion defaultStyle={{x: 0}} style={{x: spring(10)}}>
  {value => <div>{value.x}</div>}
</Motion>
  • 之后这一写法被各位大牛广泛接受,写过很多非常赞的前端教程的 Kent C. Dodds 就非常喜欢 render props, 他所任职的 PayPal 的输入框组件 downshift 也使用了 render props

  • 大家熟知的 react-router 的作者 Michael Jackson 也是 render props 的极力推崇者。他twitter过一句很有争议的话:

Next time you think you need a HOC (higher-order component) in @reactjs, you probably don't.

翻译过来就是:下次你想使用HOC解决问题时,其实大半不需要。 在回复中他补充说明到,

I can do anything you're doing with your HOC using a regular component with a render prop. Come fight me.

即是说, 所有用 HOC 完成的事,render props 都能搞定。 值得一提的是 react-router 4 里唯一的一个 HOC 是 withRouter , 而它是用 render props 实现的,有兴趣的可以去看一下 源代码

  • HOC 虽然好用,但写一个“真正好用”的HOC却要经过一道道繁琐的工序(React的新api fowardRef 就几乎是为此而生的),是个用着舒服写着烦的存在。所以感觉最近大有“少写 HOC 推崇 render props”的思潮。至于新的 Context api 虽然思路上和 react-redux 如出一辙,却选择了 render props 的写法,在我看来也是顺理成章。

Render Props 使用场景

实例1: 一个日常的使用场景是弹窗。App的弹窗UI可能千奇百怪,但它们的功能却是类似的:无非有个显示隐藏的状态,和一个控制显隐的方法,以 antd 为例:







请到「今天看啥」查看全文