[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M71H9DQJDAJVZX37NDN99D3P":3,"skill-same:01M71H9DQJDAJVZX37NDN99D3P":61},{"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":36,"linkOnly":37,"markdownContent":38,"markdownBody":39,"frontMatter":40,"refName":41,"commitSha":42,"skillDirectory":43,"forksCount":13,"repositoryHtmlUrl":44,"repositoryHomepageUrl":6,"ownerHtmlUrl":45,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":46,"install":47,"resources":60},"01M71H9DQJDAJVZX37NDN99D3P","04-anti-patterns",null,"React anti-patterns to avoid — manual JSX repetition, useEffect misuse, reference instability, prop drilling, conditional hooks, and common performance traps","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\u002F04-anti-patterns\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],"04 anti patterns","anti patterns","patterns","opencode","anti-patterns","performance","manual","hooks","conditional","reference","jsx","common","react","2026-11-10 10:12:30",false,"---\nname: 04-anti-patterns\ndescription: React anti-patterns to avoid — manual JSX repetition, useEffect misuse, reference instability, prop drilling, conditional hooks, and common performance traps\nlicense: MIT\ncompatibility: opencode\n---\n\n# React Anti-Patterns\n\nCommon patterns that cause bugs, performance issues, or maintenance problems in React.\n\n## Manual JSX Repetition\n\n**NEVER repeat JSX elements manually.** Always render from data with `Array.map`.\n\n```tsx\n\u002F\u002F ❌ MANUAL — violates DRY, unmaintainable, error-prone\n\u003Cdiv>\n  \u003CTildeLine \u002F>\n  \u003CTildeLine \u002F>\n  \u003CTildeLine \u002F>\n  \u003CTildeLine \u002F>\n  \u003CTildeLine \u002F>\n  \u003CTildeLine \u002F>\n  \u003CTildeLine \u002F>\n\u003C\u002Fdiv>\n\n\u002F\u002F ✅ DATA-DRIVEN — declarative, scalable, maintainable\n\u003Cdiv>\n  {Array.from({ length: 7 }, (_, i) => (\n    \u003CTildeLine key={i} \u002F>\n  ))}\n\u003C\u002Fdiv>\n\n\u002F\u002F ✅ with actual data\n\u003Cdiv>\n  {lines.map((line) => (\n    \u003CTildeLine key={line.id} variant={line.variant} \u002F>\n  ))}\n\u003C\u002Fdiv>\n```\n\n**Why this matters:**\n- Manual repetition hides intent (why 7?)\n- Changing count requires editing JSX, not data\n- No way to add per-item props without more repetition\n- Violates FP principle: derive UI from data, don't hardcode structure\n\n## useEffect for Derived State\n\n**Never use `useEffect` to synchronize state from props or other state.**\n\n```tsx\n\u002F\u002F ❌ SYNC STATE — infinite loops, stale data, complexity\nconst [sortedItems, setSortedItems] = useState(items);\nuseEffect(() => {\n  setSortedItems([...items].sort());\n}, [items]);\n\n\u002F\u002F ✅ DERIVE — pure, synchronous, no extra renders\nconst sortedItems = useMemo(() => [...items].sort(), [items]);\n\n\u002F\u002F ✅ even simpler — inline if cheap\nconst sortedItems = [...items].sort();\n```\n\n```tsx\n\u002F\u002F ❌ SYNC PROPS TO STATE — anti-pattern\nconst [value, setValue] = useState(initialValue);\nuseEffect(() => {\n  setValue(initialValue);\n}, [initialValue]);\n\n\u002F\u002F ✅ CONTROLLED — parent owns state\nfunction Input({ value, onChange }: { value: string; onChange: (v: string) => void }) {\n  return \u003Cinput value={value} onChange={(e) => onChange(e.target.value)} \u002F>;\n}\n\n\u002F\u002F ✅ UNCONTROLLED with key reset\n\u003Cinput key={resetKey} defaultValue={initialValue} \u002F>\n```\n\n## Reference Instability in JSX\n\n**Never create objects, arrays, or functions inline in JSX props.**\n\n```tsx\n\u002F\u002F ❌ NEW REFERENCE EVERY RENDER — child re-renders unnecessarily\n\u003CComponent\n  style={{ color: \"red\", fontSize: 14 }}\n  config={{ enabled: true, mode: \"auto\" }}\n  items={[\"a\", \"b\", \"c\"]}\n  onClick={() => handleClick(id)}\n\u002F>\n\n\u002F\u002F ✅ STABLE REFERENCES — memoize or lift out\nconst style = { color: \"red\", fontSize: 14 };\nconst config = { enabled: true, mode: \"auto\" };\nconst items = [\"a\", \"b\", \"c\"];\n\nconst handleItemClick = useCallback((id: string) => {\n  handleClick(id);\n}, [handleClick]);\n\n\u003CComponent\n  style={style}\n  config={config}\n  items={items}\n  onClick={handleItemClick}\n\u002F>\n```\n\n```tsx\n\u002F\u002F ❌ inline arrow in JSX — new function every render\n\u003Cbutton onClick={() => setCount((c) => c + 1)}>Increment\u003C\u002Fbutton>\n\n\u002F\u002F ✅ stable handler\nconst increment = () => setCount((c) => c + 1);\n\u003Cbutton onClick={increment}>Increment\u003C\u002Fbutton>\n```\n\n## useCallback \u002F useMemo Misuse\n\n**Don't memoize everything. Don't forget dependencies.**\n\n```tsx\n\u002F\u002F ❌ memoizing cheap operations — overhead > benefit\nconst count = useMemo(() => items.length, [items]);\nconst isEmpty = useMemo(() => items.length === 0, [items]);\n\n\u002F\u002F ✅ just compute inline\nconst count = items.length;\nconst isEmpty = items.length === 0;\n```\n\n```tsx\n\u002F\u002F ❌ missing dependencies — stale closures\nconst handleSubmit = useCallback(() => {\n  submit(formData); \u002F\u002F formData is stale!\n}, []); \u002F\u002F forgot formData\n\n\u002F\u002F ✅ correct dependencies\nconst handleSubmit = useCallback(() => {\n  submit(formData);\n}, [formData]);\n```\n\n```tsx\n\u002F\u002F ❌ useCallback without memoized child — no benefit\nconst handleClick = useCallback(() => {}, []);\n\u003Cbutton onClick={handleClick}>Click\u003C\u002Fbutton>; \u002F\u002F button is not memoized\n\n\u002F\u002F ✅ only when child is wrapped in React.memo\nconst MemoizedChild = React.memo(Child);\n\u003CMemoizedChild onClick={handleClick} \u002F>;\n```\n\n## Prop Drilling\n\n**Don't thread props through multiple component layers.**\n\n```tsx\n\u002F\u002F ❌ PROP DRILLING — App → Layout → Header → UserMenu → Avatar\nfunction App() {\n  const user = useUser();\n  return \u003CLayout user={user} \u002F>;\n}\nfunction Layout({ user }: { user: User }) {\n  return \u003CHeader user={user} \u002F>;\n}\nfunction Header({ user }: { user: User }) {\n  return \u003CUserMenu user={user} \u002F>;\n}\n\n\u002F\u002F ✅ CONTEXT — intermediate components don't know about user\nconst UserContext = createContext\u003CUser | null>(null);\n\nfunction App() {\n  const user = useUser();\n  return (\n    \u003CUserContext.Provider value={user}>\n      \u003CLayout \u002F>\n    \u003C\u002FUserContext.Provider>\n  );\n}\n\nfunction Avatar() {\n  const user = useContext(UserContext); \u002F\u002F only consumer knows\n  return \u003Cimg src={user?.avatar} \u002F>;\n}\n\n\u002F\u002F ✅ COMPOSITION — pass children instead of props\n\u003CLayout header={\u003CUserMenu \u002F>} \u002F>\n```\n\n## useEffect without Cleanup\n\n**Always clean up side effects.**\n\n```tsx\n\u002F\u002F ❌ NO CLEANUP — memory leaks, stale subscriptions\nuseEffect(() => {\n  const subscription = source.subscribe(setData);\n}, [source]);\n\n\u002F\u002F ✅ CLEANUP\nuseEffect(() => {\n  const subscription = source.subscribe(setData);\n  return () => subscription.unsubscribe();\n}, [source]);\n\n\u002F\u002F ❌ NO CLEANUP — event listener leaks\nuseEffect(() => {\n  window.addEventListener(\"resize\", handleResize);\n}, []);\n\n\u002F\u002F ✅ CLEANUP\nuseEffect(() => {\n  window.addEventListener(\"resize\", handleResize);\n  return () => window.removeEventListener(\"resize\", handleResize);\n}, []);\n```\n\n## Conditional Hooks\n\n**Never call hooks conditionally or in loops.**\n\n```tsx\n\u002F\u002F ❌ CONDITIONAL HOOK — breaks Rules of Hooks\nif (isLoggedIn) {\n  const user = useUser(); \u002F\u002F crash or undefined behavior\n}\n\n\u002F\u002F ✅ CONDITIONAL RENDER — hooks always run\nconst user = useUser();\nif (!isLoggedIn) return \u003CLogin \u002F>;\nreturn \u003CDashboard user={user} \u002F>;\n```\n\n```tsx\n\u002F\u002F ❌ HOOK IN LOOP — breaks Rules of Hooks\n{items.map((item) => {\n  const ref = useRef(null); \u002F\u002F crash!\n  return \u003Cdiv ref={ref}>{item.name}\u003C\u002Fdiv>;\n})}\n\n\u002F\u002F ✅ SINGLE HOOK WITH ARRAY\nconst refs = useRef\u003C(HTMLDivElement | null)[]>([]);\n{items.map((item, i) => (\n  \u003Cdiv ref={(el) => { refs.current[i] = el; }}>{item.name}\u003C\u002Fdiv>\n))}\n```\n\n## Large Components\n\n**Split components that exceed ~100 lines or mix concerns.**\n\n```tsx\n\u002F\u002F ❌ GOD COMPONENT — 300+ lines, mixed data, UI, logic\nfunction Dashboard() {\n  const [users, setUsers] = useState([]);\n  const [posts, setPosts] = useState([]);\n  const [loading, setLoading] = useState(false);\n  \u002F\u002F ... 200 more lines of handlers, effects, JSX\n}\n\n\u002F\u002F ✅ SEPARATED BY CONCERN\nfunction Dashboard() {\n  return (\n    \u003CPageLayout>\n      \u003CUserSection \u002F>\n      \u003CPostSection \u002F>\n    \u003C\u002FPageLayout>\n  );\n}\n\nfunction UserSection() {\n  const { users, isLoading } = useUsers();\n  if (isLoading) return \u003CLoading \u002F>;\n  return \u003CUserList users={users} \u002F>;\n}\n\nfunction PostSection() {\n  const { posts, isLoading } = usePosts();\n  if (isLoading) return \u003CLoading \u002F>;\n  return \u003CPostList posts={posts} \u002F>;\n}\n```\n\n## Direct State Mutation\n\n**Never mutate state directly — React won't detect changes.**\n\n```tsx\n\u002F\u002F ❌ MUTATION — React can't detect, won't re-render\nconst handleAdd = () => {\n  items.push(newItem);\n  setItems(items);\n};\n\n\u002F\u002F ✅ NEW ARRAY\nconst handleAdd = () => {\n  setItems([...items, newItem]);\n};\n\n\u002F\u002F ❌ MUTATION — nested object\nconst handleUpdate = () => {\n  user.name = \"Alice\";\n  setUser(user);\n};\n\n\u002F\u002F ✅ NEW OBJECT\nconst handleUpdate = () => {\n  setUser({ ...user, name: \"Alice\" });\n};\n\n\u002F\u002F ❌ MUTATION — array element\nitems[0].completed = true;\nsetItems(items);\n\n\u002F\u002F ✅ MAP\nsetItems(items.map((item, i) =>\n  i === 0 ? { ...item, completed: true } : item\n));\n```\n\n## Inline Function Definitions\n\n**Avoid creating functions inside JSX render body.**\n\n```tsx\n\u002F\u002F ❌ INLINE IN JSX — new function every render, reference instability\n\u003Cdiv>\n  {items.map((item) => (\n    \u003Cbutton onClick={() => handleItemClick(item.id)}>\n      {item.name}\n    \u003C\u002Fbutton>\n  ))}\n\u003C\u002Fdiv>\n\n\u002F\u002F ✅ STABLE HANDLER FACTORY\nconst makeHandleClick = (id: string) => () => handleItemClick(id);\n\n\u003Cdiv>\n  {items.map((item) => (\n    \u003Cbutton key={item.id} onClick={makeHandleClick(item.id)}>\n      {item.name}\n    \u003C\u002Fbutton>\n  ))}\n\u003C\u002Fdiv>\n\n\u002F\u002F ✅ OR CURRIED HANDLER\nconst handleItemClick = (id: string) => () => {\n  \u002F\u002F handle click\n};\n\n\u003Cdiv>\n  {items.map((item) => (\n    \u003Cbutton key={item.id} onClick={handleItemClick(item.id)}>\n      {item.name}\n    \u003C\u002Fbutton>\n  ))}\n\u003C\u002Fdiv>\n```\n\n## Default Values in Destructuring\n\n**Don't use destructuring defaults for optional props — hides missing prop bugs.**\n\n```tsx\n\u002F\u002F ❌ HIDDEN DEFAULT — caller might not know prop exists\nfunction Button({ variant = \"primary\" }: { variant?: string }) {\n  return \u003Cbutton className={variant}>Click\u003C\u002Fbutton>;\n}\n\n\u002F\u002F ✅ EXPLICIT DEFAULT — visible in component body\nfunction Button({ variant }: { variant?: string }) {\n  const resolvedVariant = variant ?? \"primary\";\n  return \u003Cbutton className={resolvedVariant}>Click\u003C\u002Fbutton>;\n}\n\n\u002F\u002F ✅ REQUIRED PROP — fail fast\nfunction Button({ variant }: { variant: string }) {\n  return \u003Cbutton className={variant}>Click\u003C\u002Fbutton>;\n}\n```\n\n## Summary\n\n| Anti-Pattern | Problem | Solution |\n|-------------|---------|----------|\n| Manual JSX repetition | DRY violation, unmaintainable | `Array.map` over data |\n| useEffect for derived state | Extra renders, complexity | `useMemo` or inline derivation |\n| Inline objects\u002Farrays in JSX | Reference instability, re-renders | Lift out, memoize, or use constants |\n| useCallback\u002FuseMemo misuse | Unnecessary overhead, stale closures | Only for expensive ops \u002F memoized children |\n| Prop drilling | Tight coupling, refactoring pain | Context API or composition |\n| useEffect without cleanup | Memory leaks, stale subscriptions | Always return cleanup function |\n| Conditional hooks | Undefined behavior, crashes | Conditional render, not conditional hooks |\n| Large components | Mixed concerns, hard to test | Split by data boundary or concern |\n| Direct state mutation | Missed re-renders, bugs | Spread, map, filter for immutability |\n| Inline functions in JSX | Reference instability | Factory functions or curried handlers |\n| Destructuring defaults | Hidden bugs, unclear API | Explicit defaults or required props |\n","# React Anti-Patterns\n\nCommon patterns that cause bugs, performance issues, or maintenance problems in React.\n\n## Manual JSX Repetition\n\n**NEVER repeat JSX elements manually.** Always render from data with `Array.map`.\n\n```tsx\n\u002F\u002F ❌ MANUAL — violates DRY, unmaintainable, error-prone\n\u003Cdiv>\n  \u003CTildeLine \u002F>\n  \u003CTildeLine \u002F>\n  \u003CTildeLine \u002F>\n  \u003CTildeLine \u002F>\n  \u003CTildeLine \u002F>\n  \u003CTildeLine \u002F>\n  \u003CTildeLine \u002F>\n\u003C\u002Fdiv>\n\n\u002F\u002F ✅ DATA-DRIVEN — declarative, scalable, maintainable\n\u003Cdiv>\n  {Array.from({ length: 7 }, (_, i) => (\n    \u003CTildeLine key={i} \u002F>\n  ))}\n\u003C\u002Fdiv>\n\n\u002F\u002F ✅ with actual data\n\u003Cdiv>\n  {lines.map((line) => (\n    \u003CTildeLine key={line.id} variant={line.variant} \u002F>\n  ))}\n\u003C\u002Fdiv>\n```\n\n**Why this matters:**\n- Manual repetition hides intent (why 7?)\n- Changing count requires editing JSX, not data\n- No way to add per-item props without more repetition\n- Violates FP principle: derive UI from data, don't hardcode structure\n\n## useEffect for Derived State\n\n**Never use `useEffect` to synchronize state from props or other state.**\n\n```tsx\n\u002F\u002F ❌ SYNC STATE — infinite loops, stale data, complexity\nconst [sortedItems, setSortedItems] = useState(items);\nuseEffect(() => {\n  setSortedItems([...items].sort());\n}, [items]);\n\n\u002F\u002F ✅ DERIVE — pure, synchronous, no extra renders\nconst sortedItems = useMemo(() => [...items].sort(), [items]);\n\n\u002F\u002F ✅ even simpler — inline if cheap\nconst sortedItems = [...items].sort();\n```\n\n```tsx\n\u002F\u002F ❌ SYNC PROPS TO STATE — anti-pattern\nconst [value, setValue] = useState(initialValue);\nuseEffect(() => {\n  setValue(initialValue);\n}, [initialValue]);\n\n\u002F\u002F ✅ CONTROLLED — parent owns state\nfunction Input({ value, onChange }: { value: string; onChange: (v: string) => void }) {\n  return \u003Cinput value={value} onChange={(e) => onChange(e.target.value)} \u002F>;\n}\n\n\u002F\u002F ✅ UNCONTROLLED with key reset\n\u003Cinput key={resetKey} defaultValue={initialValue} \u002F>\n```\n\n## Reference Instability in JSX\n\n**Never create objects, arrays, or functions inline in JSX props.**\n\n```tsx\n\u002F\u002F ❌ NEW REFERENCE EVERY RENDER — child re-renders unnecessarily\n\u003CComponent\n  style={{ color: \"red\", fontSize: 14 }}\n  config={{ enabled: true, mode: \"auto\" }}\n  items={[\"a\", \"b\", \"c\"]}\n  onClick={() => handleClick(id)}\n\u002F>\n\n\u002F\u002F ✅ STABLE REFERENCES — memoize or lift out\nconst style = { color: \"red\", fontSize: 14 };\nconst config = { enabled: true, mode: \"auto\" };\nconst items = [\"a\", \"b\", \"c\"];\n\nconst handleItemClick = useCallback((id: string) => {\n  handleClick(id);\n}, [handleClick]);\n\n\u003CComponent\n  style={style}\n  config={config}\n  items={items}\n  onClick={handleItemClick}\n\u002F>\n```\n\n```tsx\n\u002F\u002F ❌ inline arrow in JSX — new function every render\n\u003Cbutton onClick={() => setCount((c) => c + 1)}>Increment\u003C\u002Fbutton>\n\n\u002F\u002F ✅ stable handler\nconst increment = () => setCount((c) => c + 1);\n\u003Cbutton onClick={increment}>Increment\u003C\u002Fbutton>\n```\n\n## useCallback \u002F useMemo Misuse\n\n**Don't memoize everything. Don't forget dependencies.**\n\n```tsx\n\u002F\u002F ❌ memoizing cheap operations — overhead > benefit\nconst count = useMemo(() => items.length, [items]);\nconst isEmpty = useMemo(() => items.length === 0, [items]);\n\n\u002F\u002F ✅ just compute inline\nconst count = items.length;\nconst isEmpty = items.length === 0;\n```\n\n```tsx\n\u002F\u002F ❌ missing dependencies — stale closures\nconst handleSubmit = useCallback(() => {\n  submit(formData); \u002F\u002F formData is stale!\n}, []); \u002F\u002F forgot formData\n\n\u002F\u002F ✅ correct dependencies\nconst handleSubmit = useCallback(() => {\n  submit(formData);\n}, [formData]);\n```\n\n```tsx\n\u002F\u002F ❌ useCallback without memoized child — no benefit\nconst handleClick = useCallback(() => {}, []);\n\u003Cbutton onClick={handleClick}>Click\u003C\u002Fbutton>; \u002F\u002F button is not memoized\n\n\u002F\u002F ✅ only when child is wrapped in React.memo\nconst MemoizedChild = React.memo(Child);\n\u003CMemoizedChild onClick={handleClick} \u002F>;\n```\n\n## Prop Drilling\n\n**Don't thread props through multiple component layers.**\n\n```tsx\n\u002F\u002F ❌ PROP DRILLING — App → Layout → Header → UserMenu → Avatar\nfunction App() {\n  const user = useUser();\n  return \u003CLayout user={user} \u002F>;\n}\nfunction Layout({ user }: { user: User }) {\n  return \u003CHeader user={user} \u002F>;\n}\nfunction Header({ user }: { user: User }) {\n  return \u003CUserMenu user={user} \u002F>;\n}\n\n\u002F\u002F ✅ CONTEXT — intermediate components don't know about user\nconst UserContext = createContext\u003CUser | null>(null);\n\nfunction App() {\n  const user = useUser();\n  return (\n    \u003CUserContext.Provider value={user}>\n      \u003CLayout \u002F>\n    \u003C\u002FUserContext.Provider>\n  );\n}\n\nfunction Avatar() {\n  const user = useContext(UserContext); \u002F\u002F only consumer knows\n  return \u003Cimg src={user?.avatar} \u002F>;\n}\n\n\u002F\u002F ✅ COMPOSITION — pass children instead of props\n\u003CLayout header={\u003CUserMenu \u002F>} \u002F>\n```\n\n## useEffect without Cleanup\n\n**Always clean up side effects.**\n\n```tsx\n\u002F\u002F ❌ NO CLEANUP — memory leaks, stale subscriptions\nuseEffect(() => {\n  const subscription = source.subscribe(setData);\n}, [source]);\n\n\u002F\u002F ✅ CLEANUP\nuseEffect(() => {\n  const subscription = source.subscribe(setData);\n  return () => subscription.unsubscribe();\n}, [source]);\n\n\u002F\u002F ❌ NO CLEANUP — event listener leaks\nuseEffect(() => {\n  window.addEventListener(\"resize\", handleResize);\n}, []);\n\n\u002F\u002F ✅ CLEANUP\nuseEffect(() => {\n  window.addEventListener(\"resize\", handleResize);\n  return () => window.removeEventListener(\"resize\", handleResize);\n}, []);\n```\n\n## Conditional Hooks\n\n**Never call hooks conditionally or in loops.**\n\n```tsx\n\u002F\u002F ❌ CONDITIONAL HOOK — breaks Rules of Hooks\nif (isLoggedIn) {\n  const user = useUser(); \u002F\u002F crash or undefined behavior\n}\n\n\u002F\u002F ✅ CONDITIONAL RENDER — hooks always run\nconst user = useUser();\nif (!isLoggedIn) return \u003CLogin \u002F>;\nreturn \u003CDashboard user={user} \u002F>;\n```\n\n```tsx\n\u002F\u002F ❌ HOOK IN LOOP — breaks Rules of Hooks\n{items.map((item) => {\n  const ref = useRef(null); \u002F\u002F crash!\n  return \u003Cdiv ref={ref}>{item.name}\u003C\u002Fdiv>;\n})}\n\n\u002F\u002F ✅ SINGLE HOOK WITH ARRAY\nconst refs = useRef\u003C(HTMLDivElement | null)[]>([]);\n{items.map((item, i) => (\n  \u003Cdiv ref={(el) => { refs.current[i] = el; }}>{item.name}\u003C\u002Fdiv>\n))}\n```\n\n## Large Components\n\n**Split components that exceed ~100 lines or mix concerns.**\n\n```tsx\n\u002F\u002F ❌ GOD COMPONENT — 300+ lines, mixed data, UI, logic\nfunction Dashboard() {\n  const [users, setUsers] = useState([]);\n  const [posts, setPosts] = useState([]);\n  const [loading, setLoading] = useState(false);\n  \u002F\u002F ... 200 more lines of handlers, effects, JSX\n}\n\n\u002F\u002F ✅ SEPARATED BY CONCERN\nfunction Dashboard() {\n  return (\n    \u003CPageLayout>\n      \u003CUserSection \u002F>\n      \u003CPostSection \u002F>\n    \u003C\u002FPageLayout>\n  );\n}\n\nfunction UserSection() {\n  const { users, isLoading } = useUsers();\n  if (isLoading) return \u003CLoading \u002F>;\n  return \u003CUserList users={users} \u002F>;\n}\n\nfunction PostSection() {\n  const { posts, isLoading } = usePosts();\n  if (isLoading) return \u003CLoading \u002F>;\n  return \u003CPostList posts={posts} \u002F>;\n}\n```\n\n## Direct State Mutation\n\n**Never mutate state directly — React won't detect changes.**\n\n```tsx\n\u002F\u002F ❌ MUTATION — React can't detect, won't re-render\nconst handleAdd = () => {\n  items.push(newItem);\n  setItems(items);\n};\n\n\u002F\u002F ✅ NEW ARRAY\nconst handleAdd = () => {\n  setItems([...items, newItem]);\n};\n\n\u002F\u002F ❌ MUTATION — nested object\nconst handleUpdate = () => {\n  user.name = \"Alice\";\n  setUser(user);\n};\n\n\u002F\u002F ✅ NEW OBJECT\nconst handleUpdate = () => {\n  setUser({ ...user, name: \"Alice\" });\n};\n\n\u002F\u002F ❌ MUTATION — array element\nitems[0].completed = true;\nsetItems(items);\n\n\u002F\u002F ✅ MAP\nsetItems(items.map((item, i) =>\n  i === 0 ? { ...item, completed: true } : item\n));\n```\n\n## Inline Function Definitions\n\n**Avoid creating functions inside JSX render body.**\n\n```tsx\n\u002F\u002F ❌ INLINE IN JSX — new function every render, reference instability\n\u003Cdiv>\n  {items.map((item) => (\n    \u003Cbutton onClick={() => handleItemClick(item.id)}>\n      {item.name}\n    \u003C\u002Fbutton>\n  ))}\n\u003C\u002Fdiv>\n\n\u002F\u002F ✅ STABLE HANDLER FACTORY\nconst makeHandleClick = (id: string) => () => handleItemClick(id);\n\n\u003Cdiv>\n  {items.map((item) => (\n    \u003Cbutton key={item.id} onClick={makeHandleClick(item.id)}>\n      {item.name}\n    \u003C\u002Fbutton>\n  ))}\n\u003C\u002Fdiv>\n\n\u002F\u002F ✅ OR CURRIED HANDLER\nconst handleItemClick = (id: string) => () => {\n  \u002F\u002F handle click\n};\n\n\u003Cdiv>\n  {items.map((item) => (\n    \u003Cbutton key={item.id} onClick={handleItemClick(item.id)}>\n      {item.name}\n    \u003C\u002Fbutton>\n  ))}\n\u003C\u002Fdiv>\n```\n\n## Default Values in Destructuring\n\n**Don't use destructuring defaults for optional props — hides missing prop bugs.**\n\n```tsx\n\u002F\u002F ❌ HIDDEN DEFAULT — caller might not know prop exists\nfunction Button({ variant = \"primary\" }: { variant?: string }) {\n  return \u003Cbutton className={variant}>Click\u003C\u002Fbutton>;\n}\n\n\u002F\u002F ✅ EXPLICIT DEFAULT — visible in component body\nfunction Button({ variant }: { variant?: string }) {\n  const resolvedVariant = variant ?? \"primary\";\n  return \u003Cbutton className={resolvedVariant}>Click\u003C\u002Fbutton>;\n}\n\n\u002F\u002F ✅ REQUIRED PROP — fail fast\nfunction Button({ variant }: { variant: string }) {\n  return \u003Cbutton className={variant}>Click\u003C\u002Fbutton>;\n}\n```\n\n## Summary\n\n| Anti-Pattern | Problem | Solution |\n|-------------|---------|----------|\n| Manual JSX repetition | DRY violation, unmaintainable | `Array.map` over data |\n| useEffect for derived state | Extra renders, complexity | `useMemo` or inline derivation |\n| Inline objects\u002Farrays in JSX | Reference instability, re-renders | Lift out, memoize, or use constants |\n| useCallback\u002FuseMemo misuse | Unnecessary overhead, stale closures | Only for expensive ops \u002F memoized children |\n| Prop drilling | Tight coupling, refactoring pain | Context API or composition |\n| useEffect without cleanup | Memory leaks, stale subscriptions | Always return cleanup function |\n| Conditional hooks | Undefined behavior, crashes | Conditional render, not conditional hooks |\n| Large components | Mixed concerns, hard to test | Split by data boundary or concern |\n| Direct state mutation | Missed re-renders, bugs | Spread, map, filter for immutability |\n| Inline functions in JSX | Reference instability | Factory functions or curried handlers |\n| Destructuring defaults | Hidden bugs, unclear API | Explicit defaults or required props |\n",{"name":5,"license":14,"description":7,"compatibility":26},"main","816c073aaf171300af3605b06f7ec5aa7370ef0b","reference\u002Fghui\u002F.opencode\u002Fskills\u002Freact\u002Fpatterns\u002F04-anti-patterns","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":48,"prompt":58,"zipAvailable":59},[49,52,55],{"tool":50,"command":51},"npx","npx skills add lambda-solver\u002Flambdabench-pro --skill 04-anti-patterns",{"tool":53,"command":54},"bunx","bunx skills add lambda-solver\u002Flambdabench-pro --skill 04-anti-patterns",{"tool":56,"command":57},"pnpm","pnpm dlx skills add lambda-solver\u002Flambdabench-pro --skill 04-anti-patterns","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro\u002Fblob\u002Fmain\u002Freference\u002Fghui\u002F.opencode\u002Fskills\u002Freact\u002Fpatterns\u002F04-anti-patterns\u002FSKILL.md",true,[],[62,91,110,131,150,167],{"skillNo":63,"name":64,"nameZh":6,"description":65,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":66,"categories":67,"keywords":71,"publishedAt":36},"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",[68],{"categoryNo":69,"categoryName":70,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000023","Skill与智能体开发",[72,73,74,75,76,77,78,79,80,81,82,26,83,84,85,86,87,88,89,90],"tmux workflow","workflow","tmux","dev servers","development workflow","background","processes","storybook","live","servers","run","with","chat","logs","free","dev","sessions","for","development",{"skillNo":92,"name":93,"nameZh":6,"description":94,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":95,"categories":96,"keywords":98,"publishedAt":36},"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",[97],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},[99,100,101,102,103,104,105,106,26,83,107,35,108,25,109],"management","state management","state","03 state management","server","react state management","local","tanstack query","tanstack","query","URL",{"skillNo":111,"name":112,"nameZh":6,"description":113,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":114,"categories":115,"keywords":117,"publishedAt":36},"01M71H9AAGVWMYQ4NG82QPYCTE","02-component-composition","React component composition patterns — render props, compound components, list rendering with map, slot patterns, and layout primitives","https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro\u002Fblob\u002Fmain\u002Freference\u002Fghui\u002F.opencode\u002Fskills\u002Freact\u002Fpatterns\u002F02-component-composition\u002FSKILL.md",[116],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},[118,119,120,121,122,123,25,124,125,35,126,127,128,129,26,83,130],"component","02 component composition","Composition","map","list","composition patterns","components","primitives","render","react component","layout","compound","rendering",{"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":36},"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,25,142,143,26,144,35,145,124,30,146,147,148,149],"01 fp style","style","atom","conventions","integration","functional","programming","Tailwind","tailwind patterns","functional programming","effect",{"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":36},"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,35,159,160,161,162,163,164,165,128,26,166,28,83],"react animation","Animation","best practices","motion","declarative","animations","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":36},"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,182,183,184,26,35,185,89,186,187,188,149],"bun test","bun","04 bun test","test","test runner","typescript","config","testing","ZeRO","runner","projects"]