用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/tomevault-io/skills-registry --skill composition-patterns命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
基于 SOC 职业分类
正在显示 SKILL.md
| name | composition-patterns |
| description | | Use when this capability is needed. |
Composition patterns for flexible and maintainable React components. Avoid boolean prop abuse, use compound components, state lifting, and composing internals.
| Priority | Category | Impact | Description |
|---|---|---|---|
| 1 | Component Architecture | HIGH | Component structuring |
| 2 | State Management | MEDIUM | State management patterns |
| 3 | Implementation Patterns | MEDIUM | Implementation patterns |
| 4 | React 19 APIs | MEDIUM | React 19 changes |
Impact: CRITICAL
Boolean props lead to combinatorial explosion. Use composition instead.
// ❌ Boolean prop explosion - unmaintainable
function Composer({
isThread,
isDMThread,
isEditing,
isForwarding,
}: Props) {
return (
<form>
{isDMThread ? <DMField /> : isThread ? <ThreadField /> : null}
{isEditing ? <EditActions /> : isForwarding ? <ForwardActions /> : <DefaultActions />}
</form>
)
}
// ✅ Composition - explicit variants
function ThreadComposer({ channelId }: { channelId: string }) {
return (
<Composer.Frame>
<Composer.Input />
<AlsoSendToChannelField id={channelId} />
<Composer.Footer>
<Composer.Submit />
</Composer.Footer>
</Composer.Frame>
)
}
function EditComposer() {
return (
<Composer.Frame>
<Composer.Input />
<Composer.Footer>
<Composer.CancelEdit />
<Composer.SaveEdit />
</Composer.Footer>
</Composer.Frame>
)
}
Impact: HIGH
Structure complex components into subcomponents connected by shared context.
// ❌ Monolithic + render props
function Composer({
renderHeader,
renderFooter,
showAttachments,
}: Props) {
return (
<form>
{renderHeader?.()}
<Input />
{showAttachments && <Attachments />}
{renderFooter?.()}
</form>
)
}
// ✅ Compound components + shared context
const ComposerContext = createContext<ComposerContextValue | null>(null)
function ComposerProvider({ children, state, actions, meta }: ProviderProps) {
return (
<ComposerContext value={{ state, actions, meta }}>
{children}
</ComposerContext>
)
}
function ComposerInput() {
const { state, actions: { update } } = use(ComposerContext)
return <TextInput value={state.input} onChangeText={text => update(s => ({ ...s, input: text }))} />
}
// Export as compound component
= {
: ,
: ,
: ,
: ,
: ,
}
<. state={state} actions={actions} meta={meta}>
</.>
Impact: MEDIUM
Provider knows state implementation, UI only uses context interface.
// ❌ UI coupled to state implementation
function ChannelComposer({ channelId }: { channelId: string }) {
const state = useGlobalChannelState(channelId) // Coupled to specific implementation
const { submit } = useChannelSync(channelId)
return <Composer.Input value={state.input} />
}
// ✅ State management separated in Provider
function ChannelProvider({ channelId, children }: Props) {
const { state, update, submit } = useGlobalChannel(channelId)
return (
<Composer.Provider state={state} actions={{ update, submit }}>
{children}
</Composer.Provider>
)
}
// UI only needs interface
function ChannelComposer() {
return (
<Composer.Frame>
<Composer.Input /> {/* Reads state from context */}
<Composer.Submit />
</Composer.Frame>
)
}
Impact: HIGH
Define generic interface with 3 parts: state, actions, meta.
// Generic interface - any provider can implement
interface ComposerContextValue {
state: {
input: string
attachments: Attachment[]
isSubmitting: boolean
}
actions: {
update: (updater: (state: State) => State) => void
submit: () => void
}
meta: {
inputRef: React.RefObject<TextInput>
}
}
// Provider A: Local state
function ForwardMessageProvider({ children }) {
const [state, setState] = useState(initialState)
return <ComposerContext value={{ state, actions: { update: setState, submit }, meta }}>{children}</ComposerContext>
}
// Provider B: Global synced state
function ChannelProvider({ channelId, children }) {
const { state, update, submit } = useGlobalChannel(channelId)
return
}
Impact: HIGH
Lift state to Provider so sibling components can access it.
// ❌ State trapped inside component
function ForwardMessageDialog() {
return (
<Dialog>
<ForwardMessageComposer /> {/* state trapped here */}
<MessagePreview /> {/* Cannot access state! */}
<ForwardButton /> {/* Cannot call submit! */}
</Dialog>
)
}
// ✅ Lift state to Provider
function ForwardMessageDialog() {
return (
<ForwardMessageProvider>
<Dialog>
<ForwardMessageComposer />
<MessagePreview /> {/* Access state via context */}
<ForwardButton /> {/* Call submit via context */}
</Dialog>
</ForwardMessageProvider>
)
}
// Anywhere inside Provider can access state/actions
function ForwardButton() {
const { actions } = use(ComposerContext)
return <Button onPress={actions.submit}>Forward</Button>
}
Impact: MEDIUM
Create explicit variant components instead of boolean props.
// ❌ Unclear what UI renders
<Composer isThread isEditing={false} channelId="abc" showAttachments />
// ✅ Immediately clear
<ThreadComposer channelId="abc" />
<EditMessageComposer messageId="xyz" />
<ForwardMessageComposer messageId="123" />
Impact: MEDIUM
Use children for composition instead of renderX props.
// ❌ Render props - hard to read
<Composer
renderHeader={() => <CustomHeader />}
renderFooter={() => <><Formatting /><Emojis /></>}
/>
// ✅ Children - natural composition
<Composer.Frame>
<CustomHeader />
<Composer.Input />
<Composer.Footer>
<Composer.Formatting />
<Composer.Emojis />
</Composer.Footer>
</Composer.Frame>
When render props appropriate: Parent needs to pass data to children
<List data={items} renderItem={({ item, index }) => <Item item={item} />} />
⚠️ React 19+ only. Skip this section for React 18 or below.
// ❌ forwardRef (unnecessary in React 19)
const ComposerInput = forwardRef<TextInput, Props>((props, ref) => {
return <TextInput ref={ref} {...props} />
})
// ✅ ref as regular prop
function ComposerInput({ ref, ...props }: Props & { ref?: React.Ref<TextInput> }) {
return <TextInput ref={ref} {...props} />
}
// ❌ useContext (React 19)
const value = useContext(MyContext)
// ✅ use() - conditional calls possible
const value = use(MyContext)
| Check | Rule |
|---|---|
| [ ] | 3+ Boolean props? → Refactor to composition |
| [ ] | Complex conditional rendering? → Create explicit variants |
| [ ] | State trapped in component? → Lift to Provider |
| [ ] | renderX props? → Change to children |
| [ ] | React 19? → Remove forwardRef, use use() |
/react-best-practices - Performance optimization (waterfall, bundle, rendering)/web-design-guidelines - UI/UX quality (accessibility, interaction)/design-patterns - General design patternsConverted and distributed by TomeVault — claim your Tome and manage your conversions.