compositionとは
compositionとは、コンポーネントの中に別のコンポーネントを合成して出力することです。どんなコンポーネントはどんな子エレメントが入ってくるかあらかじめ想定できない場合がありますが、 例えば、dialogがあります。
compositionを使ったdialog
下のロジックは、ThankyouDialogがDialogにpropsを渡して、Dialogを出力しています。しかし、dialogは汎用的な特徴を持っているので、下の例は再利用性がないロジックになります。(拡張性なし!)
どのdialogでもtitle、description, buttonは同じcssで同じ形で出力されてしまいます。
Dialog.jsx:再利用性なし
import React from 'react'
import { useState } from 'react'
export default function Dialog(props) {
const [isOpen, setIsOpen] = useState(false);
return (
<>
<button
onClick={()=> setIsOpen(true)}>Open</button>
{isOpen && <div
style={{
position: "absolute",
zIndex: 99,
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
border: "1px solid black",
padding: 24,
backgroundColor: "white",
}}
>
<p>Hello</p>
<h1>{props.title}</h1>
<h1>{props.description}</h1>
<h1>{props.button}</h1>
<button style={{backgroundColor:"red", color: "wthie"}}
onClick={()=> setIsOpen(false)}>{props.button}</button>
</div>
}
{isOpen && <div style={{
position: "fixed",
top: 0,
left: 0,
bottom: 0,
right: 0,
backgroundColor: "lightgray"
}}/>}
</>
);
}
ThankyouDialog.jsx
import React from 'react'
import Dialog from './Dialog'
export default function ThankyouDialog() {
return (
<Dialog
title="Thanks"
description="It is honor to meet you"
button="close"/>
)
}
したは拡張性を持ったcompositionロジックになります。
親のDialogコンポーネントがあり、その親のコンポーネントを使用して
各自出力したいDialogの内容をcustomしDialogを出力することが可能です。
Dialog.jsx:再利用性あり
import React from 'react'
import { useState } from 'react'
export default function Dialog(props) {
const [isOpen, setIsOpen] = useState(false);
return (
<>
<button
onClick={()=> setIsOpen(true)}>Open</button>
{isOpen && <div
style={{
position: "absolute",
zIndex: 99,
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
border: "1px solid black",
padding: 24,
backgroundColor: "white",
}}
>
{ typeof props.title === "string" ? (
<h1>{props.title}</h1>
) : (props.title)}
{ typeof props.description === "string" ? (
<h1>{props.description}</h1>
) : (props.description)}
{ typeof props.button === "string" ? (
<button style={{backgroundColor:"red", color: "wthie"}}onClick={()=> setIsOpen(false)}>{props.button}</button>
) : (
<div onClick={()=>setIsOpen(false)}>
{props.button}
</div>
)}
</div>
}
{isOpen && <div style={{
position: "fixed",
top: 0,
left: 0,
bottom: 0,
right: 0,
backgroundColor: "lightgray"
}}/>}
</>
);
}
ThankyouDialog.jsx
import React from 'react'
import Dialog from './Dialog'
export default function ThankyouDialog() {
return (
<Dialog
title={<h1 style={{color: `purple`}}>thanks</h1>}
description="It is honor to meet you"
button={<button style={{backgroundColor: "blue", color:"white"}}>close</button>}
/>
)
}
SorryDialog.jsx
import React from 'react'
import Dialog from './Dialog'
export default function SorryDialog() {
return (
<Dialog
title={<h1 style={{color: `red`}}>Sorry</h1>}
description="Sorry My Fault!!"
button={<button style={{backgroundColor: "red", color:"white"}}>close</button>}
/>
)
}