Ant-design: HOC์™€ ํ•จ๊ป˜ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š”`antd`์˜ ๊ตฌ์„ฑ ์š”์†Œ ๋ชฉ๋ก

์— ๋งŒ๋“  2017๋…„ 02์›” 14์ผ  ยท  65์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: ant-design/ant-design

์ผ๋ฐ˜์ ์ธ ์‚ฌ์šฉ ์‚ฌ๋ก€๊ฐ€ ์•„๋‹ˆ๋ฏ€๋กœ ์šฐ์„  ์ˆœ์œ„๊ฐ€ ๋‚ฎ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์šฐ๋ฆฌ๋Š” ์—ฌ์ „ํžˆ ํ† ๋ก ํ•˜๊ณ  ๊ทธ๊ฒƒ์„ ๊ฐœ์„ ํ•˜๊ธฐ ์œ„ํ•ด ๋…ธ๋ ฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Inactive โ“FAQ ๐Ÿ—ฃ Discussion

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

์ด ๋ฌธ์ œ๋Š” ๋ฌธ์„œ์—์„œ ์‹ค์ œ๋กœ ์–ธ๊ธ‰๋˜์–ด์•ผํ•ฉ๋‹ˆ๋‹ค.์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ์„ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด์ด ๋ฒ„๊ทธ๋ฅผ ์กฐ์‚ฌํ•˜๋Š” ๋ฐ ํ•˜๋ฃจ ์ข…์ผ ๋‚ญ๋น„ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋‹น์‹ ์ด ์•ˆํ‹ฐ ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜๊ณ  React ํ‚ค๋ฅผ ์ค‘๊ณ„ํ•˜๋Š” ๊ฒƒ์„ ์•Œ์•„๋‚ด๋Š” ๋ฐ ๋„ˆ๋ฌด ๋งŽ์€ ์‹œ๊ฐ„์„ ๋‚ญ๋น„ ํ•  ํ•„์š”๊ฐ€ ์—†๋„๋ก ๊ฒฝ๊ณ ๋ฅผ ํ•ด์ฃผ์„ธ์š”. ๊ทธ๋ฆฌ๊ณ  ์ด์ œ ๋‹น์‹ ์€ ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜์žˆ๋Š” ๋งŽ์€ HOC ๋˜๋Š” ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ์— ๋งค์šฐ ์ทจ์•ฝํ•ฉ๋‹ˆ๋‹ค.
์ด๊ฒƒ์€ ์ •๋ง ๋ถ€๋„๋Ÿฌ์šด ์ผ์ž…๋‹ˆ๋‹ค. ๋‹ค์Œ ๋ฉ”์ด์ € ๋ฒ„์ „์—์„œ ์ˆ˜์ •ํ•˜์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.

๋ชจ๋“  65 ๋Œ“๊ธ€

API์˜ ์ผ๋ถ€๋กœ key ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ผ๋ถ€ ๊ตฌ์„ฑ ์š”์†Œ์˜ ๊ฒฝ์šฐ ๋ชจ๋“  API ์ด๋ฆ„์˜ ์ด๋ฆ„์„ ๋ฐ”๊ฟ€ ๋•Œ๊นŒ์ง€์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์˜ˆ

key => id
expandedKeys => expandedIds
selectedKeys => selectedIds
....

๋ธŒ๋ ˆ์ดํ‚น ์ฒด์ธ์ง€์ด์ง€๋งŒ ์ด๋Ÿฌํ•œ ์ข…๋ฅ˜์˜ ๋ธŒ๋ ˆ์ดํ‚น ์ฒด์ธ์ง€๋Š” antd-codemod ๋กœ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ๊ทธ๋ ‡๊ฒŒ ํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์‹ญ๋‹ˆ๊นŒ?

๋‚˜๋Š” ์ด๊ฒƒ์ด ์ข‹์€ ์ƒ๊ฐ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

codemod ์†”๋ฃจ์…˜์˜ ํŒฌ์ด ์•„๋‹™๋‹ˆ๋‹ค.
๋‚ด ๊ด€์ ์— ๋ถˆ๊ณผํ•˜์ง€๋งŒ ์Šฌํ”„๊ฒŒ๋„ ๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ํ™˜์˜๋ฐ›๋Š” ๊ฒƒ๋ณด๋‹ค ๋” ๋ฐ˜๋ฐœ ์ ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์ปดํฌ๋„ŒํŠธ๋ฅผ ์ปค์Šคํ…€ ์ปดํฌ๋„ŒํŠธ์— ์ž„๋ฒ ๋“œํ•˜๋Š” ๊ฒƒ์€ React์˜ ์ผ๋ฐ˜์ ์ธ ๊ด€ํ–‰์ž…๋‹ˆ๋‹ค.

๊ทธ๊ฒƒ์„ ๊ณ ์น˜๊ณ  ์˜์‹ฌ์˜ ์—ฌ์ง€์—†์ด ๊ฐœ๋ฏธ ๋””์ž์ธ ์ฑ„ํƒ์ด ๋น ๋ฅด๊ฒŒ ์ฆ๊ฐ€ํ•˜๋Š” ๊ฒƒ์„๋ณด์‹ญ์‹œ์˜ค.

Ant Design์€ ์ •๋ง ๋งค๋ ฅ์ ์ด๋ฉฐ react-bootstrap์„ ๋– ๋‚˜๊ณ  ์‹ถ์€ ์ฒซ ๋ฒˆ์งธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค.

๋ฟก ๋นต๋€จ

API์˜ ์ผ๋ถ€๋กœ ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ผ๋ถ€ ๊ตฌ์„ฑ ์š”์†Œ์˜ ๊ฒฝ์šฐ ๋ชจ๋“  API ์ด๋ฆ„์˜ ์ด๋ฆ„์„ ๋ฐ”๊ฟ€ ๋•Œ๊นŒ์ง€์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

@ afc163 ํ•ด๋‹น API์˜ ์ด๋ฆ„์„ ๋ฐ”๊ฟ€ ์ˆ˜ ์—†์œผ๋ฉด์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ์ œ๊ณต ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. https://github.com/react-component/collapse/issues/73#issuecomment -323626120

์ด๊ฒƒ์„ ๋ฌธ์„œ์— ์ถ”๊ฐ€ํ•ด์•ผํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์‹ญ๋‹ˆ๊นŒ?

@benjycui ์ดํ•ดํ•ฉ๋‹ˆ๋‹ค.

์–ด์จŒ๋“  ๊ทธ๊ฒƒ์€ ๊ฒฐ๊ตญ ์ฐจ๋‹จ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์‹œ๊ฐ„์„๋‚ด์–ด ๋‹ต๋ณ€ ํ•ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

@benjycui ๋‹น์‹ ์ด ์ œ์•ˆํ•œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ์กฐ์‚ฌํ•˜๊ณ  ์žˆ์—ˆ์ง€๋งŒ ์ ์ ˆํ•œ ํ•ด๊ฒฐ์ฑ…์ด ์•„๋‹ˆ๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋ž˜ํ•‘ ํ•  ๋•Œ ๋‚ด๋ถ€ ์ƒํƒœ๋„ ๊ฐ–๊ธฐ๋ฅผ ์›ํ•ฉ๋‹ˆ๋‹ค. ์ œ์•ˆ ๋œ ์†”๋ฃจ์…˜์œผ๋กœ๋Š” ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
๋˜ํ•œ ์ด๊ฒƒ์€ ์ž‘์€ ๋ฌธ์ œ๊ฐ€ ์•„๋‹ˆ๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ณตํ†ต ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๊ฒฉ๋ฆฌ ํ•  ์ˆ˜ โ€‹โ€‹์—†๋‹ค๋Š” ๊ฒƒ์€ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ ๋‚ด์—์„œ ๋™์ผํ•œ ์ฝ”๋“œ๊ฐ€ ์—ฌ๋Ÿฌ ๋ฒˆ ๋ฐ˜๋ณต๋œ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์ด ํฌ๋ฉด antd๋ฅผ ์ „ํ˜€ ์ฑ„ํƒํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ๊ฑด์„ค์ ์ธ ๋น„ํ‰๊ฐ€๋กœ ๊ฐ„์ฃผํ•˜์‹ญ์‹œ์˜ค.
์ž‘์—… ํ•ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!

