All skills
vercel-labs avatar

/composition-patterns

@a5343bd official
by Vercel Labsvercel-labs/agent-skills32k stars
2,784

React composition patterns that scale. Use when refactoring components with boolean prop proliferation, building flexible component libraries, or designing reusable APIs. Triggers on tasks involving compound components, render props, context providers, or component architecture. Includes React 19 API changes.

Use this Skill: https://skilld.dev/gh/vercel-labs/agent-skills/composition-patterns

This session only. Nothing lands on disk.

rulesstate-lift-state.md

≈806 tokens on demand. Your agent reads this file only when SKILL.md points to it.

Lift State into Provider Components

Move state management into dedicated provider components. This allows sibling components outside the main UI to access and modify state without prop drilling or awkward refs.

Incorrect (state trapped inside component):

function ForwardMessageComposer() {
  const [state, setState] = useState(initialState)
  const forwardMessage = useForwardMessage()

  return (
    <Composer.Frame>
      <Composer.Input />
      <Composer.Footer />
    </Composer.Frame>
  )
}

// Problem: How does this button access composer state?
function ForwardMessageDialog() {
  return (
    <Dialog>
      <ForwardMessageComposer />
      <MessagePreview /> {/* Needs composer state */}
      <DialogActions>
        <CancelButton />
        <ForwardButton /> {/* Needs to call submit */}
      </DialogActions>
    </Dialog>
  )
}

Incorrect (useEffect to sync state up):

function ForwardMessageDialog() {
  const [input, setInput] = useState('')
  return (
    <Dialog>
      <ForwardMessageComposer onInputChange={setInput} />
      <MessagePreview input={input} />
    </Dialog>
  )
}

function ForwardMessageComposer({ onInputChange }) {
  const [state, setState] = useState(initialState)
  useEffect(() => {
    onInputChange(state.input) // Sync on every change 😬
  }, [state.input])
}

Incorrect (reading state from ref on submit):

function ForwardMessageDialog() {
  const stateRef = useRef(null)
  return (
    <Dialog>
      <ForwardMessageComposer stateRef={stateRef} />
      <ForwardButton onPress={() => submit(stateRef.current)} />
    </Dialog>
  )
}

Correct (state lifted to provider):

function ForwardMessageProvider({ children }: { children: React.ReactNode }) {
  const [state, setState] = useState(initialState)
  const forwardMessage = useForwardMessage()
  const inputRef = useRef(null)

  return (
    <Composer.Provider
      state={state}
      actions={{ update: setState, submit: forwardMessage }}
      meta={{ inputRef }}
    >
      {children}
    </Composer.Provider>
  )
}

function ForwardMessageDialog() {
  return (
    <ForwardMessageProvider>
      <Dialog>
        <ForwardMessageComposer />
        <MessagePreview /> {/* Custom components can access state and actions */}
        <DialogActions>
          <CancelButton />
          <ForwardButton /> {/* Custom components can access state and actions */}
        </DialogActions>
      </Dialog>
    </ForwardMessageProvider>
  )
}

function ForwardButton() {
  const { actions } = use(Composer.Context)
  return <Button onPress={actions.submit}>Forward</Button>
}

The ForwardButton lives outside the Composer.Frame but still has access to the submit action because it's within the provider. Even though it's a one-off component, it can still access the composer's state and actions from outside the UI itself.

Key insight: Components that need shared state don't have to be visually nested inside each other—they just need to be within the same provider.

Source: SKILL.md on GitHub

No alerts27d3 checks · Risk SAFE
  • Gen Agent Trust Hub27d

    This skill provides React composition patterns and architectural guidelines for frontend development. No security considerations were identified as the skill consists entirely of instructional documentation.

  • Socket27d

    No alerts

  • Snyk27d

    Risk: LOW · No issues

Signed by skilld at a5343bd. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub last month.

Steadyupdated 8 months ago
metadata
{
  "author": "vercel",
  "version": "1.0.0"
}
  • React
  • Refactoring
  • composition
  • component-architecture
  • state-management
  • compound-components
  • react19
  • component-library

README badge

README badge for vercel-labs/agent-skills/composition-patterns

Teaches React composition patterns to avoid boolean prop proliferation and build flexible component libraries using compound components, context providers, and state lifting. Includes guidelines for refactoring component architecture and references React 19 API changes like removing forwardRef in favor of use().

Generated from the current SKILL.md.

Does this skill cover React 19 changes?
Yes. The skill includes a React 19 APIs section covering changes like removing forwardRef in favor of use() and useContext() updates, but those rules only apply if you're using React 19 or later.
What specific composition patterns does this skill teach?
The skill covers compound components, render props, context providers, state lifting, and explicit variants. It prioritizes avoiding boolean prop proliferation by composing components instead.
Is this skill for building my own components or refactoring existing ones?
Both. Use it when refactoring components with too many boolean props, designing new component libraries, or reviewing component architecture decisions.
Does this skill include code examples?
Yes. Individual rule files contain incorrect and correct code examples with explanations for each pattern.

Generated from the current SKILL.md. These answers refresh after source changes.