ðŠâš æªæ¥ã®å€æŽã«åããïŒCompound Componentã§å®çŸããæ¡åŒµæ§âšðŠ
ã³ã³ããŒãã³ãã®æ©ã¿ã解決ãããïŒð
æè¿ãããããã®æ¯ãèããæã€ã³ã³ããŒãã³ããéçºããŠããŸãâïžãŠãŒã¶ãŒãå
¥åããå
å®¹ãæ€èšŒããããç¹å®ã®ãã¿ã³ãã¯ãªãã¯ããããšãã«ã ãããã¿ãŒã衚瀺ããããç¶æ
ã«ãã£ãŠããããŒã®è¡šç€ºãå€ããã...ãæ©èœãå¢ããã«ã€ããŠãã³ã³ããŒãã³ãã«æž¡ãpropsãã©ãã©ãå¢ãã³ã³ããŒãã³ãå
ã®ããžãã¯ãè€éåããããã¯propså°çã âŠð«ããšé ãæ±ããŠããŸããã
ãšããã§ãpropsãæž¡ãããšã¯æ¬åœã«ãå°çããªã®ã§ããããïŒ
ç¹å®ã®ãã¡ã€ã³ïŒæ©èœç¯å²ïŒã ãã§å®çµãããæ·±ããã¹ããããã³ã³ããŒãã³ãããªãŒã§ããã°ãpropsãæž¡ããŠããprops drillingã¯ãŸã£ããåé¡ãããŸããã Reactã®åºæ¬çãªä»çµã¿ã ãã§ã·ã³ãã«ã«å®è£
ã§ããã³ãŒãã®æµãã远ããããããã§ãã
ãããããã®ã³ã³ããŒãã³ãã®æ©èœãæ¡åŒµããããäžéšã®æ©èœã䜿ã£ãã䜿ããªãã£ããããæè»æ§ãå¿
èŠã«ãªã£ãé端ãpropsã®ç®¡çã¯è€éããå¢ããŸããäŸãã°ãã¢ãŒãã«ã®ããããŒãããã¿ãŒãããŒãžã«ãã£ãŠè¡šç€ºã»é衚瀺ãåãæ¿ããããšããshowHeader={true}ã®ãããªpropsãéªã ããŸåŒã«å¢ããif-elseã®æ¡ä»¶åå²ãè€éåãããpropså°çããçŸå®ã®ãã®ãšãªããŸãã
ãããªæãCompound ComponentïŒè€åã³ã³ããŒãã³ãïŒãšããéæ³ã®ãã¿ãŒã³ã§ãã³ãŒããã¹ãããªæŽçã§ããããšãåèªèããŸããïŒãã®ãã¿ãŒã³ã䜿ãã°ã芪ã³ã³ããŒãã³ããåã³ã³ããŒãã³ãã®æ¯ãèãã现ããå¶åŸ¡ããå¿
èŠããªããªãããŸãã§ã³ã³ããŒãã³ãã®åããŒãïŒããããŒãæ¬æãããã¿ãŒïŒãèªåŸçã«åããŠãããã®ããã«æ±ãããã§ãã
ãã®ã¬ã€ãã§ã¯ããã®éæ³ã®ãã¿ãŒã³ã®ããããå šéšæãã¡ãããŸãã
éæ³ã®åªæïŒ Compound Componentãšã¯ïŒ ð§ââïž
Reactã®ã³ã³ããŒãã³ããå¢ããæ©èœããŽãã£ãŽãã£ããŠãããšããŸãã§çµ¡ãŸã£ãæ¯ç³žçã¿ããã§å€§å€ã§ãããããããªæãCompound Componentãšããéæ³ã®ãã¿ãŒã³ããã³ãŒããã¹ãããªæŽçããŠãããŸãïŒð
ãã®ãã¿ãŒã³ã¯ãè€æ°ã®å°ããªé¢é£ã³ã³ããŒãã³ããããŸãã§ä»²è¯ãã°ã«ãŒãã®ããã«1ã€ã®èŠªã³ã³ããŒãã³ãã«ãŸãšããŸããGoogle Chromeã®ã¿ãã®ããã«ã芪ãåžä»€å¡ãšãªããåã³ã³ããŒãã³ããããããã®åœ¹å²ãæããããšã§ãUIå šäœãçŸããæ©èœãããã§ãã
åºæ¬ã®æ§æ
// ð Detail ã³ã³ããŒãã³ããšãã倧ããªãå®¶
<Detail>
<Detail.Header title="åå詳现" /> // ðª çé¢ïŒããããŒïŒ
<Detail.Body>ã³ã³ãã³ã</Detail.Body> // ðïž ãªãã³ã°ïŒæ¬æïŒ
<Detail.Actions> // ð ïž äœæ¥ã¹ããŒã¹ïŒã¢ã¯ã·ã§ã³ãã¿ã³ïŒ
<button onClick={handleEdit}>ç·šé</button>
<button onClick={handleDelete}>åé€</button>
</Detail.Actions>
</Detail>
ãã®æ§æã¯ãã³ã³ããŒãã³ãå士ã®é¢é£æ§ãæç¢ºã«ããUIã®æ§é ãèŠèŠçã«ããããããããŸããããã«ã芪ã³ã³ããŒãã³ããç¶æ ãå éšã§ç®¡çããåã³ã³ããŒãã³ããšå ±æãããããç¶æ 管çãã·ã³ãã«ã«ãªããŸãã
åºæ¬çãªã³ã³ããžã·ã§ã³ãšã®æ¯èŒïŒã¹ãŒããŒãã³ vs. ããŒããŒæŠé ðŠžââïž
æ®éã®ã³ã³ããŒãã³ãïŒåºæ¬çãªã³ã³ããžã·ã§ã³ïŒã¯ããŸãã§**ãäžäººã§äœã§ãããªããã¹ãŒããŒãã³ã**ðŠžââïžã¿ããã§ãã
æåã¯é Œãããã§ãããæ©èœãå¢ããããšã«props
ãšããéå
·ãã©ãã©ãå¢ããprops
å°çã«é¥ããã¡...ð«
ããã«æ¯ã¹ãŠãCompound Componentã¯**ãããŒã ã§åãããŒããŒæŠéã**ðŠžââïžð¥ã§ãã
èŠ³ç¹ | ã¹ãŒããŒãã³ïŒåºæ¬çãªã³ã³ããžã·ã§ã³ïŒ | ããŒããŒæŠéïŒCompound ComponentïŒ |
---|---|---|
æ§é ã®æç¢ºã | èªç±åºŠãé«ã | æ§é ãããããªå®çŸ©ããã ð¯ |
ã¹ã¿ã€ã«ã®äžè²«æ§ | éçºè ä»»ã | ã³ã³ããŒãã³ãåŽã§ä¿èšŒ âš |
ç¶æ ã®ç®¡ç | 芪ã§ç®¡çããpropsã§æž¡ã | å éšã§èªå管çãContextã§å ±æ ð§ |
æ©èœæ¡åŒµ | propsãã©ãã©ã远å ⊠| æ°ãããµãã³ã³ããŒãã³ãã远å ããã ãïŒð¥³ |
ã€ã³ããŒã | è€æ°ã®ã€ã³ããŒããå¿ èŠ | 1ã€ã®ã€ã³ããŒãã§å®çµ ðŠ |
propså°ç | ð± | ãµãšãã©ïŒ ð |
éæ³ã®äœãæ¹ïŒContextãšTypeScript ð ïž
Compound Componentã®éæ³ã®æã¯ã**React Context
ãšTypeScript
**ã§ãã
芪ã³ã³ããŒãã³ãã¯ãContext
ãšããéæ³ã®ç®±ð§ââïžãäœã£ãŠãããã«**ããã€ã¢ãã°ãéããŠããããããã¢ãã¡ãŒã·ã§ã³ã®ç¶æ
ã**ãšãã£ãå
±éã®æ
å ±ãå
¥ããŠãããŸãã
éæ³ã®ç®±ã®èšèšå³
// ð ã¿ããªã§å
±æããéæ³ã®ç®±ã®äžèº«ã®èšèšå³
type DialogContextType = {
isOpen: boolean;
isAnimating: boolean;
};
const DialogContext = createContext<DialogContextType | null>(null);
// ðµïžââïž éæ³ã®ç®±ããå®å
šã«äžèº«ãåãåºãããã¯
export const useDialogContext = (): DialogContextType => {
const context = useContext(DialogContext);
if (!context) {
throw new Error('Dialog components must be used within Dialog');
}
return context;
};
åã©ããã¡ã¯ã芪ããçŽæ¥props
ãåãåã代ããã«ããã®éæ³ã®ç®±ããå¿
èŠãªãã®ãèªç±ã«åŒãåºããŠäœ¿ããŸããäŸãã°ã**Dialog.Header
ãDialog.Body
**ãšãã£ãåã³ã³ããŒãã³ãã¯ããã®éæ³ã®ç®±ã䜿ã£ãŠèŠªã®ç¶æ
ã«ã¢ã¯ã»ã¹ã§ããŸãã
åã³ã³ããŒãã³ãã®éæ³ã®åªæ
// åã³ã³ããŒãã³ãïŒDialog.Body
// ð® éæ³ã®ç®±ããå¿
èŠãªå€ã ãåãåºã
export const DialogBody = ({ children }) => {
const { isOpen, isAnimating } = useDialogContext();
// ãã€ã¢ãã°ãéããŠããŠããã€ã¢ãã¡ãŒã·ã§ã³ãçµäºãããå
容ã衚瀺ãã
if (!isOpen || isAnimating) {
return null;
}
return (
<div className="dialog-body">
{children}
</div>
);
};
ãã®ããã«ãåã³ã³ããŒãã³ãã¯èŠªããæç€ºçã«isOpen
ãisAnimating
ãšãã£ãprops
ãåãåãå¿
èŠããããŸãããContextãéæ³ã®ããã«å¿
èŠãªæ
å ±ãèªåã§å±ããŠãããã®ã§ãã
ããã«ãTypeScript
ã§éæ³ã®ç®±ã®äžèº«ããã£ããèšèšããŠããã°ãåå®å
šæ§ãä¿èšŒããããšãã£ã¿ãèªåã§åŒ·åãªåè£å®ãããŠãããŸããããã§ãã¿ã€ããã¹ããã°ãã°ããšæžããŸããïŒð
ã¹ãããªæŽçè¡ïŒãã¡ã€ã«æ§æãšã¢ãŒããã¯ã㣠ð
ãããžã§ã¯ãã®èŠæš¡ã«å¿ããŠãã³ã³ããŒãã³ããæŽçããå Žæã決ããŸãããã
1. æ±çšçãªã³ã³ããŒãã³ãïŒæšå¥šïŒ
誰ã§ã䜿ããå
±éUIã¯ãsrc/common/components/tabs/
ã®ããã«ãæ©èœããšã«1ã€ã®ãã©ã«ãã«ãŸãšããŸãã
src/common/components/tabs/
âââ index.ts       # ãšã¯ã¹ããŒããäžç®æã«éçŽ
âââ Tabs.tsx       # 芪ã³ã³ããŒãã³ã
âââ ...åã³ã³ããŒãã³ããã¡
index.ts
ã§ãŸãšããŠãšã¯ã¹ããŒãããã°ã**ãã£ã1è¡ã®import
**ã§å
šéšã®éšåãåŒã³åºããã®ã§ããšã£ãŠã䟿å©ïŒ
2. ãã¡ã€ã³åºæã®ã³ã³ããŒãã³ã
ç¹å®ã®æ©èœïŒååããŠãŒã¶ãŒãªã©ïŒã«ç¹åããUIã¯ãsrc/domain/product/components/ProductDetail/
ã®ããã«ããã¡ã€ã³ããšã«æŽçããŸããããã«ãããããŒã ãæ©èœã®æ
åœãæç¢ºã«ãªããå€§èŠæš¡ãªãããžã§ã¯ãã§ãè¿·åã«ãªããŸããã
è²¬ä»»åæ ïŒèª°ãäœãããã®ïŒ ð¯
Compound Componentã®æå€§ã®é åã¯ã**ãè²¬ä»»ã®æç¢ºãªåé¢ã**ã«ãããŸãã
-
ããŒãžã³ã³ããŒãã³ãïŒ
pages
ïŒïŒ- ããžãã¹ããžãã¯ïŒããŒã¿ã®ååŸãéä¿¡ãªã©ïŒã«éäžããŸãã
- UIã®ç¶æ 管çã¯ãCompound Componentã«ä»»ããŸãã
-
Compound ComponentïŒ
common/components
ïŒïŒ- UIã®ç¶æ 管çãæ¯ãèããæ åœããŸãã
- ãã¿ããã¯ãªãã¯ããããã³ã³ãã³ããåãæ¿ããããšãã£ãUIããžãã¯ãã«ãã»ã«åããŸãã
-
ãã¡ã€ã³ããžãã¯ïŒ
domain/hooks
ïŒïŒ-
useProduct
ã®ããã«ãæ¥åããžãã¯ïŒååããŒã¿ã®ååŸãèªèšŒãªã©ïŒãæ ããŸãã
-
ããã«ãããããŒãžã¯UIã®è€éãªæ¯ãèããæ°ã«ãããæ¬æ¥ã®ä»äºïŒããŒã¿ã®è¡šç€ºïŒã«å°å¿µã§ããããã«ãªããŸãããã¹ããããããç¬ç«ããŠæžããã®ã§ãéçºå¹çãå€§å¹ ã«ã¢ããããŸããð
éæ³ã®æè»æ§ïŒå¿ èŠãªéšåã ã䜿ã£ãŠããã®ïŒ ð
Compound Componentã¯ã**ãå¿ èŠãªéšåã ããèªç±ã«éžãã§äœ¿ããã**ãšããé©ãã®æè»æ§ãæã£ãŠããŸãã
ãã«æ©èœç
<Card>
<Card.Header>ã¿ã€ãã«</Card.Header>
<Card.Body>æ¬æ</Card.Body>
<Card.Footer>ããã¿ãŒ</Card.Footer>
</Card>
ããããŒãªãçïŒHeaderãæžããªãã ãïŒïŒ
<Card>
<Card.Body>æ¬æ</Card.Body>
<Card.Footer>ããã¿ãŒ</Card.Footer>
</Card>
props
ã§showHeader={false}
ãšæžãå¿
èŠã¯ãããŸããïŒäœ¿ããªãèŠçŽ ã¯æžããªããã°ããã ããªã®ã§ãã³ãŒãããšã£ãŠãã·ã³ãã«ã«ãªããŸãã
é åºã®å€æŽãè€æ°äœ¿çšãèªç±èªåšïŒ
<Card>
<Card.Body>æ¬æãå
ã«ïŒ</Card.Body>
<Card.Header>ã¿ã€ãã«ãåŸã«ïŒ</Card.Header>
</Card>
ãŸããå€éšããå¶åŸ¡ãããå Žåããprops
ãæž¡ãã ãã§ç°¡åã«å¯Ÿå¿ã§ããŸããCompound Componentã¯ãå
éšã®ç¶æ
管çã ãã§ãªããå€éšããã®å¶åŸ¡ã«ã察å¿ã§ãããã§ãã
æçµå¥¥çŸ©ïŒCompound Component + Custom Hooks âš
æã匷åãªã®ã¯ãCompound ComponentãšCustom Hooksãçµã¿åãããããšã§ãã
- Compound Component â æšæºUIãæäŸããŸãã
- Custom Hooks â UIããç¬ç«ããããžãã¯ãæäŸããŸãã
ããã«ãããéçºè ã¯2ã€ã®éžæè¢ãåŸãããŸãã
-
ç°¡åãéèŠïŒ
Compound Component
ã䜿ã£ãŠãçµ±äžãããUIã§è¿ éã«éçºããã -
æè»æ§éèŠïŒ
Custom Hooks
ã䜿ã£ãŠãããžãã¯ã ããåå©çšããUIã¯èªç±ã«ãã¶ã€ã³ããã
ãã®çµã¿åããã¯ãããªãã®æå³ã§ãããæ±çšçãªæ©èœãæ¡åŒµãããããããããšã«å®ç§ã«å¿ããŸããå ±éã®ããžãã¯ãããã¯ã«ãŸãšããããšã§ãæ§ã ãªUIã§åãæ¯ãèããå®çŸã§ããŸãã
ãŸãšãïŒCompound Componentã®çŽ æµãªãšããð
å©ç¹ | 説æ |
---|---|
責åã®åé¢ | ããŒãžã¯ããŒã¿ã®è¡šç€ºãã³ã³ããŒãã³ãã¯UIã®æ¯ãèããããã¯ã¯æ¥åããžãã¯ã«éäžã圹å²ãæç¢ºã«ãªããä¿å®æ§ãã¢ããïŒ |
ãã¶ã€ã³ã®äžè²«æ§ | æ§é ãšã¹ã¿ã€ã«ãçµ±äžãããã¶ã€ã³ã·ã¹ãã ã®æ§ç¯ã«æé©ãã¢ã¯ã»ã·ããªãã£ãèªåã§ç¢ºä¿ã§ããŸãã |
éçºå¹çã®åäž |
props å°çãåé¿ããã³ãŒãã®éè€ãæé€ãããŒã åæ
ãæç¢ºã«ãªãããã°ãæžå°ããŸãã |
é©ãã®æè»æ§ | å¿
èŠãªéšåã ãã䜿ããé åºãèªç±ã«å€ããããŸããäžèŠãªprops ã§æ©ãããšã¯ãããããŸããïŒ |
Compound Componentãã¿ãŒã³ã¯ãé©åã«äœ¿ãããšã§Reactã¢ããªãããçŸããã匷ãããããŠã¡ã³ããã³ã¹ãããããã®ã«å€ããéæ³ã§ãããããžã§ã¯ãã®èŠæš¡ãèŠä»¶ã«åãããŠããã®åŒ·åãªãã¿ãŒã³ãè³¢ã䜿ãããªããŸãããïŒðªâš
Discussion