最近 render props 在外网挺火,在逛 medium 的时候看到好几篇文章都是关于它的,由于笔者目前在做毕业设计,业务逻辑上不难实现,所以在这个过程中更多的考虑去尝试一些新的东西。在详细阅读了几篇文章后笔者也在自己的项目中用上了render props,这里就说说在这个过程中的一些思考。
最重要的一点,render props 其实和高阶组件HOC一样,是为了给纯函数组件加上state,响应react的生命周期。
为什么会有这样的需求呢?我们要从HOC说起
我们写的纯函数组件只负责处理展示,很多时候会发现,由于业务需求,组件需要被“增强”,例如响应浏览器事件等。如果只有一两个组件我们大可以全部重写为class形式,但如果有许多组件需要进行相似或相同的处理(例如都响应浏览器窗口改变这个事件)时,考虑到代码的复用性,很容易想到用函数处理,HOC也正是为了解决这样的问题而出现的。
HOC的基本原理可以写成这样:
- const HOCFactory = (Component) => {
- return class HOC extends React.Component {
- render(){
- return <Component {...this.props} />
- }
- }
- }
很明显HOC最大的特点就是:接受一个组件作为参数,返回一个新的组件。
这里是一个响应鼠标事件的HOC例子:
- import React from 'react'
- import ReactDOM from 'react-dom'
- const withMouse = (Component) => {
- return class extends React.Component {
- state = { x: 0, y: 0 }
- handleMouseMove = (event) => {
- this.setState({
- x: event.clientX,
- y: event.clientY
- })
- }
- render() {
- return (
- <div style={{ height: '100%' }} onMouseMove={this.handleMouseMove}>
- <Component {...this.props} mouse={this.state}/>
- </div>
- )
- }
- }
- }
- const App = (props) => {
- const { x, y } = props.mouse
- return (
- <div style={{ height: '100%' }}>
- <h1>The mouse position is ({x}, {y})</h1>
- </div>
- )
- }
- const AppWithMouse = withMouse(App)
- ReactDOM.render(<AppWithMouse/>, document.getElementById('root'))
笔者曾经使用了比较长时间的HOC,让我坚持用下去大概有以下这些原因,
当然HOC也存在一些问题(不然我就不会写这篇文章了...)
render prop 的出现解决了以上问题
A render prop is a function prop that a component uses to know what to render.
Render Props 的核心思想是,通过一个函数将class组件的state作为props传递给纯函数组件
这里是一个简单的使用render prop的例子
- import React from 'react'
- import ReactDOM from 'react-dom'
- import PropTypes from 'prop-types'
- class Mouse extends React.Component {
- static propTypes = {
- render: PropTypes.func.isRequired
- }
- state = { x: 0, y: 0 }
- handleMouseMove = (event) => {
- this.setState({
- x: event.clientX,
- y: event.clientY
- })
- }
- render() {
- return (
- <div style={{ height: '100%' }} onMouseMove={this.handleMouseMove}>
- {this.props.render(this.state)}
- </div>
- )
- }
- }
- const App = () => (
- <div style={{ height: '100%' }}>
- <Mouse render={({ x, y }) => (
- <h1>The mouse position is ({x}, {y})</h1>
- )}/>
- </div>
- )
- ReactDOM.render(<App/>, document.getElementById('root'))
从demo中很容易看到,新建的Mouse组件的render方法中返回了
这个函数,将其state作为参数传入其的props.render方法中,调用时直接取组件所需要的state即可。
- {this.props.render(this.state)}
这样做的优势是
MICHAEL JACKSON 在twitter上发起挑战,称所有HOC都能改写为Render props,如果你发现有例外,欢迎提出质疑��
对于二者之间的选择问题,笔者持中立态度,一方面render props 在大多数情况下比HOC更直观也更利于调试,另一方面HOC可传入多个参数的特性让我能少写不少代码,在目前的这个项目中我二者都有使用,个人根据不同的场景进行选择更有利于开发效率的提高。
(btw知乎对 jsx 的高亮emmmm...真是惨不忍睹)
来源: https://juejin.im/entry/5a151f4b518825296421555e