DEV Community

Cover image for How does VuReact compile Vue 3's defineEmits() to React?
Ryan John
Ryan John

Posted on • Originally published at vureact.top

How does VuReact compile Vue 3's defineEmits() to React?

VuReact is a tool that compiles Vue 3 code into standard, maintainable React code. In this article, we will look at how Vue 3's defineEmits() macro is mapped into React.

If you write defineEmits() in Vue, what does VuReact generate on the React side?

Before We Start

To keep the examples easy to read, this article follows two simple conventions:

  1. All Vue and React snippets focus on core logic only, with full component wrappers and unrelated configuration omitted.
  2. The discussion assumes you are already familiar with the API shape and core behavior of Vue 3 defineEmits().

Compilation Mapping

Vue defineEmits() -> React callback props

defineEmits() is the macro used inside Vue 3 <script setup> to declare custom component events. VuReact compiles those event declarations into React-style callback props and normalizes event names into the naming conventions React developers expect.

  • Vue
<script setup lang="ts">
defineProps<{ name?: string }>();

const emit = defineEmits<{
  (e: 'save-item', payload: { id: string }): void;
  (e: 'update:name', value: string): void;
}>();

const submit = () => {
  emit('save-item', { id: '1' });
  emit('update:name', 'next');
};
</script>
Enter fullscreen mode Exit fullscreen mode
  • Compiled React
type ICompProps = {
  name?: string;
  onSaveItem?: (payload: { id: string }) => void;
  onUpdateName?: (value: string) => void;
};

const submit = useCallback(() => {
  props.onSaveItem?.({ id: '1' });
  props.onUpdateName?.('next');
}, [props.onSaveItem, props.onUpdateName]);
Enter fullscreen mode Exit fullscreen mode

As the example shows, Vue defineEmits() is not translated into a runtime Hook. Instead, VuReact turns event declarations into callback props on the React component.

Event names such as save-item and update:name are mapped into React-style names such as onSaveItem and onUpdateName, while keeping the parameter types intact.

Vue v-model:xxx -> React controlled prop mapping

Events like update:xxx are especially important because they usually power Vue's parent-child two-way binding pattern through v-model:xxx.

VuReact understands this pattern and maps it into the corresponding React prop and callback pair.

  • Vue parent usage
<template>
  <Child v-model:name="current" />
</template>

<script setup>
const current = ref('');
</script>
Enter fullscreen mode Exit fullscreen mode
  • Compiled React
const Parent = memo(() => {
  const current = useVRef('');
  return <Child name={current.value} onUpdateName={(value) => (current.value = value)} />;
});
Enter fullscreen mode Exit fullscreen mode

Vue emit() calls -> React callback invocation

In Vue, emit('event-name', payload) triggers a custom component event. In React, VuReact compiles that into callback invocation through props.

  • Vue
<script setup lang="ts">
const emit = defineEmits<{
  (e: 'submit', value: string): void;
}>();

const handleSubmit = () => {
  emit('submit', 'ok');
};
</script>
Enter fullscreen mode Exit fullscreen mode
  • Compiled React
type ICompProps = {
  onSubmit?: (value: string) => void;
};

const handleSubmit = useCallback(() => {
  props.onSubmit?.('ok');
}, [props.onSubmit]);
Enter fullscreen mode Exit fullscreen mode

VuReact maps event names and payload types at compile time, and when needed it also generates the dependency array for useCallback() so the output remains stable and maintainable.

Event name mapping rules

VuReact supports mapping common Vue event naming styles into React callback props:

  • save-item -> onSaveItem
  • update:name -> onUpdateName
  • close -> onClose

This keeps the generated API aligned with React conventions while preserving the original intent of the Vue event model.

Related Links

Repository: https://github.com/vureact-js/core

Docs: https://vureact.top/en/guide/semantic-comparison/script/define-emits.html

Top comments (0)