React組件設計模式-Render-props

React組件設計模式-組合組件react

React組件設計模式-Provider-Consumer設計模式

寫業務時,咱們常常須要抽象一些使用頻率較高的邏輯,可是除了高階組件能夠抽象邏輯,RenderProps也是一種比較好的方法。bash

RenderProps,顧名思義就是將組件的props渲染出來。其實是讓組件的props接收函數,由函數來渲染內容。將通用的邏輯 抽象在該組件的內部,而後依據業務邏輯來調用函數(props內渲染內容的函數),從而達到重用邏輯的目的。ide

簡單實現

咱們先看一個最簡單的RenderProps模式的實現:函數

const RenderProps = props => <>
    {props.children(props)}
</>
複製代碼

在這裏,RenderProps組件的子組件是一個函數props.children(props),而props.children返回的是UI元素。post

使用時的代碼以下:ui

<RenderProps>
    {() => <>Hello RenderProps</>}
</RenderProps>
複製代碼

以上未做任何的業務邏輯處理,有什麼用處呢?咱們能夠想到,能夠在 RenderProps 組件中去用代碼操控返回的結果。 以最多見的用戶登陸邏輯爲例,但願在登錄以後才能夠看到內容,不然展現請登陸:spa

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組件的加強功能。3d

函數名不只能夠是children

平時通常使用的時候,props.children都是具體的組件實例,但上邊的實現是基於以函數爲子組件(children(props)),被調用返回UI。 一樣,能夠調用props中的任何函數。仍是以上邊的邏輯爲例:

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也提供了一種新模式來解決這個問題。這部分展開來講的話是另外一個話題了,我也在摸索中。

相關文章
相關標籤/搜索