์ด๊ฒƒ์€ ์ž‘์€ ๋ฌธ์ œ๊ฐ€ ์•„๋‹ˆ๋ฉฐ Ant Design ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ์„ ๋•Œ ์˜ˆ์ƒํ•˜์ง€ ๋ชปํ•œ ๋ฌธ์ œ๋ผ๊ณ  ๋™์˜ํ–ˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ์ •์˜ ๊ตฌ์„ฑ ์š”์†Œ์˜ ๋ชจ๋ฒ” ์‚ฌ๋ก€๋Š” React ํ”„๋กœ์ ํŠธ ์ „์ฒด์—์„œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๊ฐœ์ธ์ ์œผ๋กœ ์ €๋Š” Ant Design์„ ์ •๋ง ์ข‹์•„ํ•˜์ง€๋งŒ ์ผ๋ถ€์—๊ฒŒ๋Š” ์ด๊ฒƒ์ด ๊ฑฐ๋ž˜๋ฅผ ๋ฐฉํ•ด ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๊ฐ€์˜ค๋Š” Ant Design v3์—์„œ์ด ๊ธฐ๋Šฅ์ด ๊ฐœ์„ ๋˜๋Š” ๊ฒƒ์„๋ณด๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

v3์—์„œ ์ด์— ๋Œ€ํ•œ ํ•ด๊ฒฐ์ฑ…์„ ์ฐพ์œผ์‹ญ์‹œ์˜ค.

์ด ํŒจํ‚ค์ง€๊ฐ€ ์ถœ์‹œ ๋œ ํ›„ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค (์•„๋งˆ๋„).

๋ฉ”๋‰ด๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  <Icon /> ๋ฉ”๋‰ด์— React Router <Link /> ํƒœ๊ทธ๋ฅผ ์ค‘์ฒฉํ•˜์—ฌ navbar๋ฅผ ์ƒ์„ฑํ•˜๋ ค๊ณ  ์‹œ๋„ํ–ˆ์Šต๋‹ˆ๋‹ค (์ž˜๋ชป๋œ ๊ฒฝ์šฐ ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค).

๋” ์„ ํ˜ธํ•˜๋Š” ์†”๋ฃจ์…˜์ด ์žˆ์Šต๋‹ˆ๊นŒ?

IMHO,์ด ์Šค๋ ˆ๋“œ๋Š” ๊ณต์‹ ๋ฌธ์„œ์— ์žˆ์–ด์•ผํ•ฉ๋‹ˆ๋‹ค.์ด ๋ฌธ์ œ๋Š” ๋งŽ์€ ์‚ฌ์šฉ์ž์—๊ฒŒ ๊ฑฐ๋ž˜๋ฅผ ๋ฐฉํ•ด ํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
๋ฌธ์„œ๋Š” ์ƒํƒœ๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ๋Œ€์•ˆ์œผ๋กœ https://github.com/react-component/collapse/issues/73#issuecomment -323626120์„ ์–ธ๊ธ‰ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

๋‚˜๋Š” ๋ฌธ์„œ์—์„œ ์ด๊ฒƒ์— ๋Œ€ํ•œ ์–ธ๊ธ‰์„ ํ™•์‹คํžˆ ๊ฐ์‚ฌํ–ˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค! ๋‚˜๋Š” ์ด๋Ÿฐ ์ผ์„ํ•˜๋ ค๊ณ ํ–ˆ์ง€๋งŒ ์ž‘๋™ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋งŽ์€ ์‹œ๊ฐ„์„ ๋‚ญ๋น„ํ–ˆ์Šต๋‹ˆ๋‹ค.

<Collapse>
   <MyCollapseItem />
   <MyCollapseItem2 />
</Collapse>

MyCollapseItem & MyCollapseItem2 ๋Š” Collapse.Panel ๋ Œ๋”๋งํ•ฉ๋‹ˆ๋‹ค.

๋˜ํ•œ react16์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ Œ๋”์—์„œ ๊ตฌ์„ฑ ์š”์†Œ ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์ด ํŠนํžˆ ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์ค‘๋ณต ์ฝ”๋“œ๋ฅผ ๋ฐฉ์ง€ํ•˜๋Š” ๊ฒƒ์ด ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์— ๋Œ€ํ•œ ์—…๋ฐ์ดํŠธ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

์ด๊ฒƒ์€ ์‹ค์ œ๋กœ ์šฐ๋ฆฌ์—๊ฒŒ ์ค‘์š”ํ•œ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ์ƒ๊ฐํ•  ์ˆ˜์žˆ๋Š” ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์ด ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฆ„ ๋ณ€๊ฒฝ ๋ธŒ๋ ˆ์ดํ‚น ์ฒด์ธ์ง€์— ํˆฌํ‘œํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์—ฌ๊ธฐ๋„ ๋™์ผํ•ฉ๋‹ˆ๋‹ค. Tabs.TabPane ๋ฐ Menu.MenuItem ํ•ฉ๋‹ˆ๋‹ค.

๊ธฐ๋ณธ์ ์œผ๋กœ ๋‚˜๋จธ์ง€ ์†Œํ’ˆ์„ ์ „๋‹ฌํ•  ์ˆ˜์žˆ๋Š” ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ์ฐพ์•˜์Šต๋‹ˆ๋‹ค. ๋ž˜ํ•‘ ๋œ ๊ตฌ์„ฑ ์š”์†Œ์—์„œ.

React.Children.map(children, (child, index) => { ... }) ์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ฉด ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์ด ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ฒฐ๊ตญ ํ‚ค ์†์„ฑ์€ mykey/.0 ์™€ ๊ฐ™์€ ๊ฐ’์„ ์–ป์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์ œ๊ฐ€ ์ž‘์—… ํ•  ์ˆ˜์žˆ๋Š” ๊ฒƒ์ด ์•„๋‹™๋‹ˆ๋‹ค. ๋‚˜๋Š” ๋˜ํ•œ ์†์„ฑ์˜ ์ด๋ฆ„ ๋ณ€๊ฒฝ์— ํˆฌํ‘œ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ๋Š” ์‹ค์ œ๋กœ ๋‚˜๋ฅผ antd์—์„œ ๋ฉ€์–ด์ง€๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋งŒ๋“œ๋Š” ๋Šฅ๋ ฅ์ด ์‹ค์ œ๋กœ ์ œํ•œ๋ฉ๋‹ˆ๋‹ค.

Menu ๋‚ด์—์„œ React Router๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋Š” ๋ชจ๋“  ์‚ฌ๋žŒ์„ ์œ„ํ•ด @yunshuipiao ํ•ญ๋ชฉ ์€ # 6576์—์„œ ์ €์—๊ฒŒ ํšจ๊ณผ์ ์ธ ์†”๋ฃจ์…˜์„ ์ œ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค.

