写业务时,咱们常常须要抽象一些使用频率较高的逻辑,可是除了高阶组件能够抽象逻辑,RenderProps也是一种比较好的方法。react
RenderProps,顾名思义就是将组件的props渲染出来。其实是让组件的props接收函数,由函数来渲染内容。将通用的逻辑
抽象在该组件的内部,而后依据业务逻辑来调用函数(props内渲染内容的函数),从而达到重用逻辑的目的。函数
咱们先看一个最简单的RenderProps模式的实现:code
const RenderProps = props => <> {props.children(props)} </>
在这里,RenderProps组件的子组件是一个函数props.children(props)
,而props.children返回的是UI元素。get
使用时的代码以下:it
<RenderProps> {() => <>Hello RenderProps</>} </RenderProps>
以上未做任何的业务逻辑处理,有什么用处呢?咱们能够想到,能够在 RenderProps 组件中去用代码操控返回的结果。
以最多见的用户登陆逻辑为例,但愿在登录以后才能够看到内容,不然展现请登陆:import
const Auth = props => { const userName = getUserName() if (userName) { const allProps = {userName, ...props} return <> {props.children(allProps)} </> } else { return <>请登陆</> } } <Auth> {({userName}) => <>Hello!{userName}</>} </Auth>
props.children(allProps)
就至关于Auth组件嵌套的({userName}) => <>Hello!{userName}</>
登录
上边的例子中,用户若已经登录,getUserName返回用户名,不然返回空。这样咱们就能够判断返回哪些内容了。
固然,上边经过renderProps传入了userName,这属于Auth组件的加强功能。渲染
平时通常使用的时候,props.children都是具体的组件实例,但上边的实现是基于以函数为子组件(children(props)
),被调用返回UI。
一样,能够调用props中的任何函数。仍是以上边的逻辑为例:plugin
const Auth = props => { const userName = 'Mike' if (userName) { const allProps = { userName, ...props } return <>{props.login(allProps)}</> } else { return <> {props.noLogin(props)} </> } }
使用方法以下:方法
<Auth login={({userName}) => <h1>Hello {userName}</h1>} noLogin={() => <h1>please login</h1>} />
这里,Auth组件的props接收两个函数:login(表示已经登陆),noLogin(表未登陆),
Auth组件内部,经过判断是否登录来决定显示哪一个组件。
render-props做为一种抽象通用逻辑的方法,其自己也会遇到像高阶组件那样层层嵌套的问题。
<GrandFather> {Props => { <Father> {props => { <Son {...props} />; }} </Father>; }} </GrandFather>
但和高阶组件不一样的是,因为渲染的是函数(高阶组件渲染的是组件),就为利用compose提供了机会。例如react-powerplugin
。
import { compose } from 'react-powerplug' const ComposeComponent = compose( <GrandFather />, <Father /> ) <ComposeComponent> {props => { <Son {...props} />; }} <ComposeComponent/>
还有Epitath
也提供了一种新模式来解决这个问题。这部分展开来讲的话是另外一个话题了,我也在摸索中。