{
  "schemaVersion": "1.0",
  "item": {
    "slug": "react-composition",
    "name": "React Composition",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/wpank/react-composition",
    "canonicalUrl": "https://clawhub.ai/wpank/react-composition",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/react-composition",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=react-composition",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "README.md",
      "SKILL.md"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "slug": "react-composition",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-05-07T23:12:10.322Z",
      "expiresAt": "2026-05-14T23:12:10.322Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=react-composition",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=react-composition",
        "contentDisposition": "attachment; filename=\"react-composition-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null,
        "slug": "react-composition"
      },
      "scope": "item",
      "summary": "Item download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this item.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/react-composition"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/react-composition",
    "agentPageUrl": "https://openagent3.xyz/skills/react-composition/agent",
    "manifestUrl": "https://openagent3.xyz/skills/react-composition/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/react-composition/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "React Composition Patterns",
        "body": "Composition patterns for building flexible, maintainable React components. Avoid\nboolean prop proliferation by using compound components, lifting state, and\ncomposing internals. These patterns make codebases easier to work with as they\nscale."
      },
      {
        "title": "When to Apply",
        "body": "Refactoring components with many boolean props\nBuilding reusable component libraries\nDesigning flexible component APIs\nWorking with compound components or context providers"
      },
      {
        "title": "Pattern Overview",
        "body": "#PatternImpact1Avoid Boolean PropsCRITICAL2Compound ComponentsHIGH3Context Interface (DI)HIGH4State LiftingHIGH5Explicit VariantsMEDIUM6Children Over Render PropsMEDIUM"
      },
      {
        "title": "OpenClaw / Moltbot / Clawbot",
        "body": "npx clawhub@latest install react-composition"
      },
      {
        "title": "1. Avoid Boolean Prop Proliferation",
        "body": "Don't add boolean props like isThread, isEditing, isDMThread to customize\nbehavior. Each boolean doubles possible states and creates unmaintainable\nconditional logic. Use composition instead.\n\n// BAD — boolean props create exponential complexity\nfunction Composer({ isThread, isDMThread, isEditing, isForwarding }: Props) {\n  return (\n    <form>\n      <Input />\n      {isDMThread ? <AlsoSendToDMField /> : isThread ? <AlsoSendToChannelField /> : null}\n      {isEditing ? <EditActions /> : isForwarding ? <ForwardActions /> : <DefaultActions />}\n    </form>\n  )\n}\n\n// GOOD — composition eliminates conditionals\nfunction ChannelComposer() {\n  return (\n    <Composer.Frame>\n      <Composer.Input />\n      <Composer.Footer><Composer.Attachments /><Composer.Submit /></Composer.Footer>\n    </Composer.Frame>\n  )\n}\n\nfunction ThreadComposer({ channelId }: { channelId: string }) {\n  return (\n    <Composer.Frame>\n      <Composer.Input />\n      <AlsoSendToChannelField id={channelId} />\n      <Composer.Footer><Composer.Submit /></Composer.Footer>\n    </Composer.Frame>\n  )\n}\n\nEach variant is explicit about what it renders. Shared internals without a\nmonolithic parent."
      },
      {
        "title": "2. Compound Components",
        "body": "Structure complex components with shared context. Each subcomponent accesses\nstate via context, not props. Export as a namespace object.\n\nconst ComposerContext = createContext<ComposerContextValue | null>(null)\n\nfunction ComposerProvider({ children, state, actions, meta }: ProviderProps) {\n  return <ComposerContext value={{ state, actions, meta }}>{children}</ComposerContext>\n}\nfunction ComposerInput() {\n  const { state, actions: { update }, meta: { inputRef } } = use(ComposerContext)\n  return <TextInput ref={inputRef} value={state.input}\n    onChangeText={(t) => update((s) => ({ ...s, input: t }))} />\n}\n\nconst Composer = {\n  Provider: ComposerProvider, Frame: ComposerFrame,\n  Input: ComposerInput, Submit: ComposerSubmit, Footer: ComposerFooter,\n}\n\n// Consumers compose exactly what they need\n<Composer.Provider state={state} actions={actions} meta={meta}>\n  <Composer.Frame>\n    <Composer.Input />\n    <Composer.Footer><Composer.Formatting /><Composer.Submit /></Composer.Footer>\n  </Composer.Frame>\n</Composer.Provider>"
      },
      {
        "title": "3. Generic Context Interface (Dependency Injection)",
        "body": "Define a generic interface with state, actions, and meta. Any provider\nimplements this contract — enabling the same UI to work with different state\nimplementations. The provider is the only place that knows how state is managed.\n\ninterface ComposerContextValue {\n  state: { input: string; attachments: Attachment[]; isSubmitting: boolean }\n  actions: { update: (fn: (s: ComposerState) => ComposerState) => void; submit: () => void }\n  meta: { inputRef: React.RefObject<TextInput> }\n}\n\n// Provider A: Local state for ephemeral forms\nfunction ForwardMessageProvider({ children }: { children: React.ReactNode }) {\n  const [state, setState] = useState(initialState)\n  return (\n    <ComposerContext value={{ state, actions: { update: setState, submit: useForwardMessage() },\n      meta: { inputRef: useRef(null) } }}>{children}</ComposerContext>\n  )\n}\n\n// Provider B: Global synced state for channels\nfunction ChannelProvider({ channelId, children }: Props) {\n  const { state, update, submit } = useGlobalChannel(channelId)\n  return (\n    <ComposerContext value={{ state, actions: { update, submit },\n      meta: { inputRef: useRef(null) } }}>{children}</ComposerContext>\n  )\n}\n\nSwap the provider, keep the UI. Same Composer.Input works with both."
      },
      {
        "title": "4. Lift State into Providers",
        "body": "Move state into dedicated provider components so sibling components outside the\nmain UI can access and modify state without prop drilling or refs.\n\n// BAD — state trapped inside component; siblings can't access it\nfunction ForwardMessageComposer() {\n  const [state, setState] = useState(initialState)\n  return <Composer.Frame><Composer.Input /><Composer.Footer /></Composer.Frame>\n}\nfunction ForwardMessageDialog() {\n  return (\n    <Dialog>\n      <ForwardMessageComposer />\n      <MessagePreview />        {/* Can't access composer state */}\n      <ForwardButton />         {/* Can't call submit */}\n    </Dialog>\n  )\n}\n\n// GOOD — state lifted to provider; any descendant can access it\nfunction ForwardMessageProvider({ children }: { children: React.ReactNode }) {\n  const [state, setState] = useState(initialState)\n  const submit = useForwardMessage()\n  return (\n    <Composer.Provider state={state} actions={{ update: setState, submit }}\n      meta={{ inputRef: useRef(null) }}>{children}</Composer.Provider>\n  )\n}\nfunction ForwardMessageDialog() {\n  return (\n    <ForwardMessageProvider>\n      <Dialog>\n        <ForwardMessageComposer />\n        <MessagePreview />       {/* Reads state from context */}\n        <ForwardButton />        {/* Calls submit from context */}\n      </Dialog>\n    </ForwardMessageProvider>\n  )\n}\nfunction ForwardButton() {\n  const { actions } = use(Composer.Context)\n  return <Button onPress={actions.submit}>Forward</Button>\n}\n\nKey insight: Components that need shared state don't have to be visually\nnested — they just need to be within the same provider."
      },
      {
        "title": "5. Explicit Variant Components",
        "body": "Instead of one component with many boolean props, create explicit variants.\nEach composes the pieces it needs — self-documenting, no impossible states.\n\n// BAD — what does this render?\n<Composer isThread isEditing={false} channelId=\"abc\" showAttachments showFormatting={false} />\n\n// GOOD — immediately clear\n<ThreadComposer channelId=\"abc\" />\n<EditMessageComposer messageId=\"xyz\" />\n<ForwardMessageComposer messageId=\"123\" />\n\nEach variant is explicit about its provider/state, UI elements, and actions."
      },
      {
        "title": "6. Children Over Render Props",
        "body": "Use children for composition instead of renderX props. Children are more\nreadable and compose naturally.\n\n// BAD — render props\n<Composer\n  renderHeader={() => <CustomHeader />}\n  renderFooter={() => <><Formatting /><Emojis /></>}\n/>\n\n// GOOD — children composition\n<Composer.Frame>\n  <CustomHeader />\n  <Composer.Input />\n  <Composer.Footer><Composer.Formatting /><SubmitButton /></Composer.Footer>\n</Composer.Frame>\n\nWhen render props are appropriate: When the parent needs to pass data back\n(e.g., renderItem={({ item, index }) => ...})."
      },
      {
        "title": "Decision Guide",
        "body": "Component has 3+ boolean props? → Extract explicit variants (1, 5)\nComponent has render props? → Convert to compound components (2, 6)\nSiblings need shared state? → Lift state to provider (4)\nSame UI, different data sources? → Generic context interface (3)\nBuilding a component library? → Apply all patterns together"
      }
    ],
    "body": "React Composition Patterns\n\nComposition patterns for building flexible, maintainable React components. Avoid boolean prop proliferation by using compound components, lifting state, and composing internals. These patterns make codebases easier to work with as they scale.\n\nWhen to Apply\nRefactoring components with many boolean props\nBuilding reusable component libraries\nDesigning flexible component APIs\nWorking with compound components or context providers\nPattern Overview\n#\tPattern\tImpact\n1\tAvoid Boolean Props\tCRITICAL\n2\tCompound Components\tHIGH\n3\tContext Interface (DI)\tHIGH\n4\tState Lifting\tHIGH\n5\tExplicit Variants\tMEDIUM\n6\tChildren Over Render Props\tMEDIUM\nInstallation\nOpenClaw / Moltbot / Clawbot\nnpx clawhub@latest install react-composition\n\n1. Avoid Boolean Prop Proliferation\n\nDon't add boolean props like isThread, isEditing, isDMThread to customize behavior. Each boolean doubles possible states and creates unmaintainable conditional logic. Use composition instead.\n\n// BAD — boolean props create exponential complexity\nfunction Composer({ isThread, isDMThread, isEditing, isForwarding }: Props) {\n  return (\n    <form>\n      <Input />\n      {isDMThread ? <AlsoSendToDMField /> : isThread ? <AlsoSendToChannelField /> : null}\n      {isEditing ? <EditActions /> : isForwarding ? <ForwardActions /> : <DefaultActions />}\n    </form>\n  )\n}\n\n// GOOD — composition eliminates conditionals\nfunction ChannelComposer() {\n  return (\n    <Composer.Frame>\n      <Composer.Input />\n      <Composer.Footer><Composer.Attachments /><Composer.Submit /></Composer.Footer>\n    </Composer.Frame>\n  )\n}\n\nfunction ThreadComposer({ channelId }: { channelId: string }) {\n  return (\n    <Composer.Frame>\n      <Composer.Input />\n      <AlsoSendToChannelField id={channelId} />\n      <Composer.Footer><Composer.Submit /></Composer.Footer>\n    </Composer.Frame>\n  )\n}\n\n\nEach variant is explicit about what it renders. Shared internals without a monolithic parent.\n\n2. Compound Components\n\nStructure complex components with shared context. Each subcomponent accesses state via context, not props. Export as a namespace object.\n\nconst ComposerContext = createContext<ComposerContextValue | null>(null)\n\nfunction ComposerProvider({ children, state, actions, meta }: ProviderProps) {\n  return <ComposerContext value={{ state, actions, meta }}>{children}</ComposerContext>\n}\nfunction ComposerInput() {\n  const { state, actions: { update }, meta: { inputRef } } = use(ComposerContext)\n  return <TextInput ref={inputRef} value={state.input}\n    onChangeText={(t) => update((s) => ({ ...s, input: t }))} />\n}\n\nconst Composer = {\n  Provider: ComposerProvider, Frame: ComposerFrame,\n  Input: ComposerInput, Submit: ComposerSubmit, Footer: ComposerFooter,\n}\n\n// Consumers compose exactly what they need\n<Composer.Provider state={state} actions={actions} meta={meta}>\n  <Composer.Frame>\n    <Composer.Input />\n    <Composer.Footer><Composer.Formatting /><Composer.Submit /></Composer.Footer>\n  </Composer.Frame>\n</Composer.Provider>\n\n3. Generic Context Interface (Dependency Injection)\n\nDefine a generic interface with state, actions, and meta. Any provider implements this contract — enabling the same UI to work with different state implementations. The provider is the only place that knows how state is managed.\n\ninterface ComposerContextValue {\n  state: { input: string; attachments: Attachment[]; isSubmitting: boolean }\n  actions: { update: (fn: (s: ComposerState) => ComposerState) => void; submit: () => void }\n  meta: { inputRef: React.RefObject<TextInput> }\n}\n\n// Provider A: Local state for ephemeral forms\nfunction ForwardMessageProvider({ children }: { children: React.ReactNode }) {\n  const [state, setState] = useState(initialState)\n  return (\n    <ComposerContext value={{ state, actions: { update: setState, submit: useForwardMessage() },\n      meta: { inputRef: useRef(null) } }}>{children}</ComposerContext>\n  )\n}\n\n// Provider B: Global synced state for channels\nfunction ChannelProvider({ channelId, children }: Props) {\n  const { state, update, submit } = useGlobalChannel(channelId)\n  return (\n    <ComposerContext value={{ state, actions: { update, submit },\n      meta: { inputRef: useRef(null) } }}>{children}</ComposerContext>\n  )\n}\n\n\nSwap the provider, keep the UI. Same Composer.Input works with both.\n\n4. Lift State into Providers\n\nMove state into dedicated provider components so sibling components outside the main UI can access and modify state without prop drilling or refs.\n\n// BAD — state trapped inside component; siblings can't access it\nfunction ForwardMessageComposer() {\n  const [state, setState] = useState(initialState)\n  return <Composer.Frame><Composer.Input /><Composer.Footer /></Composer.Frame>\n}\nfunction ForwardMessageDialog() {\n  return (\n    <Dialog>\n      <ForwardMessageComposer />\n      <MessagePreview />        {/* Can't access composer state */}\n      <ForwardButton />         {/* Can't call submit */}\n    </Dialog>\n  )\n}\n\n// GOOD — state lifted to provider; any descendant can access it\nfunction ForwardMessageProvider({ children }: { children: React.ReactNode }) {\n  const [state, setState] = useState(initialState)\n  const submit = useForwardMessage()\n  return (\n    <Composer.Provider state={state} actions={{ update: setState, submit }}\n      meta={{ inputRef: useRef(null) }}>{children}</Composer.Provider>\n  )\n}\nfunction ForwardMessageDialog() {\n  return (\n    <ForwardMessageProvider>\n      <Dialog>\n        <ForwardMessageComposer />\n        <MessagePreview />       {/* Reads state from context */}\n        <ForwardButton />        {/* Calls submit from context */}\n      </Dialog>\n    </ForwardMessageProvider>\n  )\n}\nfunction ForwardButton() {\n  const { actions } = use(Composer.Context)\n  return <Button onPress={actions.submit}>Forward</Button>\n}\n\n\nKey insight: Components that need shared state don't have to be visually nested — they just need to be within the same provider.\n\n5. Explicit Variant Components\n\nInstead of one component with many boolean props, create explicit variants. Each composes the pieces it needs — self-documenting, no impossible states.\n\n// BAD — what does this render?\n<Composer isThread isEditing={false} channelId=\"abc\" showAttachments showFormatting={false} />\n\n// GOOD — immediately clear\n<ThreadComposer channelId=\"abc\" />\n<EditMessageComposer messageId=\"xyz\" />\n<ForwardMessageComposer messageId=\"123\" />\n\n\nEach variant is explicit about its provider/state, UI elements, and actions.\n\n6. Children Over Render Props\n\nUse children for composition instead of renderX props. Children are more readable and compose naturally.\n\n// BAD — render props\n<Composer\n  renderHeader={() => <CustomHeader />}\n  renderFooter={() => <><Formatting /><Emojis /></>}\n/>\n\n// GOOD — children composition\n<Composer.Frame>\n  <CustomHeader />\n  <Composer.Input />\n  <Composer.Footer><Composer.Formatting /><SubmitButton /></Composer.Footer>\n</Composer.Frame>\n\n\nWhen render props are appropriate: When the parent needs to pass data back (e.g., renderItem={({ item, index }) => ...}).\n\nDecision Guide\nComponent has 3+ boolean props? → Extract explicit variants (1, 5)\nComponent has render props? → Convert to compound components (2, 6)\nSiblings need shared state? → Lift state to provider (4)\nSame UI, different data sources? → Generic context interface (3)\nBuilding a component library? → Apply all patterns together"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/wpank/react-composition",
    "publisherUrl": "https://clawhub.ai/wpank/react-composition",
    "owner": "wpank",
    "version": "1.0.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/react-composition",
    "downloadUrl": "https://openagent3.xyz/downloads/react-composition",
    "agentUrl": "https://openagent3.xyz/skills/react-composition/agent",
    "manifestUrl": "https://openagent3.xyz/skills/react-composition/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/react-composition/agent.md"
  }
}