๋˜ ๋‹ค๋ฅธ ์ž‘์€ ๋ฌธ์ œ : Menu.Item์„ ๋ž˜ํ•‘ํ•˜๋ฉด ํ•˜์œ„ ํ•ญ๋ชฉ ์ค‘ ํ•˜๋‚˜๊ฐ€ ์ ์–ด๋„ ์„ธ๋กœ ๋ชจ๋“œ์—์„œ ์„ ํƒ ๋  ๋•Œ ํ•˜์œ„ ๋ฉ”๋‰ด๊ฐ€ ์„ ํƒ๋œ ๊ฒƒ์œผ๋กœ ํ‘œ์‹œ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ด€๋ จ ๋ผ์ธ :

https://github.com/react-component/menu/blob/018d6f84d622ee140d9695ba57e7a773cf368efa/src/util.js#L40
https://github.com/react-component/menu/blob/018d6f84d622ee140d9695ba57e7a773cf368efa/src/SubMenu.jsx#L314

Collapse๋ฅผ ์‚ฌ์šฉ์ž ์ •์˜ ๊ตฌ์„ฑ ์š”์†Œ๋กœ ์ž‘์—…ํ•˜๋ ค๋Š” ์‚ฌ๋žŒ๋“ค์„ ์œ„ํ•ด ์ด๊ฒƒ์„ ๋ฌธ์„œํ™”ํ•˜๊ณ  ์‹ถ๋‹ค๊ณ  ์ƒ๊ฐ

<Collapse>
  <Custom/>
  <Custom/>
</Collapse>


Custom.render() {
  return (
    <Panel {...this.props}>
      <div>My custom stuff here</div>
    </Panel>
  )
}

@ncknuna์™€ ๊ฐ™์€ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค.

Menu.Item์€ ๋ž˜ํ•‘ ํ•  ๋•Œ ์„ ํƒ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๊นŒ?

@Nomeyho ์ €๋Š” ๊ด€๋ จ ๋ฉ”์„œ๋“œ๋ฅผ ๋ณต์‚ฌ / ๋ถ™์—ฌ ๋„ฃ๊ธฐํ•˜๊ณ  ์›๋ž˜ ๊ฒ€์‚ฌ๋ฅผ ์ฃผ์„ ์ฒ˜๋ฆฌํ•˜์—ฌ ant-menu-submenu-selected ํด๋ž˜์Šค๊ฐ€ ์ถ”๊ฐ€๋˜๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ๋…ผ๋ฆฌ๋ฅผ ์žฌ๊ตฌ์„ฑ ํ•œ ๋‹ค์Œ ํด๋ž˜์Šค๋ฅผ ๋‚ด ๋ž˜ํผ์— className ๋กœ ์ „๋‹ฌํ–ˆ์Šต๋‹ˆ๋‹ค.

function loopMenuItemRecusively (children: Array<any>, keys: Array<string>, ret: { find: boolean }) {
  if (!children || ret.find) {
    return
  }
  React.Children.forEach(children, (c: any) => {
    if (ret.find) {
      return
    }
    if (c) {
      const construt = c.type
      // Original check that caused problems. I'm not concerned about omitting it
      // because I don't plan on putting a bunch of weird, large stuff in my menus...
      // if (!construt || !(construt.isSubMenu || construt.isMenuItem || construt.isMenuItemGroup)) {
      //   return;
      // }
      if (keys.indexOf(c.key) !== -1) {
        ret.find = true
      } else if (c.props && c.props.children) {
        loopMenuItemRecusively(c.props.children, keys, ret)
      }
    }
  })
}

function isChildrenSelected (children: Array<any>, selectedKeys: Array<string>) {
  const ret = { find: false }
  loopMenuItemRecusively(children, selectedKeys, ret)
  return ret.find
}

// Omitting other custom code below...
export const SubMenu = ({ children, className, selectedKeys, title, ...rest }: any) => {
  const isSelected = isChildrenSelected(children, selectedKeys)
  className = [
    className,
    isSelected ? 'ant-menu-submenu-selected' : ''
  ].filter(className => classname).join(' ')
  return (
    <SubMenu title={title} className={className} selectedKeys={selectedKeys} {...rest}>
      {children}
    </SubMenu>
  )
}

์ด๊ฒƒ์— ๋Œ€ํ•œ ์ˆ˜์ • ์‚ฌํ•ญ์ด ์žˆ์Šต๋‹ˆ๊นŒ?

@ChuckJonas์— ๋™์˜ํ•ฉ๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ๋Š” ์‹ค์ œ๋กœ ๋‚˜๋ฅผ antd์—์„œ ๋ฉ€์–ด์ง€๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋งŒ๋“œ๋Š” ๋Šฅ๋ ฅ์ด ์‹ค์ œ๋กœ ์ œํ•œ๋ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์ด Menu SubMenu ๋ฐ Menu.items๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.
์™œ? ๋‹ค๋ฅธ ํŽ˜์ด์ง€์—์„œ "CustomSubMenu"์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ... ์ด๊ฒƒ์€ "์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ"๊ตฌ์„ฑ ์š”์†Œ์˜ ์ค‘์š”ํ•œ ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.

_MainFile.js_

Import CustomSubMenu from './OtherFile.js';

<Menu>
    <CustomSubMenu />
    <CustomSubMenu2 />
    <CustomSubMenu3 />
</Menu>

๋ฐ OtherFile.js๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

render(){
 return(
     <SubMenu>
           <SubMenu.item />
           <SubMenu.item2 />
            etc...etc...
     </SubMenu>
 );
}

ํ•˜์œ„ ๋ฉ”๋‰ด์— ๋Œ€ํ•œ ์ž„์‹œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ• (๊ฐ„๋‹จํ•˜๊ฒŒ ํŽธ์ง‘ ๋จ) :

const SubMenuArray = ({ ...props }) =>
  [1, 2].map(i => (
    <Menu.SubMenu {...props} eventKey={`item_${i}`} subMenuKey={`${i}-menu-`} />
  ));

๋ฐฐ์—ด์„ ๋‹ค๋ฃฐ ๋•Œ :

  • ์†Œํ’ˆ์„ ์ „๋‹ฌํ•˜๋‹ค
  • ๊ณ ์œ ํ•ด์•ผํ•˜๋Š” eventKey ๋ฐ subMenuKey

๋” ๋‚˜์€ ์ ‘๊ทผ ๋ฐฉ์‹์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

const SubMenuWrapper = ({ children, ...props }) =>
  React.Children.map(children, (child, i) =>
    React.cloneElement(child, {
      ...props,
      eventKey: `item_${i}`,
      subMenuKey: `${i}-menu-`
    })
  );

์šฉ๋ฒ•:

      <Menu>
        <SubMenuWrapper>
          <CustomSubMenu title={"one"}/>
          <CustomSubMenu title={"two"}/>
        </SubMenuWrapper>
      </Menu>

๋‹ค์‹œ ๋งํ•˜์ง€๋งŒ, ๋ฐฐ์—ด์—์„œ ์ธ๋ฑ์Šค๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์ง€ ์•Š์„ ๊ฒƒ์ด๋ฏ€๋กœ ํ”„๋กœ๋•์…˜์—์„œ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค. ๊ทธ๋Ÿฌ๋‚˜ ์•„์ด๋””์–ด๋Š” ํ™•์‹คํ•ฉ๋‹ˆ๋‹ค.

  • 1์€ antd ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์‚ฌ์šฉ์ž ์ง€์ • ๊ตฌ์„ฑ ์š”์†Œ์— ํฌํ•จํ•˜๋Š” ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์šฐ๋ฆฌ๋ฅผ์œ„ํ•œ ์„ฑ๊ณต ๋˜๋Š” ์ค‘๋‹จ์ž…๋‹ˆ๋‹ค

