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:
- All Vue and React snippets focus on core logic only, with full component wrappers and unrelated configuration omitted.
- 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>
- 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]);
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>
- Compiled React
const Parent = memo(() => {
const current = useVRef('');
return <Child name={current.value} onUpdateName={(value) => (current.value = value)} />;
});
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>
- Compiled React
type ICompProps = {
onSubmit?: (value: string) => void;
};
const handleSubmit = useCallback(() => {
props.onSubmit?.('ok');
}, [props.onSubmit]);
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)