[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M71H9AAGVWMYQ4NG82QPYCTE":3,"skill-same:01M71H9AAGVWMYQ4NG82QPYCTE":65},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":22,"publishedAt":40,"linkOnly":41,"markdownContent":42,"markdownBody":43,"frontMatter":44,"refName":45,"commitSha":46,"skillDirectory":47,"forksCount":13,"repositoryHtmlUrl":48,"repositoryHomepageUrl":6,"ownerHtmlUrl":49,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":50,"install":51,"resources":64},"01M71H9AAGVWMYQ4NG82QPYCTE","02-component-composition",null,"React component composition patterns — render props, compound components, list rendering with map, slot patterns, and layout primitives","lambda-solver\u002Flambdabench-pro","lambda-solver","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F279071046?v=4","01M71H55W2WK3PM6RRAY9JZWAJ","01M71H55WRT9XAFDAVACTCC2XP",0,"MIT","https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro\u002Fblob\u002Fmain\u002Freference\u002Fghui\u002F.opencode\u002Fskills\u002Freact\u002Fpatterns\u002F02-component-composition\u002FSKILL.md",[17],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000009","前端开发","SCENARIO","使用场景",[23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39],"component","02 component composition","Composition","react","primitives","components","patterns","composition patterns","list","map","rendering","render","react component","layout","compound","opencode","with","2026-11-10 10:12:30",false,"---\nname: 02-component-composition\ndescription: React component composition patterns — render props, compound components, list rendering with map, slot patterns, and layout primitives\nlicense: MIT\ncompatibility: opencode\n---\n\n# React Component Composition\n\n## List Rendering — Always Use map\n\n**NEVER render lists statically.** Use `Array.map` with proper keys.\n\n```tsx\n\u002F\u002F ❌ STATIC — hard to maintain, violates DRY\n\u003Cdiv>\n  \u003CItem name=\"Alice\" \u002F>\n  \u003CItem name=\"Bob\" \u002F>\n  \u003CItem name=\"Carol\" \u002F>\n\u003C\u002Fdiv>\n\n\u002F\u002F ✅ DYNAMIC — data-driven, composable\n\u003Cdiv>\n  {users.map((user) => (\n    \u003CItem key={user.id} name={user.name} \u002F>\n  ))}\n\u003C\u002Fdiv>\n```\n\n### Key Rules\n\n- **Use stable IDs** — never array index as key\n- **Key at the top level** — on the mapped component, not nested\n- **Fragment with key** — when mapping to multiple elements\n\n```tsx\n\u002F\u002F ❌ index as key — causes reordering bugs\n{\n  items.map((item, i) => \u003CItem key={i} {...item} \u002F>);\n}\n\n\u002F\u002F ✅ stable id\n{\n  items.map((item) => \u003CItem key={item.id} {...item} \u002F>);\n}\n\n\u002F\u002F ✅ fragment with key when multiple children\n{\n  items.map((item) => (\n    \u003CReact.Fragment key={item.id}>\n      \u003Cdt>{item.name}\u003C\u002Fdt>\n      \u003Cdd>{item.value}\u003C\u002Fdd>\n    \u003C\u002FReact.Fragment>\n  ));\n}\n```\n\n## Conditional Rendering — Pattern Match\n\n```tsx\n\u002F\u002F ✅ early return for guard clauses\nif (!data) return \u003CLoading \u002F>;\nif (error) return \u003CError error={error} \u002F>;\n\n\u002F\u002F ✅ ternary for binary choice\nreturn isEditing ? \u003CEditForm \u002F> : \u003CDisplayView \u002F>;\n\n\u002F\u002F ✅ logical AND for simple toggle\nreturn showBanner && \u003CBanner \u002F>;\n\n\u002F\u002F ✅ record lookup for multiple variants\nconst variants = {\n  idle: \u003CIdle \u002F>,\n  loading: \u003CLoading \u002F>,\n  success: \u003CSuccess data={data} \u002F>,\n  error: \u003CError error={error} \u002F>,\n};\nreturn variants[status];\n```\n\n## Compound Components\n\nGroup related components that share state implicitly.\n\n```tsx\n\u002F\u002F Tabs compound component\n\u003CTabs value={activeTab} onValueChange={setActiveTab}>\n  \u003CTabs.List>\n    \u003CTabs.Trigger value=\"overview\">Overview\u003C\u002FTabs.Trigger>\n    \u003CTabs.Trigger value=\"details\">Details\u003C\u002FTabs.Trigger>\n  \u003C\u002FTabs.List>\n  \u003CTabs.Content value=\"overview\">\n    \u003COverview \u002F>\n  \u003C\u002FTabs.Content>\n  \u003CTabs.Content value=\"details\">\n    \u003CDetails \u002F>\n  \u003C\u002FTabs.Content>\n\u003C\u002FTabs>\n```\n\n## Render Props \u002F Slots\n\nAllow parent to inject content without prop drilling.\n\n```tsx\n\u002F\u002F Slot pattern\n\u003CCard>\n  \u003CCard.Header>\n    \u003Ch2>Title\u003C\u002Fh2>\n  \u003C\u002FCard.Header>\n  \u003CCard.Body>\n    \u003Cp>Content goes here\u003C\u002Fp>\n  \u003C\u002FCard.Body>\n  \u003CCard.Footer>\n    \u003CButton>Action\u003C\u002FButton>\n  \u003C\u002FCard.Footer>\n\u003C\u002FCard>\n\n\u002F\u002F Render prop for customization\n\u003CDataTable\n  data={rows}\n  renderRow={(row) => (\n    \u003CCustomRow data={row} onSelect={handleSelect} \u002F>\n  )}\n\u002F>\n```\n\n## Layout Primitives\n\nCreate reusable layout components instead of repeating flex\u002Fgrid classes.\n\n```tsx\n\u002F\u002F Stack — vertical spacing\n\u003CStack gap={4}>\n  \u003CItem \u002F>\n  \u003CItem \u002F>\n  \u003CItem \u002F>\n\u003C\u002FStack>\n\n\u002F\u002F Grid — responsive columns\n\u003CGrid columns={{ mobile: 1, tablet: 2, desktop: 3 }} gap={4}>\n  {items.map((item) => \u003CCard key={item.id} {...item} \u002F>)}\n\u003C\u002FGrid>\n\n\u002F\u002F Cluster — horizontal wrapping\n\u003CCluster gap={2}>\n  {tags.map((tag) => \u003CBadge key={tag}>{tag}\u003C\u002FBadge>)}\n\u003C\u002FCluster>\n```\n\n## Component Boundaries\n\nSplit components at data boundaries:\n\n```tsx\n\u002F\u002F ❌ one giant component\nfunction Page() {\n  const [data, setData] = useState();\n  const [filter, setFilter] = useState();\n  \u002F\u002F ... 200 lines of mixed concerns\n}\n\n\u002F\u002F ✅ separated by concern\nfunction Page() {\n  return (\n    \u003CPageLayout>\n      \u003CFilterBar \u002F>\n      \u003CDataList \u002F>\n    \u003C\u002FPageLayout>\n  );\n}\n\nfunction DataList() {\n  const data = useData(); \u002F\u002F custom hook\n  return (\n    \u003CStack>\n      {data.map((item) => (\n        \u003CDataCard key={item.id} {...item} \u002F>\n      ))}\n    \u003C\u002FStack>\n  );\n}\n```\n","# React Component Composition\n\n## List Rendering — Always Use map\n\n**NEVER render lists statically.** Use `Array.map` with proper keys.\n\n```tsx\n\u002F\u002F ❌ STATIC — hard to maintain, violates DRY\n\u003Cdiv>\n  \u003CItem name=\"Alice\" \u002F>\n  \u003CItem name=\"Bob\" \u002F>\n  \u003CItem name=\"Carol\" \u002F>\n\u003C\u002Fdiv>\n\n\u002F\u002F ✅ DYNAMIC — data-driven, composable\n\u003Cdiv>\n  {users.map((user) => (\n    \u003CItem key={user.id} name={user.name} \u002F>\n  ))}\n\u003C\u002Fdiv>\n```\n\n### Key Rules\n\n- **Use stable IDs** — never array index as key\n- **Key at the top level** — on the mapped component, not nested\n- **Fragment with key** — when mapping to multiple elements\n\n```tsx\n\u002F\u002F ❌ index as key — causes reordering bugs\n{\n  items.map((item, i) => \u003CItem key={i} {...item} \u002F>);\n}\n\n\u002F\u002F ✅ stable id\n{\n  items.map((item) => \u003CItem key={item.id} {...item} \u002F>);\n}\n\n\u002F\u002F ✅ fragment with key when multiple children\n{\n  items.map((item) => (\n    \u003CReact.Fragment key={item.id}>\n      \u003Cdt>{item.name}\u003C\u002Fdt>\n      \u003Cdd>{item.value}\u003C\u002Fdd>\n    \u003C\u002FReact.Fragment>\n  ));\n}\n```\n\n## Conditional Rendering — Pattern Match\n\n```tsx\n\u002F\u002F ✅ early return for guard clauses\nif (!data) return \u003CLoading \u002F>;\nif (error) return \u003CError error={error} \u002F>;\n\n\u002F\u002F ✅ ternary for binary choice\nreturn isEditing ? \u003CEditForm \u002F> : \u003CDisplayView \u002F>;\n\n\u002F\u002F ✅ logical AND for simple toggle\nreturn showBanner && \u003CBanner \u002F>;\n\n\u002F\u002F ✅ record lookup for multiple variants\nconst variants = {\n  idle: \u003CIdle \u002F>,\n  loading: \u003CLoading \u002F>,\n  success: \u003CSuccess data={data} \u002F>,\n  error: \u003CError error={error} \u002F>,\n};\nreturn variants[status];\n```\n\n## Compound Components\n\nGroup related components that share state implicitly.\n\n```tsx\n\u002F\u002F Tabs compound component\n\u003CTabs value={activeTab} onValueChange={setActiveTab}>\n  \u003CTabs.List>\n    \u003CTabs.Trigger value=\"overview\">Overview\u003C\u002FTabs.Trigger>\n    \u003CTabs.Trigger value=\"details\">Details\u003C\u002FTabs.Trigger>\n  \u003C\u002FTabs.List>\n  \u003CTabs.Content value=\"overview\">\n    \u003COverview \u002F>\n  \u003C\u002FTabs.Content>\n  \u003CTabs.Content value=\"details\">\n    \u003CDetails \u002F>\n  \u003C\u002FTabs.Content>\n\u003C\u002FTabs>\n```\n\n## Render Props \u002F Slots\n\nAllow parent to inject content without prop drilling.\n\n```tsx\n\u002F\u002F Slot pattern\n\u003CCard>\n  \u003CCard.Header>\n    \u003Ch2>Title\u003C\u002Fh2>\n  \u003C\u002FCard.Header>\n  \u003CCard.Body>\n    \u003Cp>Content goes here\u003C\u002Fp>\n  \u003C\u002FCard.Body>\n  \u003CCard.Footer>\n    \u003CButton>Action\u003C\u002FButton>\n  \u003C\u002FCard.Footer>\n\u003C\u002FCard>\n\n\u002F\u002F Render prop for customization\n\u003CDataTable\n  data={rows}\n  renderRow={(row) => (\n    \u003CCustomRow data={row} onSelect={handleSelect} \u002F>\n  )}\n\u002F>\n```\n\n## Layout Primitives\n\nCreate reusable layout components instead of repeating flex\u002Fgrid classes.\n\n```tsx\n\u002F\u002F Stack — vertical spacing\n\u003CStack gap={4}>\n  \u003CItem \u002F>\n  \u003CItem \u002F>\n  \u003CItem \u002F>\n\u003C\u002FStack>\n\n\u002F\u002F Grid — responsive columns\n\u003CGrid columns={{ mobile: 1, tablet: 2, desktop: 3 }} gap={4}>\n  {items.map((item) => \u003CCard key={item.id} {...item} \u002F>)}\n\u003C\u002FGrid>\n\n\u002F\u002F Cluster — horizontal wrapping\n\u003CCluster gap={2}>\n  {tags.map((tag) => \u003CBadge key={tag}>{tag}\u003C\u002FBadge>)}\n\u003C\u002FCluster>\n```\n\n## Component Boundaries\n\nSplit components at data boundaries:\n\n```tsx\n\u002F\u002F ❌ one giant component\nfunction Page() {\n  const [data, setData] = useState();\n  const [filter, setFilter] = useState();\n  \u002F\u002F ... 200 lines of mixed concerns\n}\n\n\u002F\u002F ✅ separated by concern\nfunction Page() {\n  return (\n    \u003CPageLayout>\n      \u003CFilterBar \u002F>\n      \u003CDataList \u002F>\n    \u003C\u002FPageLayout>\n  );\n}\n\nfunction DataList() {\n  const data = useData(); \u002F\u002F custom hook\n  return (\n    \u003CStack>\n      {data.map((item) => (\n        \u003CDataCard key={item.id} {...item} \u002F>\n      ))}\n    \u003C\u002FStack>\n  );\n}\n```\n",{"name":5,"license":14,"description":7,"compatibility":38},"main","816c073aaf171300af3605b06f7ec5aa7370ef0b","reference\u002Fghui\u002F.opencode\u002Fskills\u002Freact\u002Fpatterns\u002F02-component-composition","https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro","https:\u002F\u002Fgithub.com\u002Flambda-solver","2026-05-31 17:08:46",{"source":8,"skillName":5,"commands":52,"prompt":62,"zipAvailable":63},[53,56,59],{"tool":54,"command":55},"npx","npx skills add lambda-solver\u002Flambdabench-pro --skill 02-component-composition",{"tool":57,"command":58},"bunx","bunx skills add lambda-solver\u002Flambdabench-pro --skill 02-component-composition",{"tool":60,"command":61},"pnpm","pnpm dlx skills add lambda-solver\u002Flambdabench-pro --skill 02-component-composition","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro\u002Fblob\u002Fmain\u002Freference\u002Fghui\u002F.opencode\u002Fskills\u002Freact\u002Fpatterns\u002F02-component-composition\u002FSKILL.md",true,[],[66,94,112,131,150,167],{"skillNo":67,"name":68,"nameZh":6,"description":69,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":70,"categories":71,"keywords":75,"publishedAt":40},"01M71H9FNA5D6Y4ANXD18Z1Z3X","tmux-workflow","Development workflow with tmux — run dev servers, Storybook, and background processes in persistent sessions with live logs, while keeping OpenCode free for chat","https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro\u002Fblob\u002Fmain\u002Freference\u002Fghui\u002F.opencode\u002Fskills\u002Ftmux\u002FSKILL.md",[72],{"categoryNo":73,"categoryName":74,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000023","Skill与智能体开发",[76,77,78,79,80,81,82,83,38,39,84,85,86,87,88,89,90,91,92,93],"tmux","workflow","tmux workflow","dev servers","free","live","servers","run","chat","logs","development workflow","storybook","dev","sessions","for","development","processes","background",{"skillNo":95,"name":96,"nameZh":6,"description":97,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":98,"categories":99,"keywords":101,"publishedAt":40},"01M71H9DQJDAJVZX37NDN99D3P","04-anti-patterns","React anti-patterns to avoid — manual JSX repetition, useEffect misuse, reference instability, prop drilling, conditional hooks, and common performance traps","https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro\u002Fblob\u002Fmain\u002Freference\u002Fghui\u002F.opencode\u002Fskills\u002Freact\u002Fpatterns\u002F04-anti-patterns\u002FSKILL.md",[100],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},[29,102,103,104,105,106,107,108,109,110,38,111,26],"anti patterns","04 anti patterns","jsx","reference","conditional","hooks","manual","performance","anti-patterns","common",{"skillNo":113,"name":114,"nameZh":6,"description":115,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":116,"categories":117,"keywords":119,"publishedAt":40},"01M71H9BXF511W2R3B73S5P9ZN","03-state-management","React state management patterns — lifting state, colocation, URL state, server state with TanStack Query, local state with useState\u002FuseReducer","https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro\u002Fblob\u002Fmain\u002Freference\u002Fghui\u002F.opencode\u002Fskills\u002Freact\u002Fpatterns\u002F03-state-management\u002FSKILL.md",[118],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},[120,121,122,123,26,124,29,125,126,127,128,38,129,39,130],"management","state management","state","03 state management","query","URL","tanstack","react state management","tanstack query","server","local",{"skillNo":132,"name":133,"nameZh":6,"description":134,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":135,"categories":136,"keywords":138,"publishedAt":40},"01M71H98RDXRQZDR496SRD906M","01-fp-style","React functional programming style — pure components, hooks conventions, Effect Atom integration, and Tailwind patterns","https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro\u002Fblob\u002Fmain\u002Freference\u002Fghui\u002F.opencode\u002Fskills\u002Freact\u002Fpatterns\u002F01-fp-style\u002FSKILL.md",[137],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},[139,140,141,142,143,144,145,29,146,38,147,148,26,149,28,107],"01 fp style","style","tailwind patterns","functional programming","effect","Tailwind","conventions","integration","atom","functional","programming",{"skillNo":151,"name":152,"nameZh":6,"description":153,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":154,"categories":155,"keywords":157,"publishedAt":40},"01M71H95PYGAWBS5C8KN0C4WGT","react-animation","React animation with react\u002Fmotion (Framer Motion) — declarative animations, gestures, layout animations, and performance best practices","https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro\u002Fblob\u002Fmain\u002Freference\u002Fghui\u002F.opencode\u002Fskills\u002Freact\u002Fanimation\u002FSKILL.md",[156],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},[158,26,159,160,39,161,162,163,164,165,36,38,166,109],"react animation","Animation","animations","best practices","motion","declarative","gestures","framer","framer motion",{"skillNo":168,"name":169,"nameZh":6,"description":170,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":171,"categories":172,"keywords":177,"publishedAt":40},"01M71H92TG8T2E5ZQ95PHAKZZC","04-bun-test","Bun built-in test runner — zero-config testing for Effect, React, and TypeScript projects","https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro\u002Fblob\u002Fmain\u002Freference\u002Fghui\u002F.opencode\u002Fskills\u002Feffect-ts\u002Ftesting\u002F04-bun-test\u002FSKILL.md",[173,176],{"categoryNo":174,"categoryName":175,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000008","测试与质量",{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},[178,179,180,181,143,182,183,38,184,185,186,187,90,188,26],"bun test","04 bun test","bun","test","projects","runner","config","typescript","test runner","ZeRO","testing"]