ã¯ããã« åããŸããŠãã¬ãã¬ãžãŒãºæ ªåŒäŒç€ŸFEãšã³ãžãã¢ã®æ£®å±±ã§ãã ä»åã¯ãReactéçºã«ãããã³ã³ããŒãã³ãã®å®çŸ©æ¹æ³ã®ïŒã€ã®è§£ãã玹ä»ããŸãã çµè« çµè«ãç°¡æœã«èšèŒãããšä»¥äžã§ãã ããžãã¯ãUIããžãã¯ãšæ¥åããžãã¯ã«åãåããã UIãšUIããžãã¯ã¯å¯çµåãããŠåå©çšæ§ãé«ããã UIãšæ¥åããžãã¯ã¯ççµåã«ããŠåå©çšæ§ãé«ããã èæ¯ãå
·äœçãªäŸã¯åŸè¿°ããŸãã ãªããã®èšäºãæžããã®ã ç§ã調ã¹ãéãã§ã¯Reactã«ãããã³ã³ããŒãã³ãã®å®çŸ©æ¹æ³ã«ããããã¹ããã©ã¯ãã£ã¹ãååšããªãããã§ãã Reactã®å
¬åŒããã¥ã¡ã³ãã«ãããŠãã³ã³ããŒãã³ãã®å®çŸ©æ¹æ³ã®æ¹éã¯èšèŒãç¡ãããšæããŸããããã¯Reactã®ææ³ãšããŠéçºè
ããããžã§ã¯ãã®èŠæš¡ãç¹æ§ãèæ
®ããŠããçšåºŠã®èªç±åºŠãæã£ãŠéçºã§ããããšãå°éããã®ã§ã¯ãªãããšèããŠããŸãã èªç±åºŠãé«ããšéçºæ¹æ³ã®ææ®µãå¢ããŸããææ®µãå€ãã®ã§ã©ã®éçºæ¹æ³ããã¹ããªã®ãReactã®éçºè
ãæ¥ã
ãæ§ã
ãªéçºææ®µã詊è¡é¯èª€ãããã°ãå·çããããè°è«ããŠããŸãã ãããžã§ã¯ãã«åãããŠæé©ãªææ®µãéžæã§ããäœå°ãããã®ã¯è¯ãããšã§ãã ãããããã®èªç±åºŠã®é«ãããã®ãŸãŸã«ããŠããã ã€ãŸãã³ã³ããŒãã³ãã®å®çŸ©ã«ãŒã«ãææ§ãªç¶æ
ã§ãããžã§ã¯ããé²ããšä»¥äžã®ãããªããšãèµ·ããå¯èœæ§ããããŸãã éçºè
ãåã
ãèªç±ã«éçºãé²ããã ã·ã¹ãã å
ã«æ§ã
ãªã³ã³ããŒãã³ãå®è£
ã®æµæŽŸãçãŸããèªåã®å®è£
ãæ£ããã倿ã§ããªããªãã å®è£
æ¹æ³ã®æ£è§£ãåããããäœãã©ãã«æžãã¹ããèªä¿¡ããªãããå®è£
ã¹ããŒããèœã¡ãã ä¿®æ£ãå ãã床ã«è€éããå¢ããåå©çšæ§ãäœäžããã æçµçã«ãããžã§ã¯ãåœåã§ã¯1æéãšèŠç©ãã£ãŠããèŠæš¡ã®ä¿®æ£ã¿ã¹ã¯ã«3æéããã£ãŠããŸãã äžèšãææããããã«ããFEãšã³ãžãã¢ãçŽåŸæãæã£ãŠã³ã³ããŒãã³ãå®è£
ãã§ããã«ãŒã«ãäœãå¿
èŠããããŸããã ã³ã³ããŒãã³ãå®è£
ã«ããã課é¡ã¯UIãšããžãã¯ã®é¢ä¿æ§ ããè°è«ãããã®ã¯ä»¥äžã§ãã ã³ã³ããŒãã³ãã®UIãšããžãã¯ãå¯çµåã«ããã®ããççµåã«ããã®ãã ççµåã®å Žåã¯HooksãæŽ»çšããã®ããã³ã³ããŒãã³ãèªäœãåããã®ãã ããããReactã«ãããããžãã¯ãšã¯äœãïŒ ãããããã®èšäºã«ãããŠã®Reactã«ãããããžãã¯ãšã¯returnã§DOMãè¿ãåã®åŠçãUIã®è¡šç€ºåå²ã®ããšã§ãã const Component = () => { const [state, setState] = useState(true); const data = fetch('https://api.endpoint'); // ... // ããããäžãããžã㯠return ( <h1>{data.title}</h1> <!-- UI衚瀺ã®åå²ããžã㯠--> <p>{state ? 'on' : 'off' }</p> </> ) } äžèšã§ããžãã¯ãšèšã£ãŠãã以äžã®ïŒçš®é¡ã«åé¡ã§ãããšèããŠããŸãã UIããžã㯠æ¥åããžã㯠UIããžã㯠UIããžãã¯ãšã¯ãUIã®å¶åŸ¡ã®ã¿ãç®çãšããããžãã¯ã§ãã å
·äœäŸãšããŠã¯ä»¥äžã®æ§ãªæåãæããããŸãã ãã°ã«ãã¿ã³ã®on/offã®å¶åŸ¡ ãã«ããŠã³ã®ééã®å¶åŸ¡ const Toggle = ({ isActive }) => { return isActive ? <ActiveToggle/> : <InActiveToggle/> } UIããžãã¯ã¯ããæ¥åã«äŸåããªããçŽç²ãªUIã®ãµããŸãã®å¶åŸ¡ã«ãªããŸãã æ¥åããžã㯠æ¥åããžãã¯ãšã¯æ¥åã«ãŒã«ãå®çŸããããã®ããžãã¯ã§ãã 衚瀺ããæ°å€ã«åäœãä»ããçã®æ¥åç¬èªã®ã衚瀺ããŒã¿ã®æŽåœ¢ããããAPIã®çºè¡ãçã該åœããŸãã const Price = () => { const { data } = fetch('https://api.endpoint'); const { quantity, unitPrice ,taxRate, shippingCost } = data; const basePrice = quantity * unitPrice; const price = (basePrice + shippingCost) * taxRate; return ( <h1>äŸ¡æ Œ: {price}å</h1> <p>å
èš³</p> <ul> <li>åæ°: {quantity}å</li> <li>å䟡: {unitPrice}å</li> <li>çšç: {taxRate}%</li> <li>éæ: {shippingCost}å</li> </ul> </> ) } UIãšããžãã¯ã®å¯çµåãççµåã®äœ¿ãåã UIãšããžãã¯ã¯å¿
ããããå¯çµåãè¯ãããšããççµåãè¯ãããšã¯èšãåããŸããã åè¿°ããããžãã¯ã®åé¡ïŒUIããžãã¯ãšæ¥åããžãã¯ïŒã«ãã£ãŠå€ããããšæããŸãã ã³ã³ããŒãã³ãåäœã§èŠããšãããã«åãåããããŠããèšäºãèŠãããŸãã ããããã®1éšåãã«ãŒã«åããŠãããžã§ã¯ãå
šäœã«é©å¿ããããšãããšããããžã§ã¯ãã®èŠæš¡ãæ¥åããžãã¯ã®è€éããèµ·å ããŠã©ãããŠãã«ãŒã«ãå®ãã®ãèŠããå Žé¢ã«ééããŸãããããŠèŠãããªãããã«ãŒã«ãå®ãããã«ãæå³ããªãè€é床ã®é«ãã³ã³ããŒãã³ããçã¿åºãããŸãã äžæãUIãšããžãã¯ã®é¢ä¿æ§ãã«ãŒã«åããããã«ã¯ããžãã¯ã®åé¡ãèæ
®ããå¿
èŠããããŸãã ç§ã®èãã§ã¯ä»¥äžã®äœ¿ãåããæãŸããã§ãã UIãšUIããžãã¯ã¯å¯çµå UIãšæ¥åããžãã¯ã¯ççµå UIããžãã¯ãšæ¥åããžãã¯ã¯ççµå å
·äœçãªå®è£
äŸ å
·äœçã«ã©ã®ããã«å®è£
ãã¹ããäžè¬çãªAtomic designã«æ²¿ã£ãåé¡ã®ã³ãŒãã§èª¬æããŸãã ãŸãåã³ã³ããŒãã³ãã®åºåãã¯ä»¥äžã«ãªããŸãã â» templatesãšpagesã¯ããã§ã¯çããŸãã atoms ã³ã³ããŒãã³ãã®æå°åäœã ããžãã¯ã¯æããªãã ã¹ããŒãã¬ã¹ãªã³ã³ããŒãã³ãã ã·ã¹ãã å
šäœã§æµçšã§ããã molecules atomsãmoleculesã®è€åã³ã³ããŒãã³ãã UIããžãã¯ãæã€ããšãããã ã¹ããŒãã¬ã¹ãªã³ã³ããŒãã³ãã ã·ã¹ãã å
šäœã§æµçšã§ããã organisms atomsãmoleculesã®è€åã³ã³ããŒãã³ãã æ¥åã®ãã¡ã€ã³æ
å ±ãDOMã«æã€ããšãããã ãã®ããã·ã¹ãã å
šäœã§æµçšã§ãããšã¯éããªãã APIãšã®çéãæ¥åããžãã¯ãæã€ããšãããã ãã®ããã¹ããŒãã¬ã¹ãšã¯éããªãã atoms // ã¢ã¯ãã£ããªã©ãžãªãã¿ã³ const ActiveRadio = () => { return ( <div style={{ width: 15px; height: 15px; backgroundColor: white; border: 1px solid black; borderRadius: 10px; display: flex; alignItems: center; justifyContent: center; }}> <span style={{ width: 5px; height: 5px; backgroundColor: blue; borderRadius: 10px; }} /> </div> ) } const Title = ({ text }) => { return <h1 style={{ fontSize: 20px }}>{text}</h1> } atomsã®ç¹åŸŽ ã³ã³ããŒãã³ãã®æå°åäœã ããžãã¯ã¯æããªãã ã¹ããŒãã¬ã¹ãªã³ã³ããŒãã³ãã ã·ã¹ãã å
šäœã§æµçšãããã atomså®è£
ã®æ³šæç¹ atomsã§ã¯åºæ¬çã« return ã®äžã«ããžãã¯ãæžãããããšã¯ãããŸããã ãšããã®ãæèçã«ããžãã¯ãæžããªããšãããããã¯ããæå°åäœãã®ã³ã³ããŒãã³ããªã®ã§è²¬åãå°ããèªç¶ãšæžãå¿
èŠããªããªãã€ã¡ãŒãžã§ãã ããžãã¯ãæžãå¿
èŠãããå Žåã¯ãã®atomsã¯ãæå°åäœããšããŠæ±ãã¹ãã§ãªãå¯èœæ§ããããŸãã æŽã«æå°ã®ã³ã³ããŒãã³ãã«ãªãåŸãªãããçãäœå°ãããããšæããŸãã molecules import { ActiveRadio, InActiveRadio } from '~/atoms/radio'; // on/offãã§ããã©ãžãªãã¿ã³ const Radio = ({ isActive }) => { return isActive ? <ActiveRadio /> : <InActiveRadio /> } import { Button } from '~/atoms/button'; // ãã¡ã€ã«ã¢ããããŒããã©ãŒã & ãã¿ã³ const FileUpload = ({ name, text }) => { const ref = useRef(null); const onClickInput = () => ref.current.click(); return ( <Button onClick={onClickInput} >{text}</Button> <input hidden name={name} ref={ref} type="file" /> </> ); } moleculesã®ç¹åŸŽ atomsãmoleculesã®è€åã³ã³ããŒãã³ãã UIããžãã¯ãæã€ããšãããã ã¹ããŒãã¬ã¹ãªã³ã³ããŒãã³ãã ã·ã¹ãã å
šäœã§æµçšãããã äžèšã®ã©ãžãªãã¿ã³ã®ããã«ã³ãŒãéãå°ãªããŠããä»ã®ã³ã³ããŒãã³ãã«äŸåãããŠããã°moleculesã«è©²åœããŸãã ãããatomsãšmoleculesã®äžçªã®éãã§ãã moleculeså®è£
ã®æ³šæç¹â moleculesã«ãããUIããžãã¯ãšUIã¯åè¿°ã®éããå¯çµåãã«ããã®ãæãŸããã§ãã ãªããªããäŸåé¢ä¿ãç°¡æœã«ãªããããããã§ãã äŸãã°ã以äžã®ããã«UIããžãã¯ã Custom hook ã§å
±éåãããšããŸãã å
šãŠã®pulldownã«å
±éããåŠç // usePulldown.ts export const usePulldown = () => { return ... } äžè¬çãªãã«ããŠã³ // Pulldown.tsx const Pulldown = () => { const pulldownProps = usePulldown() return <Pulldown {...plldownProps}/> } æ€çŽ¢å¯èœãªãã«ããŠã³ // SearchPulldown.tsx const SearchPulldown = () => { const pulldownProps = usePulldown() // ... SearchPulldownç¬èªã®ããžã㯠return ( <!-- other component --> <Pulldown {...plldownProps}/> </> ) } è€æ°éžæå¯èœãªãã«ããŠã³ // MultiPulldown.tsx const MultiPulldown = () => { const pulldownProps = usePulldown() // ... MultiPulldownç¬èªã®ããžã㯠return ( <!-- other component --> <Pulldown {...plldownProps}/> </> ) } ããã§ usePulldown ã®åŠçã®äžã§ SearchPulldown.tsx ã®ã¿ã«äŸå€çãªåŠçã®è¿œå ãå¿
èŠã«ãªã£ããšããŸãã æ ¹æ¬çãªå¯ŸåŠãšããŠã¯ usePulldown ã®äžããäŸå€çãªåŠçãå
¥ãéšåãåãåºããŠä»ã® Pulldown ã MultiPulldown ã«ã倿Žç®æã®ã³ãŒããç§»æ€ããããšã«ãªãããšæããŸãã ãããå
ã
äžå
管çãããŠããã³ãŒããããããéè€ãããæžãæ¹ã¯DRYååã«ãåããŸãã 倧æµã¯ä»¥äžã®ããã« if æãäžè¡å
¥ããŠäŸå€çãªåŠçãèµ°ããããããªçŽæçãªå¯ŸåŠãããŠããŸããŸãã // usePulldown.ts export const usePulldown = (type) => { + if(type === 'searchPulldown') doSomething(); return ... } äŸåãããåŽã® usePulldown ãäŸåããåŽã®ã³ã³ããŒãã³ãã®æ
å ±ãä¿æããããšã«ãªããŸãã ãããªããšåæ¹åã«äŸåãçºçãäŸåé¢ä¿ãããããªããšã«ãªããŸãã ããã¯Reactã«ãããããã°ã©ãã³ã°å
šè¬ãšããŠè¯ããªãå®è£
ããšæããŸãã ãããReactéçºã§äžèšã®ããã«äŒŒããããªãµããŸãã®ã³ã³ããŒãã³ããè€æ°çæãããŠéçºèŠæš¡ã倧ãããªããšèªç¶ãšãã£ãŠããŸããã¡ã§ãã ãããããããã£ãä¿®æ£ãçºçããªãããã«ããUIããžãã¯ããšãDOMãã¯å¯çµåã«å®è£
ããã³ã³ããŒãã³ãå士ã®ç¬ç«æ§ãé«ããæ¹ãåã³ã³ããŒãã³ãã®æ¡åŒµæ§ãé«ããªããŸãã moleculeså±€ã§è€éãªUIã®ãµããŸããæã€ããšã¯å°ãªãã®ã§1ãã¡ã€ã«ã«ãUIããžãã¯ããšãDOMããå¯çµåã«å®è£
ããŠã50è¡ååŸã«åããŠå¯èªæ§ãæ
ä¿ããããšãå¯èœãªã¯ãã§ãã moleculeså®è£
ã®æ³šæç¹â¡ moleculesã³ã³ããŒãã³ãã¯ã·ã¹ãã å
šäœã§æŽ»çšã§ããã¬ãã«ã®åå©çšæ§ãæã€ããšãæãŸããã§ãã ã·ã¹ãã å
šäœã§æŽ»çšã§ãããšã¯ç¹å®ã®æ¥åãã¡ã€ã³ã«çžãããªããšããããšã§ãã äŸãã°ä»¥äžã®ãã¡ã€ã«ã¢ããããŒããã¿ã³ã¯æ±çšæ§ãé«ãåºæ¬çã«ã©ããªå Žé¢ã§ã掻çšã§ããããšæããŸãã import { Button } from '~/atoms/button'; // ãã¡ã€ã«ã¢ããããŒããã©ãŒã & ãã¿ã³ const FileUpload = ({ name, text }) => { const ref = useRef(null); const onClickInput = () => ref.current.click(); return ( <Button onClick={onClickInput} >{text}</Button> <input hidden name={name} ref={ref} type="file" /> </> ); } éã«ç¹å®ã®æ¥åãã¡ã€ã³ã«çžãããŠãããšã¯ä»¥äžã®ãããªç¶æ
ã§ãã éãã¯ãã¿ã³ã®ååãåºå®å€ã«ãªã£ãã ãã§ãã import { Button } from '~/atoms/button'; // ãã¡ã€ã«ã¢ããããŒããã©ãŒã & ãã¿ã³ const FileUpload = ({ name }) => { const ref = useRef(null); const onClickInput = () => ref.current.click(); return ( <Button onClick={onClickInput} >ãããã£ãŒã«ç»åã®ã¢ããããŒã</Button> <input hidden name={name} ref={ref} type="file" /> </> ); } ã©ããªã·ã¹ãã ãéçºããŠãããã®åæããªãã§ããã äžèšã®ãã¡ã€ã«ã¢ããããŒããã¿ã³ã¯ãŠãŒã¶æ
å ±ã®ç»é²ãç·šéãæ
ãç»é¢ã§ããæŽ»çšã§ããªãã³ã³ããŒãã³ãã«ãªãããšãæ³åã§ããŸãã ããã·ã¹ãã ãååç»é²çã®æ©èœãæã£ãŠããããã¡ãã§ããã¡ã€ã«ã¢ããããŒããã¿ã³ã¯å¿
èŠã«ãªãããã§ãã ãããäžèšã®ããã«ãç¹å®ã®æ¥åãã¡ã€ã³ãã«éå®ãããã³ã³ããŒãã³ãã ãšåå©çšã¯ã§ããŸããã åå©çšæ§ã®äœãã³ã³ããŒãã³ããmoleculesã¬ãã«ã§ååšããŠãããšã·ã¹ãã ã®èŠæš¡ã倧ãããªã£ãæã«ä»¥äžã®ã©ã¡ããã®èŠãã察åŠãçºçããŸãã å©çšç®æãéå®çãªã³ã³ããŒãã³ããæ¥µç«¯ã«å¢ãã ç¡çããatomsãpageså
ã§çµã¿åãããŠå®è£
ãªã®ã§moleculesã§ã¯ç¹å®ã®æ¥åãã¡ã€ã³ã«çžãããªãã³ã³ããŒãã³ãã§ããã¹ãã§ãã ç¹å®ã®æ¥åãã¡ã€ã³ãšã¯äœã ç¹å®ã®æ¥åãã¡ã€ã³ãšã¯äœãã«ã€ããŠããã«è©³ããè§ŠããŸãã åçŽã«ãæ¥åãã¡ã€ã³ããšã¯èšããã«ãç¹å®ã®æ¥åãã¡ã€ã³ããšåŒãã§ããã®ã«ã¯æå³ããããŸãã æ¥µç«¯ãªäŸã§ãããéçºããã·ã¹ãã ãåå管çã·ã¹ãã ã§ãã以å€ã®æ
å ±ãæ±ããªãã£ããšããŸãã åå管çã·ã¹ãã ååç»é²æ©èœ ååç·šéæ©èœ ååå逿©èœ ãã®å Žåã«ã¯ãç¹å®ã®æ¥åãã¡ã€ã³ã¯ãååç»é²æ©èœãååç·šéæ©èœãååå逿©èœãã該åœããŸãã ãªã®ã§ä»¥äžã®ãããªã³ã³ããŒãã³ããå®è£
ãããŠãã·ã¹ãã å
šäœã§æŽ»çšã§ããã®ã§moleculesãšããŠæç«ããŸãã import { Button } from '~/atoms/button'; // ãã¡ã€ã«ã¢ããããŒããã©ãŒã & ãã¿ã³ const FileUpload = ({ name }) => { const ref = useRef(null); const onClickInput = () => ref.current.click(); return ( <Button onClick={onClickInput} >ååç»åã®ã¢ããããŒã</Button> <input hidden name={name} ref={ref} type="file" /> </> ); } ãã ã·ã¹ãã ã以äžã®ãããªæ§æã ãšäžèšã®ã³ã³ããŒãã³ãã¯moleculesãšããŠæç«ããŸããã ããªãŒããŒã±ããã·ã¹ãã ãŠãŒã¶ç®¡çæ©èœ ç»é²ãç·šéãåé€ ååç®¡çæ©èœ ç»é²ãç·šéãåé€ moleculeså®è£
ã®æ³šæç¹ãŸãšã é·ããªããŸãããç¹ã«æ³šæãã¹ãã¯ä»¥äžã®2ç¹ã§ãã UIãšUIããžãã¯ãå¯çµåã«ãªã£ãŠããããš ç¹å®ã®æ¥åãã¡ã€ã³ã«çžãããªãããš organisms import { Title, Paragraph } from '~/atoms' import { PriceList } from '~/molecules/PriceList' // äŸ¡æ Œ const Price = () => { const { data } = fetch('https://api.endpoint') const { quantity, unitPrice ,taxRate, shippingCost } = data; const basePrice = quantity * unitPrice; const price = (basePrice + shippingCost) * taxRate; return ( <Title>äŸ¡æ Œ: {price}å</Title> <Paragraph>å
èš³</Paragraph> <PriceList quantity={quantity} taxRate={taxRate} shippingCost={shippingCost} /> </> ) } organismsã®ç¹åŸŽ atomsãmoleculesã®è€åã³ã³ããŒãã³ãã æ¥åã®ãã¡ã€ã³æ
å ±ãDOMã«æã€ããšãããã APIãšã®çéãæ¥åããžãã¯ãæã€ããšãããã organismsã®å®è£
ã®æ³šæç¹ æ¥åããžãã¯ãšUIïŒDOMïŒãççµåã«ããããšã§ãã organismsã¯äžèšã®äŸã®ããã«æ¥åããžãã¯ãæ¥åã®ãã¡ã€ã³æ
å ±ãDOMã«æã¡ãŸãã ãã äžèšã®ã³ãŒãäŸã¯æªãäŸã§ãã 以äžã®ããã«æ¥åããžãã¯ãšUIãå¯çµåããŠãããšæªãç¹ã3ç¹ãããŸãã åå©çšæ§ã®äœäž ããŒã¿æ§é ãèŠããªã æ¥åããžãã¯ãDOMäžã§å®è£
ã§ããŠããŸã 1. åå©çšæ§ã®äœäž æ¥åããžãã¯ãšUIãå¯çµåããŠããã®ã§UIãåå©çšããããŠãéãããå Žé¢ã§ããæŽ»çšã§ããŸããã 2. ããŒã¿æ§é ãèŠããªã ã³ã³ããŒãã³ãã«propsãååšããªãã®ã§æçµçã«ã©ããªæ§é ã®ããŒã¿ãã¬ã³ããªã³ã°ãããã®ãèªã¿åãããã«ã¯DOMãå
šãŠèªã¿è§£ãå¿
èŠããããŸããäžèšã®ã³ãŒãã¯ãŸã ã·ã³ãã«ã§ããDOMã®äžã§æ¡ä»¶åå²ãçºçãããã³ãŒãéãå¢ãããšããªãããã©ããªããŸãã 3. æ¥åããžãã¯ãDOMäžã§å®è£
ã§ããŠããŸã æ¥åããžãã¯ãDOMäžã«å®è£
ããããšãããžãã¯ã®èšèŒå Žæã以äžã®2ãã¿ãŒã³ã«ãªããŸãã returnããäž DOMã®äž æžãå Žæãè€æ°ããã«ãŒã«ãååšããªããšéçºããæã«ã©ã¡ãã«æžãã¹ããè¿·ããçãŸããŸãã äŸãã°ãå
çšæç€ºããã³ãŒãã«ãããŠæ¥åäžã®ä»æ§ãå€ãã£ãŠäŒå¡ã®æã¯ãäŸ¡æ Œã10%offãã«ãªããšããæ¥åããžãã¯ãå ãã£ããšããŸãã äžçªæã£åãæ©ãããããšãããšæçµçã«ã¬ã³ããªã³ã°ãããŠããäŸ¡æ Œã«èšç®åŠçãå ããå®è£
ã«ãªãããã§ãã import { Title } from '~/atoms/Title' import { PriceList } from '~/molecules/PriceList' // äŸ¡æ Œ const Price = () => { const { data } = fetch('https://api.endpoint') - const { quantity, unitPrice ,taxRate, shippingCost } = data + const { quantity, unitPrice ,taxRate, shippingCost, isMember } = data cons t basePrice = quantity cons unitPrice t price = (basePrice + shippingCost) taxRate return ( - <Title>äŸ¡æ Œ: {price}å</Title> + <Title>äŸ¡æ Œ: {isMember ? price * 0.9 : price} <p>å
èš³</p> <PriceList quantity={quantity} taxRate={taxRate} shippingCost={shippingCost} /> </> ) } ãã®äŸã§ã¯ã³ãŒãã®è¡æ°ãçãã§ãããå®éã®organismsã³ã³ããŒãã³ãã«ãªããšã³ãŒãã®è¡æ°ãé·ããªããã¡ã§èªç¶ãšãããã£ã楜ãªå®è£
ã«æµãããããšãå€ãã§ãã ãããŠäœããåä»ãªã®ã¯äžèšã®äŸã®ããã«äžé
æŒç®å1ã€ã ãšå¯ŸããŠæªããªãããã«èŠããããšã§ãã ããã«æŽã«ããäžçš®é¡ããŽãŒã«ãäŒå¡ã远å ããããšã©ãã§ããããïŒ import { Title } from '~/atoms/Title' import { PriceList } from '~/molecules/PriceList' // äŸ¡æ Œ const Price = () => { const { data } = fetch('https://api.endpoint') - const { quantity, unitPrice ,taxRate, shippingCost, isMember } = data + const { quantity, unitPrice ,taxRate, shippingCost, isMember, isGoldMember } = data cons t basePrice = quantity cons unitPrice t price = (basePrice + shippingCost) taxRate return ( - <Title>äŸ¡æ Œ: {isMember ? price * 0.9 : price} + <Title>äŸ¡æ Œ: {isGoldMember + ? price * 0.8 + : isMember + ? price * 0.9 + : price + }å <p>å
èš³</p> <PriceList quantity={quantity} taxRate={taxRate} shippingCost={shippingCost} /> </> ) } å
ã
ã®ã³ãŒãã§DOMã«äžé
æŒç®åãå®è£
ãããŠãããšèªç¶ãšããã«è¿œå ããå®è£
ãããŠããŸãããšããããšæããŸãã ãããªããšæ¥åããžãã¯ã return ã®äžã ãã§ãªãDOMã®äžã«ãååšããããšã«ãªããŸãã ããžãã¯ã®å®è£
ç®æãã«ãŒã«ããªãè€æ°ç®æã«ãªãããšã§å¯èªæ§ãäžæ°ã«èœã¡ãŸãã DOMãåå©çšããããã«å¥ãã¡ã€ã«ã«åãåºãããšããŠãããžãã¯ãå«ãããšã§åçŽã«DOMã ããåãåºãããšãã§ããªããªããŸãã æéç äžèšã®è¯ããªã2ç¹ãæéããããã«ã¯ãæ¥åããžãã¯ãšUIãççµåã«ããå¿
èŠããããŸãã å
·äœçã«ã¯ãorganismsã®äžã§ãã³ã³ããŒãã³ãã2ã€ã«åããŸãã organisms/ â Presentations/ â â Price.tsx ïŒUIã責åãšããã³ã³ããŒãã³ãïŒ â â Containers/ â PriceContainer.tsx ïŒæ¥åããžãã¯ã責åãšããã³ã³ããŒãã³ãïŒ ä»åŸã2ã€ã®ã³ã³ããŒãã³ãã¯ä»¥äžã®åŒã³æ¹ãããŸãã UIã責åãšããã³ã³ããŒãã³ã: Presentational Components æ¥åããžãã¯ã責åãšããã³ã³ããŒãã³ã: Container Components PresentationalComponents // organisms/Price.tsx import { Title } from '~/atoms/Title' import { PriceList } from '~/molecules/PriceList' // äŸ¡æ Œ const Price = ({ price, quantity, taxRate, shippingCost }) => { return ( <Title>äŸ¡æ Œ: {price}å</Title> <p>å
èš³</p> <PriceList quantity={quantity} taxRate={taxRate} shippingCost={shippingCost} /> </> ) } PresentationalComponentsã®ç¹åŸŽ ã¹ããŒãã¬ã¹ãªã³ã³ããŒãã³ãã§ã ã©ã®ããã«ããŒã¿ã衚瀺ãããïŒ ãã責åãšããŸãã UI衚瀺ã®ã¿ã責任ç¯å²ãšããŠåãåºãããŠããã®ã§å¥ã®å Žæã§åå©çšãå¯èœã«ãªããŸãã PresentationalCompornents ã¯æ¥åããžãã¯ãæããªããããstorybookçã®UIã®ã©ã€ãã©ãªåã容æã«ã§ããŸãã propsã衚瀺ãã¹ãããŒã¿ã®æ§é ãã®ãã®ã«ãªããŸãã PresentationalComponentså®è£
ã®æ³šæç¹ propsãAPIã®ããŒã¿æ§é ã«äŸåãããªãããšã§ãã ãããŸã§ããã©ã®ããã«ããŒã¿ã衚瀺ãããïŒãã«æ³šç®ããŸãã APIã®ããŒã¿æ§é ã«äŸåãããšUIã®æ§é ãšããŒã¿æ§é ãä¹é¢ããŠèŠããå®è£
ã匷ãããããããŸãã APIã®ããŒã¿æ§é ã®å€æŽãé »çºããFEã®æ¹ä¿®å·¥æ°ãå¢ãããšBEåŽãFEã®è² è·ã軜æžããããã«UIããªãã³ãªAPIå®çŸ©ãæèãããããŸãã ãããªã£ãŠããŸããšBEå®è£
ãUIã«åŒã£åŒµãããŠæ¥åãã¡ã€ã³ã«æ²¿ã£ãå®è£
ãã§ããFEãBEãæ¡åŒµæ§ã®äœãå®è£
ã«ãªã£ããããŠããŸããŸãã ContainerComponents // organisms/PriceContainer.tsx const PriceContainer = () => { const { data } = fetch('https://api.endpoint') const { quantity, unitPrice ,taxRate, shippingCost } = data; const basePrice = quantity * unitPrice; const price = (basePrice + shippingCost) * taxRate; return ( <Price price={price} quantity={quantity} taxRate={taxRate} shippingCost={shippingCost} /> ) } ContainerComponentsã®ç¹åŸŽ æ¥åããžãã¯ã®å®è£
ã«çç®ããã³ã³ããŒãã³ãã«ãªããŸãã ã©ã衚瀺ããããã®è²¬ä»»ã¯ãã¹ãŠ PresentationalComponents ã«å§ããŸãã ContainerComponents ã§ã¯äœçœ®ã®èª¿æŽãäœçœã®ããã«ã¹ã¿ã€ã«ãåœãŠãããšããããŸããã Presentational/Container Componentsã®å®è£
æ¹é organismsã®äžã§ã PresentationalComponents ãš ContainerComponents ã¯ãã£ã¬ã¯ããªãåºåãããŠæç¢ºã«éããã®ãšããŠå®çŸ©ããŠããã®ãè¯ãã§ãã ããããããšã§ä¿®æ£ãå¿
èŠãªå Žåã«ã©ã¡ãã®ã³ã³ããŒãã³ããä¿®æ£ãã¹ãããæç¢ºã«å€æãä»ããŸãã ãã ã³ã³ããŒãã³ãã®å®è£
ãå§ããåãã Presentational/Container Components ãã©ããã£ãæ§é ã«ãã¹ããèšèšããããšã¯é£æåºŠãéåžžã«é«ãã§ãã ãŸã㯠Presentational Components ãã²ãããå®è£
ããŠãããç»é¢ãŸã§å®è£
ããã®ãæãŸããã§ãã ãã®åŸAPIãpagesã³ã³ããŒãã³ãã§ç¹ããã¿ãŸãã pagesã§APIãçºè¡ãããšorganismsã® Presentational Components ã蟿ã£ãŠæ«ç«¯ã®atomsã³ã³ããŒãã³ããŸã§ããŒã¿ããã±ããªã¬ãŒããŠããããšã«ãªããŸãã ãã®æã«propsãšããŠåãåã£ãããŒã¿ãç¡å å·¥ã§ãã®ãŸãŸæŽã«æ«ç«¯ã®ã³ã³ããŒãã³ãã«æž¡ãå Žé¢ãçºçããã¯ãã§ãã ãã®å Žé¢ã§ Container Components ã®å®è£
ãæ€èšããŠãããšããã®ãææ»ããå°ãªãã§ããŸãã çµè« ãŸãšãã§ãããçµè«ä»¥äžã®ãããªæ§æã»ã«ãŒã«ã§ã³ã³ããŒãã³ããåå²ããŸããã atoms ã³ã³ããŒãã³ãã®æå°åäœã ããžãã¯ã¯æããªãã ã¹ããŒãã¬ã¹ãªã³ã³ããŒãã³ãã ã·ã¹ãã å
šäœã§æµçšã§ããã molecules atomsãmoleculesã®è€åã³ã³ããŒãã³ãã UIããžãã¯ãæã€ããšãããã ã¹ããŒãã¬ã¹ãªã³ã³ããŒãã³ãã ã·ã¹ãã å
šäœã§æµçšã§ããã organisms atomsãmoleculesã®è€åã³ã³ããŒãã³ãã æ¥åã®ãã¡ã€ã³æ
å ±ãDOMã«æã€ããšãããã ãã®ããã·ã¹ãã å
šäœã§æµçšã§ãããšã¯éããªãã APIãšã®çéãæ¥åããžãã¯ãæã€ããšãããã PresentationalComponentsãšContainerComponentsãåããã åŸãæ©æµ Atomic designã®åºåãæç¢ºå atoms/moleculesã®åå©çšæ§ã»æ¡åŒµæ§ã®æ
ä¿ organismsã®UIãšæ¥åããžãã¯ã®è²¬åãã³ã³ããŒãã³ãåäœã§åé¢ å
šäœãéããŠã©ãã«äœãå®è£
ãã¹ããã倿ã§ããããã«ãªãç¡çãªå®è£
ãçãŸããªãä»çµã¿ãå®çŸã§ããŸããã ãããã« ãããã§ããã§ããããã äžèšã®ã³ã³ããŒãã³ãéçºã®æ§æãã©ã®ãããžã§ã¯ãã§ãäžæãè¡ããšã¯éããªãã§ãããäœã1ã€ã§ãåèã«ãªãç®æãããã°å¹žãã§ããç§ã®æå±ããHRããã¯äºæ¥éšã¯çºè¶³ããŠãŸã æ¥ãæµ
ãããããã¯ãã®ç¶æ³ã0-1ãã§ãŒãºã«ãããŸãããªã®ã§ãããã£ãã©ãããæ§æã§éçºãé²ããã¹ãããªã©ãæ€èšã»æ±ºå®ããŠãããæ©äŒãå€ãã§ãããã®èšäºãã芧ã«ãªãããã®äºæ¥éšãäžç·ã«çãäžããŠã¿ãããªãšæãæ¹ã1人ã§ãå¢ããã°å¬ããæããŸãïŒïŒè©³ãã㯠ãã¡ã ïŒ var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(e){var n=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,t=0,r={},a={manual:e.Prism&&e.Prism.manual,disableWorkerMessageHandler:e.Prism&&e.Prism.disableWorkerMessageHandler,util:{encode:function e(n){return n instanceof i?new i(n.type,e(n.content),n.alias):Array.isArray(n)?n.map(e):n.replace(/&/g,"&").replace(/ =g.reach);A+=w.value.length,w=w.next){var E=w.value;if(n.length>e.length)return;if(!(E instanceof i)){var P,L=1;if(y){if(!(P=l(b,A,e,m))||P.index>=e.length)break;var S=P.index,O=P.index+P[0].length,j=A;for(j+=w.value.length;S>=j;)j+=(w=w.next).value.length;if(A=j-=w.value.length,w.value instanceof i)continue;for(var C=w;C!==n.tail&&(j g.reach&&(g.reach=W);var z=w.prev;if(_&&(z=u(n,z,_),A+=_.length),c(n,z,L),w=u(n,z,new i(f,p?a.tokenize(N,p):N,k,N)),M&&u(n,w,M),L>1){var I={cause:f+","+d,reach:W};o(e,n,t,w.prev,A,I),g&&I.reach>g.reach&&(g.reach=I.reach)}}}}}}function s(){var e={value:null,prev:null,next:null},n={value:null,prev:e,next:null};e.next=n,this.head=e,this.tail=n,this.length=0}function u(e,n,t){var r=n.next,a={value:t,prev:n,next:r};return n.next=a,r.prev=a,e.length++,a}function c(e,n,t){for(var r=n.next,a=0;a ))*-->)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^ $|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s '"]+/}},cdata:{pattern:/ /i,greedy:!0},tag:{pattern:/ \/=$ \/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^ \/]+/,inside:{punctuation:/^ \/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.languages.markup.doctype.inside["internal-subset"].inside=Prism.languages.markup,Prism.hooks.add("wrap",(function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&/,"&"))})),Object.defineProperty(Prism.languages.markup.tag,"addInlined",{value:function(a,e){var s={};s["language-"+e]={pattern:/(^ $)/i,lookbehind:!0,inside:Prism.languages[e]},s.cdata=/^ $/i;var t={"included-cdata":{pattern:/ /i,inside:s}};t["language-"+e]={pattern:/[\s\S]+/,inside:Prism.languages[e]};var n={};n[a]={pattern:RegExp("( ]*>)(?: ))*\\]\\]>|(?! )".replace(/__/g,(function(){return a})),"i"),lookbehind:!0,greedy:!0,inside:t},Prism.languages.insertBefore("markup","cdata",n)}}),Object.defineProperty(Prism.languages.markup.tag,"addAttribute",{value:function(a,e){Prism.languages.markup.tag.inside["special-attr"].push({pattern:RegExp("(^|[\"'\\s])(?:"+a+")\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s'\">=]+(?=[\\s>]))","i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[e,"language-"+e],inside:Prism.languages[e]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup,Prism.languages.xml=Prism.languages.extend("markup",{}),Prism.languages.ssml=Prism.languages.xml,Prism.languages.atom=Prism.languages.xml,Prism.languages.rss=Prism.languages.xml; !function(s){var e=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;s.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:RegExp("@[\\w-](?:[^;{\\s\"']|\\s+(?!\\s)|"+e.source+")*?(?:;|(?=\\s*\\{))"),inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+e.source+"|(?:[^\\\\\r\n()\"']|\\\\[^])*)\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+e.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+e.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:e,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},s.languages.css.atrule.inside.rest=s.languages.css;var t=s.languages.markup;t&&(t.tag.addInlined("style","css"),t.tag.addAttribute("style","css"))}(Prism); Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[ ]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/}; Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp("(^|[^\\w$])(?:NaN|Infinity|0[bB][01]+(?:_[01]+)*n?|0[oO][0-7]+(?:_[0-7]+)*n?|0[xX][\\dA-Fa-f]+(?:_[\\dA-Fa-f]+)*n?|\\d+(?:_\\d+)*n|(?:\\d+(?:_\\d+)*(?:\\.(?:\\d+(?:_\\d+)*)?)?|\\.\\d+(?:_\\d+)*)(?:[Ee][+-]?\\d+(?:_\\d+)*)?)(?![\\w$])"),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==| >>?=?|[-+*/%&|^!= ]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:RegExp("((?:^|[^$\\w\\xA0-\\uFFFF.\"'\\])\\s]|\\b(?:return|yield))\\s*)/(?:(?:\\[(?:[^\\]\\\\\r\n]|\\\\.)*\\]|\\\\.|[^/\\\\\\[\r\n])+/[dgimyus]{0,7}|(?:\\[(?:[^[\\]\\\\\r\n]|\\\\.|\\[(?:[^[\\]\\\\\r\n]|\\\\.|\\[(?:[^[\\]\\\\\r\n]|\\\\.)*\\])*\\])*\\]|\\\\.|[^/\\\\\\[\r\n])+/[dgimyus]{0,7}v[dgimyus]{0,7})(?=(?:\\s|/\\*(?:[^*]|\\*(?!/))*\\*/)*(?:$|[\r\n,.;:})\\]]|//))"),lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:Prism.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:Prism.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),Prism.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),Prism.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),Prism.languages.markup&&(Prism.languages.markup.tag.addInlined("script","javascript"),Prism.languages.markup.tag.addAttribute("on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)","javascript")),Prism.languages.js=Prism.languages.javascript; !function(e){e.languages.diff={coord:[/^(?:\*{3}|-{3}|\+{3}).*$/m,/^@@.*@@$/m,/^\d.*$/m]};var n={"deleted-sign":"-","deleted-arrow":" ",unchanged:" ",diff:"!"};Object.keys(n).forEach((function(a){var i=n[a],r=[];/^\w+$/.test(a)||r.push(/\w+/.exec(a)[0]),"diff"===a&&r.push("bold"),e.languages.diff[a]={pattern:RegExp("^(?:["+i+"].*(?:\r\n?|\n|(?![\\s\\S])))+","m"),alias:r,inside:{line:{pattern:/(.)(?=[\s\S]).*(?:\r\n?|\n)?/,lookbehind:!0},prefix:{pattern:/[\s\S]/,alias:/\w+/.exec(a)[0]}}}})),Object.defineProperty(e.languages.diff,"PREFIXES",{value:n})}(Prism); !function(t){var n=t.util.clone(t.languages.javascript),e="(?:\\{ *\\.{3}(?:[^{}]| )*\\})";function a(t,n){return t=t.replace(/ /g,(function(){return"(?:\\s|//.*(?!.)|/\\*(?:[^*]|\\*(?!/))\\*/)"})).replace(/ /g,(function(){return"(?:\\{(?:\\{(?:\\{[^{}]*\\}|[^{}])*\\}|[^{}])*\\})"})).replace(/ /g,(function(){return e})),RegExp(t,n)}e=a(e).source,t.languages.jsx=t.languages.extend("markup",n),t.languages.jsx.tag.pattern=a(" +(?:[\\w.:$-]+(?:=(?:\"(?:\\\\[^]|[^\\\\\"])*\"|'(?:\\\\[^]|[^\\\\'])*'|[^\\s{'\"/>=]+| ))?| ))* */?)?>"),t.languages.jsx.tag.inside.tag.pattern=/^ \/]*/,t.languages.jsx.tag.inside["attr-value"].pattern=/=(?!\{)(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s'">]+)/,t.languages.jsx.tag.inside.tag.inside["class-name"]=/^[A-Z]\w*(?:\.[A-Z]\w*)*$/,t.languages.jsx.tag.inside.comment=n.comment,t.languages.insertBefore("inside","attr-name",{spread:{pattern:a(" "),inside:t.languages.jsx}},t.languages.jsx.tag),t.languages.insertBefore("inside","special-attr",{script:{pattern:a("= "),alias:"language-javascript",inside:{"script-punctuation":{pattern:/^=(?=\{)/,alias:"punctuation"},rest:t.languages.jsx}}},t.languages.jsx.tag);var s=function(t){return t?"string"==typeof t?t:"string"==typeof t.content?t.content:t.content.map(s).join(""):""},g=function(n){for(var e=[],a=0;a 0&&e[e.length-1].tagName===s(o.content[0].content[1])&&e.pop():"/>"===o.content[o.content.length-1].content||e.push({tagName:s(o.content[0].content[1]),openedBraces:0}):e.length>0&&"punctuation"===o.type&&"{"===o.content?e[e.length-1].openedBraces++:e.length>0&&e[e.length-1].openedBraces>0&&"punctuation"===o.type&&"}"===o.content?e[e.length-1].openedBraces--:i=!0),(i||"string"==typeof o)&&e.length>0&&0===e[e.length-1].openedBraces){var r=s(o);a 0&&("string"==typeof n[a-1]||"plain-text"===n[a-1].type)&&(r=s(n[a-1])+r,n.splice(a-1,1),a--),n[a]=new t.Token("plain-text",r,null,r)}o.content&&"string"!=typeof o.content&&g(o.content)}};t.hooks.add("after-tokenize",(function(t){"jsx"!==t.language&&"tsx"!==t.language||g(t.tokens)}))}(Prism); !function(e){e.languages.typescript=e.languages.extend("javascript",{"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|type)\s+)(?!keyof\b)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?:\s* ]| ]| ]*>)*>)*>)?/,lookbehind:!0,greedy:!0,inside:null},builtin:/\b(?:Array|Function|Promise|any|boolean|console|never|number|string|symbol|unknown)\b/}),e.languages.typescript.keyword.push(/\b(?:abstract|declare|is|keyof|readonly|require)\b/,/\b(?:asserts|infer|interface|module|namespace|type)\b(?=\s*(?:[{_$a-zA-Z\xA0-\uFFFF]|$))/,/\btype\b(?=\s*(?:[\{*]|$))/),delete e.languages.typescript.parameter,delete e.languages.typescript["literal-property"];var s=e.languages.extend("typescript",{});delete s["class-name"],e.languages.typescript["class-name"].inside=s,e.languages.insertBefore("typescript","function",{decorator:{pattern:/@[$\w\xA0-\uFFFF]+/,inside:{at:{pattern:/^@/,alias:"operator"},function:/^[\s\S]+/}},"generic-function":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s* ]| ]| ]*>)*>)*>(?=\s*\()/,greedy:!0,inside:{function:/^#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/,generic:{pattern:/ \/=$ \/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/g,a=RegExp("(?:__|[^\r\n<])*(?:\r\n?|\n|(?:__|[^\r\n<])(?![^\r\n]))".replace(/__/g,(function(){return i.source})),"gi"),s=!1;Prism.hooks.add("before-sanity-check",(function(i){var a=i.language;e.test(a)&&!i.grammar&&(i.grammar=Prism.languages[a]=Prism.languages.diff)})),Prism.hooks.add("before-tokenize",(function(i){s||Prism.languages.diff||Prism.plugins.autoloader||(s=!0,console.warn("Prism's Diff Highlight plugin requires the Diff language definition (prism-diff.js).Make sure the language definition is loaded or use Prism's Autoloader plugin."));var a=i.language;e.test(a)&&!Prism.languages[a]&&(Prism.languages[a]=Prism.languages.diff)})),Prism.hooks.add("wrap",(function(s){var r,n;if("diff"!==s.language){var g=e.exec(s.language);if(!g)return;r=g[1],n=Prism.languages[r]}var f=Prism.languages.diff&&Prism.languages.diff.PREFIXES;if(f&&s.type in f){var u,l=s.content.replace(i,"").replace(/</g,"<").replace(/&/g,"&"),t=l.replace(/(^|[\r\n])./g,"$1");u=n?Prism.highlight(t,n,r):Prism.util.encode(t);var o,m=new Prism.Token("prefix",f[s.type],[/\w+/.exec(s.type)[0]]),d=Prism.Token.stringify(m,s.language),c=[];for(a.lastIndex=0;o=a.exec(u);)c.push(d+o[0]);/(?:^|[\r\n]).$/.test(l)&&c.push(d),s.content=c.join(""),n&&s.classes.push("language-"+r)}}))}}(); code[class*=language-],pre[class*=language-]{color:#f8f8f2;background:0 0;text-shadow:0 1px rgba(0,0,0,.3);font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto;border-radius:.3em}:not(pre)>code[class*=language-],pre[class*=language-]{background:#272822}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#8292a2!important}.token.punctuation{color:#DA71D6!important}.token.namespace{opacity:.7!important}.token.constant,.token.deleted,.token.property,.token.symbol,.token.tag{color:#f92672!important}.token.boolean,.token.number{color:#ae81ff!important}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#CE9278!important}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url,.token.variable{color:#f8f8f2!important}.token.atrule,.token.attr-value,.token.class-name,.token.function{color:#D4D59A!important}.token.keyword{color:#4689CC!important}.token.important,.token.regex{color:#fd971f!important}.token.bold,.token.important{font-weight:700!important}.token.italic{font-style:italic}.token.entity{cursor:help} pre.diff-highlight>code .token.deleted:not(.prefix),pre>code.diff-highlight .token.deleted:not(.prefix){background-color:rgba(255,0,0,.1);color:inherit;display:block}pre.diff-highlight>code .token.inserted:not(.prefix),pre>code.diff-highlight .token.inserted:not(.prefix){background-color:rgba(0,255,128,.1);color:inherit;display:block} .entry h1 { font-weight: 700; } .entry h2 { border:none; font-weight: 700; } .language-tsx { color: #43B3FE!important; filter: contrast(110%); } .language-tsx .boolean { color: #43B3FE!important; } .language-tsx .function-variable { color: #41C0A1!important; } .language-tsx .plain-text { color: #8292a2!important } .language-tsx .tag { color: #41C0A1!important } .language-tsx .tag .punctuation { color: #8292a2!important } .language-tsx .language-javascript{ color: #D5D5A4!important } .language-diff .inserted{ color: #41C0A1!important }