ํ‚ค์˜ ์ข…์†์„ฑ์„ ์ œ๊ฑฐ ํ•  ์ˆ˜์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋ฉ”๋‰ด๋ฅผ ์˜ˆ๋กœ ๋“ค์–ด itemKey ์†Œํ’ˆ์„ ๋„์ž… ํ•œ ๋‹ค์Œ context ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฉ”๋‰ด๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ˜ธํ™˜์„ฑ์„ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ๋ฉ”๋‰ด๋Š” ์—ฌ์ „ํžˆ ์ž์‹์„ ํƒ์ƒ‰ํ•˜๊ณ  key ๋ฅผ itemKey ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค. ๋™์‹œ์— selectedKeys ์™€ ๊ฐ™์€ props์˜ ์˜๋ฏธ๋ฅผ ์œ ์ง€ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

@yesmeck ์†”์งํžˆ ๋งํ•ด์„œ ant design ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฝ๋‹ˆ๋‹ค ( ํ•˜์ง€๋งŒ ์ด๋ฒˆ ์ฃผ์— ์ค‘์š”ํ•œ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์— ์‚ฌ์šฉํ•  ๊ณ„ํš์ž…๋‹ˆ๋‹ค ).

๋‚ด๊ฐ€ ์ดํ•ดํ•˜๋Š” ํ•œ, ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์œผ๋กœ ์ƒˆ๋กœ์šด context API ๋ฐ˜์‘์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

์ข‹์€ ์†Œ์‹์ž…๋‹ˆ๋‹ค

์˜ˆ, ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด cloneElement ๋Œ€์‹  context ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

ํ•ด๊ฒฐ์ฑ…์€ "React.Children.forEach"๋ฐ "React.cloneElement"๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์†Œํ’ˆ์„ ์ „๋‹ฌํ•˜๊ณ  ์ƒˆ ์†Œํ’ˆ์„ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ์˜ˆ๋ฅผ ๋“ค์–ด ์‚ฌ์šฉ์ž ์ง€์ • ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

