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