[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M7AFPWT807HH9DPTJBQJ5466":3,"skill-same:01M7AFPWT807HH9DPTJBQJ5466":52},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":19,"linkOnly":20,"markdownContent":21,"markdownBody":22,"frontMatter":23,"refName":31,"commitSha":32,"skillDirectory":33,"forksCount":34,"repositoryHtmlUrl":35,"repositoryHomepageUrl":35,"ownerHtmlUrl":36,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":37,"install":38,"resources":51},"01M7AFPWT807HH9DPTJBQJ5466","trove-react",null,"React 19 coding conventions and performance patterns. Auto-activates when working with React\u002FTypeScript files. Covers hooks, state management, TanStack Query, Zustand, immutable updates, and component conventions.","bravew\u002Ftrove","bravew","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F10855844?v=4","01M7ACJ91JZSQYHT81XPVYR7VA","Yong","01M7AFERNR92HDPGNGP5QA16DM",10,"MIT","https:\u002F\u002Fgithub.com\u002Fbravew\u002Ftrove\u002Fblob\u002Fmain\u002Fplugins\u002Ftrove-dev\u002Fskills\u002Ftrove-react\u002FSKILL.md",[],[],"2026-11-15 14:19:17",false,"---\nname: trove-react\ndescription: \"React 19 coding conventions and performance patterns. Auto-activates when working with React\u002FTypeScript files. Covers hooks, state management, TanStack Query, Zustand, immutable updates, and component conventions.\"\npaths:\n  - \"**\u002F*.tsx\"\n  - \"**\u002F*.jsx\"\nwhen_to_use: \"react component; react hooks; tanstack query; zustand state\"\nuser-invocable: false\nmetadata:\n  trove-category: code\n  trove-category-label: Code\n---\n\u003C!-- AUTO-GENERATED from SKILL.md.tmpl — do not edit directly -->\n\u003C!-- Regenerate: bun run build:skills -->\n\n## Session Init\n\nThis skill ships Trove conventions. Prefer existing project patterns over generic best practices when they conflict.\n\n# React 19 Conventions\n\n## Immutable State Updates (CRITICAL)\n\nReact StrictMode double-invokes state updaters. Mutating objects causes duplicated side effects.\n\n```typescript\n\u002F\u002F BAD — mutation causes bugs in StrictMode\nsetMessages(prev => {\n  prev[prev.length - 1].text += content; \u002F\u002F MUTATION!\n  return [...prev];\n});\n\n\u002F\u002F GOOD — immutable update\nsetMessages(prev => {\n  const updated = [...prev];\n  const lastIndex = updated.length - 1;\n  updated[lastIndex] = { ...updated[lastIndex], text: updated[lastIndex].text + content };\n  return updated;\n});\n```\n\n## Zustand Selectors (CRITICAL)\n\nAlways use selectors — never destructure the store directly:\n\n```typescript\n\u002F\u002F BAD — subscribes to entire store, re-renders on ANY change\nconst { darkMode } = useGlobalStore();\n\n\u002F\u002F GOOD — subscribes only to darkMode\nconst darkMode = useGlobalStore(state => state.darkMode);\n\n\u002F\u002F GOOD — multiple values with useShallow\nimport { useShallow } from 'zustand\u002Fshallow';\nconst { username, email } = useUserStore(\n  useShallow(state => ({ username: state.username, email: state.email }))\n);\n```\n\n## Component Patterns\n\n- Prefer function components with hooks\n- Use `React.memo()` only when profiling shows re-render cost\n- Extract custom hooks for reusable logic\n- Keep components under 200 lines — split into sub-components\n\n## TanStack Query\n\n```typescript\n\u002F\u002F Queries — always provide staleTime\nconst { data, isLoading } = useQuery({\n  queryKey: ['users', userId],\n  queryFn: () => fetchUser(userId),\n  staleTime: 5 * 60 * 1000,\n});\n\n\u002F\u002F Mutations — invalidate related queries on success\nconst mutation = useMutation({\n  mutationFn: updateUser,\n  onSuccess: () => queryClient.invalidateQueries({ queryKey: ['users'] }),\n});\n```\n\n## Error Boundaries\n\nWrap route-level components with error boundaries. Never let errors crash the full app.\n\n## AI Gotchas\n\n- **useEffect dependencies**: Always include all referenced values in the dependency array\n- **Ref vs State**: Use `useRef` for values that don't trigger re-renders (timers, DOM refs)\n- **Key prop**: Use stable, unique IDs — never use array index as key for dynamic lists\n- **Event handlers**: Define inline only for simple logic; extract for complex handlers\n","\u003C!-- AUTO-GENERATED from SKILL.md.tmpl — do not edit directly -->\n\u003C!-- Regenerate: bun run build:skills -->\n\n## Session Init\n\nThis skill ships Trove conventions. Prefer existing project patterns over generic best practices when they conflict.\n\n# React 19 Conventions\n\n## Immutable State Updates (CRITICAL)\n\nReact StrictMode double-invokes state updaters. Mutating objects causes duplicated side effects.\n\n```typescript\n\u002F\u002F BAD — mutation causes bugs in StrictMode\nsetMessages(prev => {\n  prev[prev.length - 1].text += content; \u002F\u002F MUTATION!\n  return [...prev];\n});\n\n\u002F\u002F GOOD — immutable update\nsetMessages(prev => {\n  const updated = [...prev];\n  const lastIndex = updated.length - 1;\n  updated[lastIndex] = { ...updated[lastIndex], text: updated[lastIndex].text + content };\n  return updated;\n});\n```\n\n## Zustand Selectors (CRITICAL)\n\nAlways use selectors — never destructure the store directly:\n\n```typescript\n\u002F\u002F BAD — subscribes to entire store, re-renders on ANY change\nconst { darkMode } = useGlobalStore();\n\n\u002F\u002F GOOD — subscribes only to darkMode\nconst darkMode = useGlobalStore(state => state.darkMode);\n\n\u002F\u002F GOOD — multiple values with useShallow\nimport { useShallow } from 'zustand\u002Fshallow';\nconst { username, email } = useUserStore(\n  useShallow(state => ({ username: state.username, email: state.email }))\n);\n```\n\n## Component Patterns\n\n- Prefer function components with hooks\n- Use `React.memo()` only when profiling shows re-render cost\n- Extract custom hooks for reusable logic\n- Keep components under 200 lines — split into sub-components\n\n## TanStack Query\n\n```typescript\n\u002F\u002F Queries — always provide staleTime\nconst { data, isLoading } = useQuery({\n  queryKey: ['users', userId],\n  queryFn: () => fetchUser(userId),\n  staleTime: 5 * 60 * 1000,\n});\n\n\u002F\u002F Mutations — invalidate related queries on success\nconst mutation = useMutation({\n  mutationFn: updateUser,\n  onSuccess: () => queryClient.invalidateQueries({ queryKey: ['users'] }),\n});\n```\n\n## Error Boundaries\n\nWrap route-level components with error boundaries. Never let errors crash the full app.\n\n## AI Gotchas\n\n- **useEffect dependencies**: Always include all referenced values in the dependency array\n- **Ref vs State**: Use `useRef` for values that don't trigger re-renders (timers, DOM refs)\n- **Key prop**: Use stable, unique IDs — never use array index as key for dynamic lists\n- **Event handlers**: Define inline only for simple logic; extract for complex handlers\n",{"name":5,"paths":24,"metadata":27,"description":7,"when_to_use":30,"user-invocable":20},[25,26],"**\u002F*.tsx","**\u002F*.jsx",{"trove-category":28,"trove-category-label":29},"code","Code","react component; react hooks; tanstack query; zustand state","main","f88db1f1cf0e0703dd962051ebc142db961d7799","plugins\u002Ftrove-dev\u002Fskills\u002Ftrove-react",1,"https:\u002F\u002Fgithub.com\u002Fbravew\u002Ftrove","https:\u002F\u002Fgithub.com\u002Fbravew","2026-11-12 07:56:32",{"source":8,"skillName":5,"commands":39,"prompt":49,"zipAvailable":50},[40,43,46],{"tool":41,"command":42},"npx","npx skills add bravew\u002Ftrove --skill trove-react",{"tool":44,"command":45},"bunx","bunx skills add bravew\u002Ftrove --skill trove-react",{"tool":47,"command":48},"pnpm","pnpm dlx skills add bravew\u002Ftrove --skill trove-react","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fbravew\u002Ftrove\u002Fblob\u002Fmain\u002Fplugins\u002Ftrove-dev\u002Fskills\u002Ftrove-react\u002FSKILL.md",true,[],[53,60,67,74,81,88],{"skillNo":54,"name":55,"nameZh":6,"description":56,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":57,"categories":58,"keywords":59,"publishedAt":19},"01M7AGJDHTQAS1VK6P7VJAV79G","using-trove","Skill discipline anchor for the Trove marketplace. Loaded once per session; routes the agent to the right trove-* skill before code, planning, review, or git actions.","https:\u002F\u002Fgithub.com\u002Fbravew\u002Ftrove\u002Fblob\u002Fmain\u002Fskills\u002Fworkflow\u002Fusing-trove\u002FSKILL.md",[],[],{"skillNo":61,"name":62,"nameZh":6,"description":63,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":64,"categories":65,"keywords":66,"publishedAt":19},"01M7AGJAS4V4TXE6TV6F839BGZ","trove-write-skill","Skill authoring workflow. Use when creating or updating a Codex or Trove skill, including rubrics, tasks, metadata, and validation.","https:\u002F\u002Fgithub.com\u002Fbravew\u002Ftrove\u002Fblob\u002Fmain\u002Fskills\u002Fworkflow\u002Ftrove-write-skill\u002FSKILL.md",[],[],{"skillNo":68,"name":69,"nameZh":6,"description":70,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":71,"categories":72,"keywords":73,"publishedAt":19},"01M7AGJ87K41ZAC8DDBAV17QFW","trove-worktree","Git worktree workflow for spikes, risky experiments, and broad refactors that should not disturb the user's current branch.","https:\u002F\u002Fgithub.com\u002Fbravew\u002Ftrove\u002Fblob\u002Fmain\u002Fskills\u002Fworkflow\u002Ftrove-worktree\u002FSKILL.md",[],[],{"skillNo":75,"name":76,"nameZh":6,"description":77,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":78,"categories":79,"keywords":80,"publishedAt":19},"01M7AGJ32V58VYBFYMS9EMHRY4","trove-why","Reconstruct design rationale and decision history from evidence — source control, issue tracker (Linear), docs (Notion), chat (Slack), error tracking (Sentry) — with calibrated confidence. Use for \"why does X work this way\", \"why did we pick Y\", regressions, and postmortems. Use trove-explain for how it works now.","https:\u002F\u002Fgithub.com\u002Fbravew\u002Ftrove\u002Fblob\u002Fmain\u002Fskills\u002Fworkflow\u002Ftrove-why\u002FSKILL.md",[],[],{"skillNo":82,"name":83,"nameZh":6,"description":84,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":85,"categories":86,"keywords":87,"publishedAt":19},"01M7AGJ0FHJSRR8MMXC3V8XNHF","trove-verify","Completion verification workflow. Use before claiming done, fixed, complete, ready, or shipped.","https:\u002F\u002Fgithub.com\u002Fbravew\u002Ftrove\u002Fblob\u002Fmain\u002Fskills\u002Fworkflow\u002Ftrove-verify\u002FSKILL.md",[],[],{"skillNo":89,"name":90,"nameZh":6,"description":91,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":92,"categories":93,"keywords":94,"publishedAt":19},"01M7AGHWV4B9SDS60RH5W0B0K5","trove-unslop","Cut AI tells from writing — PR descriptions, release notes, specs, commit bodies, and replies. Use before finalizing prose, or when the user asks to clean up, de-slop, or make text sound human.","https:\u002F\u002Fgithub.com\u002Fbravew\u002Ftrove\u002Fblob\u002Fmain\u002Fskills\u002Fworkflow\u002Ftrove-unslop\u002FSKILL.md",[],[]]