React中的render props,让组件复用(共享)变得简单,你还不赶紧掌握它?

Posted 前端不释卷leo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React中的render props,让组件复用(共享)变得简单,你还不赶紧掌握它?相关的知识,希望对你有一定的参考价值。

术语“render prop”是指一种在react组件之间使用一个值为函数的prop共享代码的简单技术。

具有 render prop 的组件接受一个函数,该函数返回一个 React 元素并调用它而不是实现自己的渲染逻辑。

我们知道,组件是 React 代码复用的主要单元,但如何分享一个组件封装到其他需要相同 state 组件的状态或行为并不总是很容易。

如何使用render prop?

官网举了一个经典的跟踪 Web 应用程序中的鼠标位置的例子:

Render Props – React

我这里也举一个非常简单的使用render prop的例子,帮助大家更容易去理解。

首先,新建一个显示“Hello World”的组件ShowHello.js:

import React from 'react';

class ShowHello extends React.Component 
  constructor(props) 
    super(props);
    this.state = 
      greet:"Hello World"
    
  
  render()
    return (
      <p>this.state.greet</p>
    )
  


export default ShowHello

现在我们有一个组件Page,想要获取组件ShowHello的greet此时的状态(即“Hello World”),我们常规的做法可以是:在ShowHello组件内部的渲染方法渲染 Page组件:

Page.js

import React from 'react';

class Page extends React.Component 
  constructor(props) 
	super(props);
    this.state = 
      greet: this.props.greet     //获取父组件(ShowHello)的prop
    
  
  render()
    return (
      <div>
        <p>this.state.greet</p>     //渲染
      </div>
    )
  


export default Page

ShowHello.js

import React from 'react';
import Page from './Page';

class ShowHello extends React.Component 
  constructor(props) 
	super(props);
    this.state = 
      greet:"Hello World"
    
  
  render()
    return (
      <div>
        <Page greet=this.state.greet />     //将greet作为prop传给子组件Page
      </div>
    )
  


export default ShowHello

这种方法适用于我们的特定用例,但我们还没有达到以可复用的方式真正封装状态或行为的目标。现在,每当我们想要状态用于不同的用例时,我们必须创建一个新的组件(本质上是另一个ShowHello组件,通过将prop传给另一个子组件),它专门为该用例呈现一些东西。

这也是 render prop 的来历:我们可以提供一个带有函数 prop 的ShowHello组件,它能够动态决定什么需要渲染,而不是将Page组件硬编码到ShowHello组件里,并有效地改变它的渲染结果。

import React from 'react';

class ShowHello extends React.Component 
  constructor(props) 
	super(props);
    this.state = 
      greet:"Hello World"
    
  
  render()
    return (
      <div>
        /* <Page greet=this.state.greet /> */   //将prop方式换成render prop的方式
        this.props.render(this.state.greet)    //不同的组件共享同一个状态,且不需要创建            
                                                 //一个新的ShowHello组件
      </div>
    )
  


export default ShowHello
import React from 'react';
import ShowHello from './ShowHello';
import Page from './Page';

class Home extends React.Component 
  render()
    return (
      <div>
        <ShowHello render=greet => (   //通过render prop的方式决定哪个组件渲染使用此状态
          <Page greet=greet/>
        )/>
      </div>
    )
  


export default Home

现在,我们提供了一个 render 方法,让ShowHello组件能够动态决定什么需要渲染,而不是克隆ShowHello组件然后硬编码来解决特定的用例。如果存在其他组件使用该状态,那么只需要将render中的Page组件改成其他组件即可。

更具体地说,render prop 是一个用于告知组件需要渲染什么内容的函数 prop。

这项技术使我们共享状态或行为非常容易。要获得这个状态或行为,只要渲染一个带有render prop的组件就能够告诉它当前要渲染什么。

render prop并不是react的API,而是一种与高阶组件(HOC)类似的设计模式,ShowHello组件中传递的prop也不一定要是render,也可以是其他标识,如child(或其他自己想要的标识)。

import React from 'react';
import ShowHello from './ShowHello';
import Page from './Page';

class Home extends React.Component 
  render()
    return (
      <div>
        <ShowHello child=greet => (   //prop可以为自己想要的标识,须传入一个函数
          <Page greet=greet/>
        )/>
      </div>
    )
  


export default Home

ShowHello内部的prop也相应变化

import React from 'react';

class ShowHello extends React.Component 
  constructor(props) 
	super(props);
    this.state = 
      greet:"Hello World"
    
  
  render()
    return (
      <div>
        this.props.child(this.state.greet)     //prop此时为child,切记此时child为函数
        //上面相当于渲染成 <Page greet=this.state.greet /> 
      </div>
    )
  


export default ShowHello

更容易理解的一种方式是,你可以认为现在prop传的不是具体某个状态,而是一个函数,函数体是要渲染(或者说使用共享状态)的组件,函数的参数为实际的传入渲染组件的state。

关键部分

<ShowHello child=greet => (  //prop为一个函数
  <Page greet=greet/>
)/>
this.props.child(this.state.greet)    //为函数传入共享状态

以上是关于React中的render props,让组件复用(共享)变得简单,你还不赶紧掌握它?的主要内容,如果未能解决你的问题,请参考以下文章

React10.render props 模式实现组件复用

react 中 render-props 模式

09.Render-props

React10.render props 模式实现组件复用

React的render-props模式、高阶组件

React中组件细节点(通信props类型校验复用)