Skip to content

React → Vue mapping

This page expands the “Behavior (current)” section from the root README. For a complete, implementation-level checklist (parser + codegen), see Compiler features. For unsupported patterns, see limitations.

Component shape

  • One React function component per file is the intended target.
  • Default export is resolved, including through React.memo, React.forwardRef, and similar wrappers (see parser logic in src/parser/react.ts).
  • Named default-export arrow forms and function declarations are supported.
  • The template is taken from the last return that yields JSX (early returns that don’t represent the main tree can be skipped—see tests).

Setup preservation

Component body statements are emitted in source order where possible:

  • Destructuring (e.g. const { a } = useThing()), custom hooks, and nested function declarations are often emitted as verbatim script text.
  • useState-backed values get best-effort .value unwrapping inside lowered snippets when the compiler recognizes the pattern.

Hooks → Vue

ReactVue (approximate)
useStateref (+ optional setter helper)
useRefref
useMemo(() => …, deps)computed(() => …) using the real factory source when possible
useEffect(fn, [])onMounted(fn)
useEffect(fn, [deps])watch([...], fn, { flush: 'post' }) — dependency expressions are rewritten so ref-like React names map to Vue refs
useEffect(fn) (no deps array)watchEffect(fn)

Cleanup: return () => { ... } inside useEffect may still need manual mapping to watch / onMounted teardown in Vue.

JSX and template

  • Object spread on JSX elementsv-bind in the template (see fixture test/fixtures/spread.jsx).
  • Component vs DOM follows React’s usual lowercase intrinsic rule.
  • Lists: key is placed on template / v-for as appropriate (see tests for “key on template v-for”).
  • Conditionals and children are lowered into the IR template tree (TemplateNode types in src/ir/types.ts).

Output format

  • Vue 3 SFC with <script setup lang="ts"> and <template>.

Tests as specification

Behavior is pinned by test/convert.test.mjs and fixtures under test/fixtures/:

  • destructure.jsx — destructuring preserved verbatim
  • early-return.jsx — last JSX return wins
  • arrow-implicit.jsx — default export arrow + implicit return JSX
  • spread.jsx — spread → v-bind
  • use-effect.jsxuseEffectwatch / onMounted

Additional assertions in the same test file cover useMemo with props/state, v-for / key placement, and inline handlers.

Questions? parsajiravand@gmail.com · MIT License · BRANDING.md for name / fork policy · https://cross-framework.netlify.app/ · https://cross-framework-doc.netlify.app/