1. 程式人生 > 實用技巧 >React元件設計模式-Render-props

React元件設計模式-Render-props

寫業務時,我們經常需要抽象一些使用頻率較高的邏輯,但是除了高階元件可以抽象邏輯,RenderProps也是一種比較好的方法。

RenderProps,顧名思義就是將元件的props渲染出來。實際上是讓元件的props接收函式,由函式來渲染內容。將通用的邏輯抽象在該元件的內部,然後依據業務邏輯來呼叫函式(props內渲染內容的函式),從而達到重用邏輯的目的。

簡單實現

我們先看一個最簡單的RenderProps模式的實現:

const RenderProps = props => <>
    {props.children(props)}
</>

在這裡,RenderProps元件的子元件是一個函式props.children(props),而props.children返回的是UI元素。

使用時的程式碼如下:

<RenderProps>
    {() => <>Hello RenderProps</>}
</RenderProps>

以上未作任何的業務邏輯處理,有什麼用處呢?我們可以想到,可以在 RenderProps 元件中去用程式碼操控返回的結果。
以最常見的使用者登入邏輯為例,希望在登陸之後才可以看到內容,否則展示請登入:

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元件的增強功能。

函式名不僅可以是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元件內部,通過判斷是否登陸來決定顯示哪個元件。

資源搜尋網站大全 https://www.renrenfan.com.cn 廣州VI設計公司https://www.houdianzi.com

總結

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