create-mixins | Skill Performance & Reviews | TopRankSkills

TopRank Skills

Home / Skills / development / create-mixins

create-mixins

maintained by remix-run

star 32.5k account_tree 2.7k verified_user MIT License
bolt View GitHub

name: create-mixins description: Create @remix-run/component mixins using createMixin with lifecycle-first semantics. Use when adding new mixins with correct runtime behavior and type flow.

Creating Mixins (@remix-run/component)

Use this skill when authoring new mixins in packages/component.

The key principle: model the real runtime contract first, then write the smallest code that matches it.

Core Runtime Semantics

Treat these as constraints, not suggestions:

  1. A mixin handle is tied to one mounted host node lifecycle.
  2. insert is the host-node availability point for imperative setup.
  3. remove is teardown for that same lifecycle.
  4. queueTask runs post-commit and receives (node, signal) for mixins.
  5. Mixin render functions should stay pure; side effects belong in insert, remove, or queued work.
createMixin<NodeType>((handle) => {
  // Setup runs once per handle lifecycle.
  handle.addEventListener('insert', (event) => {
    // event.node is the mounted host node for this lifecycle.
    // Attach imperative effects here.
  })

  handle.addEventListener('remove', () => {
    // Teardown for the same lifecycle.
    // Remove listeners, abort work, release resources.
  })

  return (props) => {
    // Render stays pure: derive props/JSX only.
    // Post-commit work goes in queueTask when needed.
    handle.queueTask((node) => {
      // Runs after commit with the concrete host node.
    })
    return <handle.element {...props} />
  }
})

If your implementation assumes semantics that do not exist (node swapping, repeated insert for the same handle, etc.), remove that logic.

Authoring Rules

  1. Start with lifecycle truth:
    • Use insert for attach/setup.
    • Use remove for detach/cleanup.
  2. Keep state minimal and intentional:
    • Do not keep mutable state "just in case" if runtime guarantees make it unnecessary.
  3. Be precise with defensive checks:
    • Use invariant(...) when a condition is guaranteed by runtime and violation means framework bug.
    • Use soft guards only when nullability is genuinely part of valid runtime flow.
  4. Use queueTask((node, signal) => ...) for post-commit DOM work.
    • In most mixins, only node is needed.
    • Reach for signal only when work is async or cancellation-sensitive.
  5. Do not add signal.aborted checks for purely synchronous work.
  6. Favor function expression for helpers in scope.
  7. Avoid speculative runtime assumptions.

Preferred Patterns

1) Pure prop transform mixin

let withTitle = createMixin((handle) => (title: string, props: { title?: string }) => (
  <handle.element {...props} title={title} />
))

2) Lifecycle-managed imperative listener

let withFocus = createMixin<HTMLElement>((handle) => {
  handle.addEventListener('insert', (event) => {
    event.node.focus()
  })
  return (props) => <handle.element {...props} />
})

3) Post-commit rebind with node provided by queueTask

handle.queueTask((node) => {
  node.removeEventListener(prevType, stableHandler, prevCapture)
  node.addEventListener(nextType, stableHandler, nextCapture)
})

Anti-Patterns

  • Adding state for hypothetical runtime scenarios.
  • Broad defensive null checks where runtime guarantees presence.
  • Mixing setup/cleanup side effects into render-only code paths.
  • Using signal.aborted in synchronous non-racy code as boilerplate.
  • Hiding semantic uncertainty with casts instead of fixing types/contracts.

Mixin Creation Checklist

  • Runtime assumptions are stated and match reconciler behavior.
  • Lifecycle wiring uses insert/remove directly.
  • State is minimal; no "might change later" scaffolding.
  • queueTask used only where post-commit timing is required.
  • Type flow from createMixin<ThisType> is preserved.
  • Tests cover ordering, teardown, and type inference contracts.

chat Comments (0)

chat_bubble_outline

No comments yet. Be the first to share your thoughts!

Skill Details

GitHub Stars 32.5k
GitHub Forks 2.7k
Created Mar 2026
Last Updated 2个月前
development development full stack

Related Skills

nestjs-expert
chevron_right
performance-optimization
chevron_right
makepad-patterns
chevron_right
makepad-reference
chevron_right
devup-ui
chevron_right

Build your own?

Join 12,000+ developers contributing to the Claude ecosystem.