<Select>
  {({ onSelect }) => (
    <div>
      <Option onClick={onSelect} key="0">option1</Option>
      <Option onClick={onSelect} key="1">option2</Option>
    </div>
  )
</Select>

๊ทธ๋ฆฌ๊ณ  antd ์„ ํƒ ์†Œ์Šค๋Š” "React.Children.forEach"๋ฐ "React.cloneElement"๋Œ€์‹  ํ•จ์ˆ˜ ์ž์‹ ์†Œํ’ˆ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์ด ์–ด๋ฆฌ์„์€ ์งˆ๋ฌธ์ด๋ผ๋ฉด ์‹ค๋ก€ํ•ฉ๋‹ˆ๋‹ค.ํ•˜์ง€๋งŒ ์ €๋Š” ์—ฌ์ „ํžˆ React์™€ Ant Design์— ์ต์ˆ™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
์ด๊ฒƒ์€ ์‹ค์งˆ์ ์œผ๋กœ react-redux ์—ฐ๊ฒฐ SPA ๋‚ด์—์„œ Ant ๋””์ž์ธ ๋ฉ”๋‰ด๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๊นŒ?
๊ทธ๋ ‡๋‹ค๋ฉด Ant Design์œผ๋กœ ๋น„๊ต์  ๋ณต์žกํ•œ SPA๋ฅผ ์–ด๋–ป๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๊นŒ?

์ด๊ฒƒ์— ๋Œ€ํ•œ ์—…๋ฐ์ดํŠธ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

์ด ๋ฌธ์ œ์— ๋Œ€ํ•œ ์—…๋ฐ์ดํŠธ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ? ๋ฉ”๋‰ด ํ•ญ๋ชฉ์ด HOC์—์„œ ์ด์ƒํ•˜๊ฒŒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

์•ˆ๋…•ํ•˜์„ธ์š” ! ์—ฌ๊ธฐ์—์„œ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค. ์ €๋Š” ์ด๋Ÿฌํ•œ ์ข…๋ฅ˜์˜ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์‚ฌ์šฉ์ž ์ •์˜ ํ•  ์ˆ˜์žˆ๋Š” ๋ฐ ์ •๋ง ๊ด€์‹ฌ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
์‚ฌ์šฉ์ž ์ง€์ • Select.Option ์‹ค์ œ๋กœ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ์Šค๋ ˆ๋“œ์—์„œ ์ œ์•ˆ ๋œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์ด ์ž‘๋™ํ•˜๋Š” ๋ฐ ๋„์›€์ด๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ๋นˆ ์˜ต์…˜์ด์žˆ๋Š” ์ž‘์—… ์„ ํƒ์ด ์žˆ์Šต๋‹ˆ๋‹ค ....

import React from 'react';
import PropTypes from 'prop-types';
import { Select } from 'antd';

const { Option } = Select;

const PictureOption = ({ label, value, pictureId, ...props }) => (
    <Option label={label} value={value} className="select-item" {...props}>
        <div className="select-item__thumbnail">
            <img src={pictureId} alt="item-img" />
        </div>
        <div className="select-item__name">{label}</div>
    </Option>
);

PictureOption.propTypes = {
    label: PropTypes.string.isRequired,
    value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
    pictureId: PropTypes.string.isRequired,
};

export default PictureOption;

์‚ฌ์šฉ์ž ๊ถŒํ•œ์— ๋”ฐ๋ผ UI ์š”์†Œ๋ฅผ ๋ Œ๋”๋งํ•˜๊ธฐ ์œ„ํ•ด CASL ์„ ์‚ฌ์šฉํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์†Œํ’ˆ์ด ์ž์‹ ์š”์†Œ์— ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ „ํŒŒ๋˜์ง€ ์•Š์•„ isRootMenu ํ•จ์ˆ˜์— ๋Œ€ํ•œ ํ˜ธ์ถœ์ด ์‹คํŒจํ•˜๊ธฐ ๋•Œ๋ฌธ์— SubMenu๊ฐ€ ๋ Œ๋”๋ง๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์œผ๋กœ ํ•˜์œ„ ๋ฉ”๋‰ด๋ฅผ ์ƒ์ˆ˜๋กœ ์ •์˜ํ•˜๊ณ  '์†์œผ๋กœ'์†Œํ’ˆ์— ์ „๋‹ฌํ–ˆ์Šต๋‹ˆ๋‹ค.
````
render () {

// ### Administration Menu ###
const AdminMenu = ({ ...props }) => {
  return (
    <Can I="access" on="admin-content">
      <Menu.Divider {...props} />
      <Menu.SubMenu
        {...props}
        title={
          // FIXME: Icon is not rendered... :-/
          <span>
            <Icon type="tools" />
            <span>Administration</span>
          </span>
        }
        // title={<span>Administration</span>}
        key="admin">
        <Menu.Item key="users" tabIndex={0}>
          <Icon type="android" />
          <span>User Administration</span>
        </Menu.Item>
        <Menu.Item key="permissions" tabIndex={0}>
          <Icon type="lock" />
          <span>Permissions</span>
        </Menu.Item>
      </Menu.SubMenu>
    </Can>
  );
};

return (
  <Layout id="menu-component-layout">
    <Layout.Sider width="300px" collapsible="false" trigger={null}>
      <Menu theme="dark" mode="inline" defaultSelectedKeys={['user']} defaultOpenKeys={['user', 'config', 'admin']}>
        <AdminMenu />
      </Menu>
    </Layout.Sider>
    <Layout.Content id="menu-component-content">
      <h3>Page containing a side menu</h3>
    </Layout.Content>
  </Layout>
);

}
````

์ด ์†”๋ฃจ์…˜์€ ๊ทธ๋‹ค์ง€ ํŽธ๋ฆฌํ•˜์ง€๋Š” ์•Š์ง€๋งŒ ์ง€๊ธˆ์€ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์—ฌ์ „ํžˆ ์•„์ด์ฝ˜์ด ํฌํ•จ ๋œ ํ•˜์œ„ ๋ฉ”๋‰ด์˜ ์ œ๋ชฉ์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋ Œ๋”๋ง๋˜์ง€ ์•Š๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„์ด์ฝ˜์ด ์—†์Šต๋‹ˆ๋‹ค.

๋ˆ„๊ตฌ๋“ ์ง€ ๊ทธ๊ฒƒ์„ ๊ณ ์น˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ?

์—ฌ๊ธฐ์— ์‡ผ์ผ€์ด์Šค๋ฅผ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค : https://github.com/gibelium/meteor-react-antd-casl

GitHub
ant-design UI ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” meteor / react ํ™˜๊ฒฝ์—์„œ CASL ์ธ์ฆ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ ์‡ผ์ผ€์ด์Šค-gibelium / meteor-react-antd-casl

@gibelium ์•„์ด์ฝ˜ ๋ Œ๋”๋ง์€ ์‹ค์ œ๋กœ ์ž์ฒด ๋ฌธ์ œ๊ฐ€ ๋  ๊ฐ€์น˜๊ฐ€ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ฅผ ๋ณต์ œํ•˜๊ณ  ์•„์ด์ฝ˜์„ ๊ณ ์ŠคํŠธ ๋ฒ„ํŠผ์œผ๋กœ ๋ฐ”๊พธ๋ ค๊ณ  ์‹œ๋„ํ–ˆ๋Š”๋ฐ ๋ฒ„ํŠผ ์œค๊ณฝ์„ ์ด ํ‘œ์‹œ๋˜์ง€๋งŒ ์•„์ด์ฝ˜๋„ ๋ฒ„ํŠผ์—์„œ ๋ Œ๋”๋ง๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

@gotjoshua ๊ทธ ์ „์šฉ ๋ฌธ์ œ๋ฅผ ๋งŒ๋“ค ๊ฒƒ์ž…๋‹ˆ๊นŒ?

๊ธฐ๋ณธ ํ™•์žฅ ๋ฉ”๋‰ด ํ•ญ๋ชฉ ์„ค์ •๋„ ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‚ด ํ•ด๊ฒฐ ๋ฐฉ๋ฒ• ๊ตฌํ˜„์€ Menu์˜ defaultOpenKeys ์†์„ฑ์„ ๋ฌด์‹œํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๊ฒƒ์„ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ์•„์ด๋””์–ด๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

์ด ๋ฌธ์ œ๋Š” ๋ฌธ์„œ์—์„œ ์‹ค์ œ๋กœ ์–ธ๊ธ‰๋˜์–ด์•ผํ•ฉ๋‹ˆ๋‹ค.์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ์„ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด์ด ๋ฒ„๊ทธ๋ฅผ ์กฐ์‚ฌํ•˜๋Š” ๋ฐ ํ•˜๋ฃจ ์ข…์ผ ๋‚ญ๋น„ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋‹น์‹ ์ด ์•ˆํ‹ฐ ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜๊ณ  React ํ‚ค๋ฅผ ์ค‘๊ณ„ํ•˜๋Š” ๊ฒƒ์„ ์•Œ์•„๋‚ด๋Š” ๋ฐ ๋„ˆ๋ฌด ๋งŽ์€ ์‹œ๊ฐ„์„ ๋‚ญ๋น„ ํ•  ํ•„์š”๊ฐ€ ์—†๋„๋ก ๊ฒฝ๊ณ ๋ฅผ ํ•ด์ฃผ์„ธ์š”. ๊ทธ๋ฆฌ๊ณ  ์ด์ œ ๋‹น์‹ ์€ ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜์žˆ๋Š” ๋งŽ์€ HOC ๋˜๋Š” ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ์— ๋งค์šฐ ์ทจ์•ฝํ•ฉ๋‹ˆ๋‹ค.
์ด๊ฒƒ์€ ์ •๋ง ๋ถ€๋„๋Ÿฌ์šด ์ผ์ž…๋‹ˆ๋‹ค. ๋‹ค์Œ ๋ฉ”์ด์ € ๋ฒ„์ „์—์„œ ์ˆ˜์ •ํ•˜์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ์— ๋Œ€ํ•œ ์—…๋ฐ์ดํŠธ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ? ๋ฉ”๋‰ด defaultOpenKeys ์„ค์ •์ด ์ž‘๋™ํ•˜์ง€ ์•Š์Œ

์ •๋ง ๋น ๋ฅด๋ฉด ์šฐ์„  ์ˆœ์œ„๊ฐ€ ๋†’์€ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๐Ÿ”ฅ

๋‚˜๋Š” (์•„๋งˆ๋„) ๊ตฌํ˜„ํ•  ์ˆ˜์—†๋Š” ์œ ์‚ฌํ•œ ์‚ฌ์šฉ ์‚ฌ๋ก€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
redux ์ €์žฅ์†Œ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœํ•˜๋Š” ์˜ต์…˜์œผ๋กœ Select ๋ฅผ ๋ Œ๋”๋งํ•˜๋Š” redux ์—ฐ๊ฒฐ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋งŒ๋“ค๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ๊ณณ์—์„œ ๋™์ผํ•œ ์ฝ”๋“œ๋ฅผ "๋ณต์‚ฌ-๋ถ™์—ฌ ๋„ฃ๊ธฐ"ํ•˜๊ณ  ์‹ถ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— Form.getFieldDecorator ๋‚ด๋ถ€์—์„œ์ด ์œ ํ˜•์˜ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์ง€๋งŒ connect HOC ์‚ฌ์šฉ์œผ๋กœ ์ธํ•ด ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ.

ํŽธ์ง‘ : ๋‚ด ์‚ฌ์šฉ ์‚ฌ๋ก€์— ๋Œ€ํ•œ ํ•ด๊ฒฐ์ฑ…์„ ์ฐพ์•˜์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์ด forwardRef ์˜ต์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ์œ„์—์„œ ์„ค๋ช…ํ•œ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋งŒ๋“ค ์ˆ˜์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.
connect(mapStateToProps, mapDispatchToProps, null, { forwardRef: true })(Component);
์ด ์†”๋ฃจ์…˜์€ connect HOC์—๋งŒ ํ•ด๋‹น๋˜์ง€๋งŒ React.forwardRef ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์œ ์‚ฌํ•œ ์†”๋ฃจ์…˜์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด์•ผํ•ฉ๋‹ˆ๋‹ค.

์ด์ „ ์˜๊ฒฌ์— ๋ง๋ถ™์—ฌ-์˜ˆ, ์ด๊ฒƒ์ด ์šฐ์„  ์ˆœ์œ„๋กœ ๊ฐ„์ฃผ ๋  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์œ„์—์„œ ์„ค๋ช…ํ•œ๋Œ€๋กœ ๋ฌธ์ œ ์ค‘ ํ•˜๋‚˜๋ฅผ ์„ฑ๊ณต์ ์œผ๋กœ ํ•ด๊ฒฐ ํ•œ ํ›„ ์ด์ œ ์‚ฌ์šฉ์ž ์ง€์ • ๊ตฌ์„ฑ ์š”์†Œ๋กœ ๋ž˜ํ•‘ ๋œ Tabs.TabPane ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋งŒ๋“ค์–ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๋งค์šฐ ์ผ๋ฐ˜์ ์ธ ์‚ฌ์šฉ ์‚ฌ๋ก€-> ๋ž˜ํ•‘ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ถŒํ•œ์„ ํ™•์ธํ•˜๋ฏ€๋กœ ์กฐ๊ฑด์ด ์ถฉ์กฑ๋˜๋ฉด ํ•˜์œ„ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ๋ Œ๋”๋ง๋˜๊ณ  ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ๊ทธ๋ ‡์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์— ๋Œ€ํ•œ ๊ฐ„๋‹จํ•˜๊ณ  ์ž‘๋™ํ•˜๋Š” ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๊นŒ?

์ด๊ฒƒ์— ๋Œ€ํ•œ ์—…๋ฐ์ดํŠธ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

๊ธฐ๋ณธ์ ์œผ๋กœ ๋‚˜๋จธ์ง€ ์†Œํ’ˆ์„ ์ „๋‹ฌํ•  ์ˆ˜์žˆ๋Š” ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ์ฐพ์•˜์Šต๋‹ˆ๋‹ค. ๋ž˜ํ•‘ ๋œ ๊ตฌ์„ฑ ์š”์†Œ์—์„œ.

์ฝ˜์†” ๊ฒฝ๊ณ ๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๊นŒ?
index.js:1437 Warning: React does not recognize the staticContext prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase staticcontext`. ์‹ค์ˆ˜๋กœ ์ƒ์œ„ ๊ตฌ์„ฑ ์š”์†Œ์—์„œ ์ „๋‹ฌํ•œ ๊ฒฝ์šฐ DOM ์š”์†Œ์—์„œ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.

index.js : 1437 ๊ฒฝ๊ณ  : ์†์„ฑ dispatch ๊ฐ’์ด ์ž˜๋ชป๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

  • ๊ผฌ๋ฆฌํ‘œ. ์š”์†Œ์—์„œ ์ œ๊ฑฐํ•˜๊ฑฐ๋‚˜ ๋ฌธ์ž์—ด ๋˜๋Š” ์ˆซ์ž ๊ฐ’์„ ์ „๋‹ฌํ•˜์—ฌ DOM์— ์œ ์ง€ํ•˜์‹ญ์‹œ์˜ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ https://fb.me/react-attribute-behavior๋ฅผ ์ฐธ์กฐ
    li (MenuItem์— ์˜ํ•ด ์ƒ์„ฑ๋จ)
    MenuItem์—์„œ (Connect (MenuItem)์— ์˜ํ•ด ์ƒ์„ฑ๋จ)
    Connect (MenuItem) (Context.Consumer์— ์˜ํ•ด ์ƒ์„ฑ๋จ)
    ํŠธ๋ฆฌ๊ฑฐ์—์„œ (ํˆดํŒ์œผ๋กœ ์ƒ์„ฑ๋จ)
    ํˆดํŒ์—์„œ (Context.Consumer์— ์˜ํ•ด ์ƒ์„ฑ๋จ)
    ํˆดํŒ์—์„œ (Context.Consumer์— ์˜ํ•ด ์ƒ์„ฑ๋จ)
    MenuItem์—์„œ (FortKnox.js : 55)
    _FortKnox์—์„œ (ConnectFunction์— ์˜ํ•ด ์ƒ์„ฑ๋จ)
    ConnectFunction์—์„œ (Context.Consumer์— ์˜ํ•ด ์ƒ์„ฑ๋จ)
    withRouter (Connect (_FortKnox)) (PageSider / index.js : 114์—์„œ)
    ul (DOMWrap์— ์˜ํ•ด ์ƒ์„ฑ๋จ)
    DOMWrap์—์„œ (SubPopupMenu์— ์˜ํ•ด ์ƒ์„ฑ๋จ)
    SubPopupMenu์—์„œ (Connect (SubPopupMenu)์— ์˜ํ•ด ์ƒ์„ฑ๋จ)
    Connect (SubPopupMenu) (๋ฉ”๋‰ด์—์„œ ์ƒ์„ฑ)
    ๊ณต๊ธ‰์ž (๋ฉ”๋‰ด์—์„œ ์ƒ์„ฑ)
    `
  • ๊ฐ™์€ ๋ฌธ์ œ ... Menu.Item์„ ๋ž˜ํ•‘ํ•˜๊ธฐ ์œ„ํ•ด HOC๋กœ ๊ถŒํ•œ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋งŒ๋“ค๊ณ  ์‹ถ์ง€๋งŒ antd๋Š” ์ด๊ฒƒ์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

    ๋‚˜๋Š” ๊ทธ ๋ฌธ์ œ์— ์‹œ๊ฐ„์„ ๋ณด๋ƒˆ๋‹ค ...

    ๊ทธ๋ฆฌ๊ณ  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค ๐ŸŽ‰, ๋‚˜๋จธ์ง€ ์†Œํ’ˆ์„ ie์—๊ฒŒ ์ „๋‹ฌํ•˜๋ฉด๋ฉ๋‹ˆ๋‹ค. Collapse.Panel (rc-panel์˜ ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ํ™•์ธํ•˜์—ฌ ์ดํ•ด)

    export const CustomPanel: React.FC = ({ header, children, ...props }) => {
      // do whatever you like
    
      return <Collapse.Panel header={header} {...props}>
        {children}
      </Collapse.Panel>
    };
    

    ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค.

    <Collapse>
        <CustomPanel key="first" header="Header 1">Body</CustomPanel>
        <CustomPanel key="second" header="Header 2">Body</CustomPanel>
    </Collapse>
    

    4.0 ๋ฆด๋ฆฌ์Šค์—์„œ์ด ์†”๋ฃจ์…˜์„ ๋ณด๋Š” ๊ฒƒ์ด ๋ฉ‹์งˆ ๊ฒƒ์ž…๋‹ˆ๋‹ค!

    ์ด๊ฒƒ์€ ์ ˆ๋Œ€์ ์œผ๋กœ ์ตœ์šฐ์„  ์ˆœ์œ„์ž…๋‹ˆ๋‹ค.
    ๋ฌธ์ž ๊ทธ๋Œ€๋กœ ํŠน๋ณ„ํ•œ ๋™์ž‘์ด ํ•„์š”ํ•  ๋•Œ (๋•Œ๋กœ๋Š” ๊ถŒํ•œ ๋ถ€์—ฌ์™€ ๊ฐ™์€ ๊ฐ„๋‹จํ•œ ๋™์ž‘) ์ด๋Ÿฌํ•œ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
    ์˜ˆ๋ฅผ ๋“ค์–ด ๋™์ ์œผ๋กœ๋กœ๋“œ๋˜๋Š” ๋ฉ”๋‰ด๋ฅผ ๋งŒ๋“ค๋ ค๊ณ ํ•˜๋ฏ€๋กœ ๋ฐ์ดํ„ฐ๊ฐ€ ๋„์ฐฉํ•  ๋•Œ๊นŒ์ง€ ์ด๋ฆ„์œผ๋กœ ์Šคํ”ผ๋„ˆ๊ฐ€์žˆ๋Š” ๋น„ํ™œ์„ฑํ™” ๋œ Menu.Item ๋ฅผ ๋ฌธ์ž ๊ทธ๋Œ€๋กœ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.
    ๊ทธ๊ฒƒ์€ ์ตœ์ ์ด ์•„๋‹™๋‹ˆ๋‹ค.

    ๋‚˜๋Š” ๊ทธ ๋ฌธ์ œ์— ์‹œ๊ฐ„์„ ๋ณด๋ƒˆ๋‹ค ...

    ๊ทธ๋ฆฌ๊ณ  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค ๐ŸŽ‰, ๋‚˜๋จธ์ง€ ์†Œํ’ˆ์„ ie์—๊ฒŒ ์ „๋‹ฌํ•˜๋ฉด๋ฉ๋‹ˆ๋‹ค. Collapse.Panel (rc-panel์˜ ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ํ™•์ธํ•˜์—ฌ ์ดํ•ด)

    ํ›Œ๋ฅญํ•œ ์†”๋ฃจ์…˜์ด์ง€๋งŒ (์ •๋ง๋กœ ๋‚ด ํ”„๋กœ์ ํŠธ์—์„œ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค) ์ผ๋ถ€ ๊ธฐ๋Šฅ์„ ์žƒ๊ฒŒ๋ฉ๋‹ˆ๋‹ค.
    ์ฆ‰, <SubMenu> ์ด <Menu> ์˜ ์ง๊ณ„ ์ž์‹์ด ์•„๋‹Œ ๊ฒฝ์šฐ defaultOpenKeys ๋Š” ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๐Ÿ˜ž

    ๋ฐฉ๊ธˆ์ด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

    ๋ฌธ์„œ์—์„œ ํ™•์ธ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๋‚ด ํ”„๋กœ์ ํŠธ์—์„œ AntDesign์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ์ง„์ง€ํ•˜๊ฒŒ ์žฌ๊ณ ํ•˜๊ฒŒ ๋งŒ๋“œ๋Š”์ด ๋ฌธ์ œ (๋‹ค๋ฅธ ๋ช‡ ๊ฐ€์ง€ ์‚ฌ์†Œํ•œ ๋ฌธ์ œ ์ค‘์—์„œ)๋ฅผ ์ ‘ํ•˜๊ฒŒ๋˜์–ด ๋งค์šฐ ์‹ค๋ง ์Šค๋Ÿฝ์Šต๋‹ˆ๋‹ค.

    ๋‚˜๋Š” ๊ทธ๊ฒƒ์— ๋Œ€ํ•œ ํ•ด๊ฒฐ์ฑ…์ด ์•„์ง ์—†๋‹ค๋Š” ๊ฒƒ์„ ๋ฏฟ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

    ์ด๊ฒƒ์€ ์ •๋ง ๊ณ ์ณ์•ผํ•ฉ๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ๊ฐœ๋ฐœ์ž๋Š” ์ฆ‰์‹œ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ฆ‰, ์ œ๊ณต๋œ api๋กœ ์ถ”๊ฐ€ ํ•  ์ˆ˜์—†๋Š” ๋” ๋งŽ์€ ๊ธฐ๋Šฅ์„ ํ†ตํ•ฉํ•˜๊ณ  ์‹ถ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” HOC๋ฅผ ์ผ๋ฐ˜์ ์ด์ง€ ์•Š๊ฑฐ๋‚˜ ์šฐ์„  ์ˆœ์œ„๊ฐ€ ๋‚ฎ์€ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ผ๊ณ  ๋ถ€๋ฅด์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. React์˜ ๊ตฌ์„ฑ ์  ํŠน์„ฑ์˜ ๊ธฐ๋ณธ์ž…๋‹ˆ๋‹ค.

    ์ด ๋ฌธ์ œ๋ฅผ ์ˆ˜์ •ํ•˜๊ณ  ์ˆ˜์ •๋˜๋Š” ๋™์•ˆ ์‚ฌ๋žŒ๋“ค์ด ์—ฌ๊ธฐ์—์„œ ์ฐพ์€ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์ •๋ณด๋ฅผ ๊ณต์‹ ๋ฌธ์„œ์— ์ถ”๊ฐ€ํ•˜์‹ญ์‹œ์˜ค.

    ์ด ๋ฌธ์ œ๋ฅผ ์ˆ˜์ •ํ•˜๊ณ  ์ˆ˜์ •๋˜๋Š” ๋™์•ˆ ์‚ฌ๋žŒ๋“ค์ด ์—ฌ๊ธฐ์—์„œ ์ฐพ์€ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์ •๋ณด๋ฅผ ๊ณต์‹ ๋ฌธ์„œ์— ์ถ”๊ฐ€ํ•˜์‹ญ์‹œ์˜ค.

    ์œ ์ง€ ๊ด€๋ฆฌ์ž๋Š” PR์— ๊ฐœ๋ฐฉ๋˜์–ด ์žˆ์œผ๋ฉฐ ์›ํ•˜๋Š” ๊ฒฝ์šฐ ๋ฌธ์„œ ์—…๋ฐ์ดํŠธ์— ๋Œ€ํ•œ PR์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์œผ๋ฉฐ ์‹œ๊ฐ„์ด ์žˆ์Šต๋‹ˆ๋‹ค.

    ๋ฟก๋ฟก

    ๋‚˜๋Š” ๊ทธ ๋ฌธ์ œ์— ์‹œ๊ฐ„์„ ๋ณด๋ƒˆ๋‹ค ...

    ๊ทธ๋ฆฌ๊ณ  ๊ทธ๊ฒƒ์€ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค, ๋‹น์‹ ์€ ie์— ๋‚˜๋จธ์ง€ ์†Œํ’ˆ์„ ์ „๋‹ฌํ•˜๊ธฐ ๋งŒํ•˜๋ฉด๋ฉ๋‹ˆ๋‹ค. Collapse.Panel (rc-panel์˜ ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ํ™•์ธํ•˜์—ฌ ์ดํ•ด)

    export const CustomPanel: React.FC = ({ header, children, ...props }) => {
      // do whatever you like
    
      return <Collapse.Panel header={header} {...props}>
        {children}
      </Collapse.Panel>
    };
    

    ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค.

    <Collapse>
        <CustomPanel key="first" header="Header 1">Body</CustomPanel>
        <CustomPanel key="second" header="Header 2">Body</CustomPanel>
    </Collapse>
    

    ๋ˆ„๊ตฐ๊ฐ€ ์•„๋ž˜์—์„œ ๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚˜๊ณ  ์žˆ๋Š”์ง€ ์„ค๋ช…ํ•ด ์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? ๋˜ํ•œ ๊ตฌ์„ฑ ์š”์†Œ ๋‚ด์—์„œ Panel ๋ž˜ํ•‘์„ ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค.

    ์ด ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ : :

     <PersonalInfoPanel
                    header="header"
                    key={"personalInfo" + i}
                    extra={genExtra()}
                />
    

    PersonalInfoPanel ๋‚ด๋ถ€ :

    function PersonalInfoPanel(props, ref) {
        return (
            <Panel header={props.header} key={props.key} extra={props.extra}>
    ...
    

    ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

    ๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์„ ๋Œ€์‹  ์‚ฌ์šฉํ•˜์ž๋งˆ์ž :

    function PersonalInfoPanel(props, ref) {
        return (
            <Panel {...props}>
    ...
    

    ์ž‘๋™ํ•˜๊ธฐ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.
    ๋ˆ„๊ตฐ๊ฐ€ ์ด์œ ๋ฅผ ์„ค๋ช… ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

     <Panel {...props}>
    ...
    

    ์ž‘๋™ํ•˜๊ธฐ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.

    ๋ˆ„๊ตฐ๊ฐ€ ์ด์œ ๋ฅผ ์„ค๋ช… ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

    ๋‚ด๊ฐ€ ์ดํ•ดํ–ˆ๋“ฏ์ด ๋ถ€๋ชจ Collapse๋Š” ํ—ค๋”, ํ‚ค ๋ฐ ์ถ”๊ฐ€ (์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ์˜ˆ์—์„œ) ์ด์™ธ์˜ ์†Œํ’ˆ์„ ์„ค์ •ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๋ถ€๋ชจ Collapse์˜ ์ด๋Ÿฌํ•œ ์†Œํ’ˆ์€ ์‚ฌ์šฉ์ž ์ •์˜ ๊ตฌ์„ฑ ์š”์†Œ ๋‚ด์˜ ํŒจ๋„ ๊ตฌ์„ฑ ์š”์†Œ์— ๋ช…์‹œ ์ ์œผ๋กœ ๋ฐฐ์น˜ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

    React Inspector๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ณ€๊ฒฝํ•˜๊ณ  ํ•˜๋‚˜์”ฉ ์ „๋‹ฌํ•  ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  ์†Œํ’ˆ์„ ๋ฐฐ์šธ ์ˆ˜ ์žˆ์ง€๋งŒ ... props ๊ตฌ๋ฌธ์€ ๋ถ€๋ชจ๊ฐ€ ์ž์‹ ํŒจ๋„์— ์ถ”๊ฐ€ํ•˜๋ ค๋Š” ๋ชจ๋“  ๊ฒƒ์ด ์ฒจ๋ถ€๋˜๋„๋กํ•ฉ๋‹ˆ๋‹ค ( ๋ช…์‹œ ์ ์œผ๋กœ ์„ค์ •ํ•ด์•ผํ•˜๋Š” ํ•ญ๋ชฉ์„ ํฌํ•จํ•˜๋˜ ์ด์— ๊ตญํ•œ๋˜์ง€ ์•Š์Œ)

    ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.
    ๋งŽ์€ (๋˜๋Š” ๊ฑฐ์˜) ๊ฐœ๋ฐœ์ž๊ฐ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉ์ž ์ •์˜ ๊ตฌ์„ฑ ์š”์†Œ์— ์‚ฌ์šฉํ•˜๊ธฐ๋ฅผ ์›ํ•ฉ๋‹ˆ๋‹ค.

    ์˜ˆ)
    ์ด ์ฝ”๋“œ๋Š” ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ฉ”๋‰ด์™€ ๋ฉ”๋‰ด ํ•ญ๋ชฉ์—๋Š” ๋ถˆํˆฌ๋ช… ํ•œ ์†Œํ’ˆ์ด ํ•„์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

          <Menu>
            { menus.map((item) => {
              if (item.to) {
                return <Menu.Item title={item.title} />;
              }
              // some codes...
              return null;
            })}
          </Menu>
    

    ํŠธ์œ— ๋‹ด์•„ ๊ฐ€๊ธฐ
    ์Šค๋ ˆ๋“œ๋ฅผ ์ฝ์—ˆ์Šต๋‹ˆ๊นŒ?
    ์ž‘๋™ํ•˜๊ฒŒํ•˜๋ ค๋ฉด ๋‚˜๋จธ์ง€ ์†Œํ’ˆ์„ ๋‚ด๋ถ€ antd ๊ตฌ์„ฑ ์š”์†Œ์— ์ „๋‹ฌํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

    antd Menu ๋‚ด๋ถ€์—์„œ antd react-router NavLinks ๋Œ€ํ•œ ์‚ฌ์šฉ์ž ์ง€์ • ๊ตฌ์„ฑ ์š”์†Œ + ์กฐ๊ฑด๋ถ€ ๋ Œ๋”๋ง์„ ์–ป๋Š” ๋ฐ ๋„์›€์ด ๋œ ๊ฒƒ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค react-router ์‹ค์ œ๋กœ ์ด๊ฒƒ์€ ์ˆ˜์ •์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ด ์Šค๋ ˆ๋“œ๋ฅผ ์ฐพ๊ธฐ๊นŒ์ง€ ๋งŽ์€ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฝ๋‹ˆ๋‹ค.

    _edit- ์‹ ๊ฒฝ ์“ฐ์ง€ ๋งˆ์„ธ์š”, selectedKeys๊ฐ€ ์ œ๋Œ€๋กœ ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค _

    const Nav = withRouter(() => {
      const auth = store.isAuthenticated;
    
      return (
        <Menu selectedKeys={[history.location.pathname]} mode="horizontal">
          <NavItem id="/">Home</NavItem>
          {auth && <NavItem id="/create">Create Post</NavItem>}
          {!auth && <NavItem id="/sign-in">Sign In</NavItem>}
          {!auth && <NavItem id="/register">Register</NavItem>}
        </Menu>
      );
    });
    
    const NavItem = ({ ...props }) => (
      <Menu.Item {...props} key={props.id}>
        <NavLink exact to={props.id}>
          {props.children}
        </NavLink>
      </Menu.Item>
    );
    

    ํŠธ์œ— ๋‹ด์•„ ๊ฐ€๊ธฐ
    ์Šค๋ ˆ๋“œ๋ฅผ ์ฝ์—ˆ์Šต๋‹ˆ๊นŒ?
    ์ž‘๋™ํ•˜๊ฒŒํ•˜๋ ค๋ฉด ๋‚˜๋จธ์ง€ ์†Œํ’ˆ์„ ๋‚ด๋ถ€ antd ๊ตฌ์„ฑ ์š”์†Œ์— ์ „๋‹ฌํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

    ์œ„์˜ ์˜ˆ๋ฅผ ์‚ดํŽด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ์ด ์Šค๋ ˆ๋“œ์—์„œ ๋ชจ๋“  ์ž‘์—…์„ ์ ์šฉํ–ˆ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์ง€๋งŒ ์—ฌ์ „ํžˆ ์ œ๋Œ€๋กœ ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. props๋ฅผ ์•„๋ž˜๋กœ ์ „๋‹ฌํ•˜๊ณ  Menu.Item ์— ํŽผ์นฉ๋‹ˆ๋‹ค.ํ•˜์ง€๋งŒ ํ™œ์„ฑํ™”๋˜๋ฉด ์—ฌ์ „ํžˆ ๊ฐ•์กฐ ํ‘œ์‹œ๋˜์ง€ ์•Š์œผ๋ฉฐ ๊ตฌ์„ฑ ์š”์†Œ ํŠธ๋ฆฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
    image

    ๋‚˜๋Š” ๊ทธ ๋ฌธ์ œ์— ์‹œ๊ฐ„์„ ๋ณด๋ƒˆ๋‹ค ...

    ๊ทธ๋ฆฌ๊ณ  ๊ทธ๊ฒƒ์€ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค, ๋‹น์‹ ์€ ie์— ๋‚˜๋จธ์ง€ ์†Œํ’ˆ์„ ์ „๋‹ฌํ•˜๊ธฐ ๋งŒํ•˜๋ฉด๋ฉ๋‹ˆ๋‹ค. Collapse.Panel (rc-panel์˜ ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ํ™•์ธํ•˜์—ฌ ์ดํ•ด)

    ์ œ ๊ฒฝ์šฐ์—๋Š” "{... props}"๋’ค์— "header = {calculated_header}"๋ฅผ ๋„ฃ์–ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒํ•˜์ง€ ์•Š์œผ๋ฉด ํŒจ๋„์˜ ํ—ค๋”๊ฐ€ ํ‘œ์‹œ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์‹œํ€€์Šค ๋’ท๋ถ€๋ถ„์— ๋‚˜์˜ค๋Š” "{... props}"๊ฐ€ "ํ—ค๋”"์ •๋ณด๋ฅผ ๋ฎ์–ด ์“ฐ๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ฒ˜์Œ์— "{... props}"๋ฅผ ๋„ฃ์œผ๋ฉด ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ๋‚˜์ค‘์— ๋‚˜ํƒ€๋‚˜๋Š” "ํ—ค๋”"๊ฐ€ ์†Œํ’ˆ์˜ "ํ—ค๋”"์ •๋ณด๋ฅผ ๋ฎ์–ด ์“ฐ๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

    @ marcin-piela ์‘๋‹ต์— ๋Œ€ํ•œ ๋‚˜์˜ ์ ์‘์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

    export const CustomPanel: React.FC = ({ headerinfo, children, ...props }) => { // do whatever you like const calculated_header = {() => headerinfo.someinformation } return <Collapse.Panel {...props} header={calculated_header} > {children} </Collapse.Panel> };

    ์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
    0 / 5 - 0 ๋“ฑ๊ธ‰