news May 23, 2026 · 60 views · 2 min read

Transitioning Vue 3's defineExpose() to React with VuReact

Discover how VuReact seamlessly compiles Vue 3's defineExpose() into React's forwardRef() and useImperativeHandle(), maintaining the original functionality and interaction model.

Introduction

VuReact provides an efficient solution for developers transitioning from Vue to React, particularly when dealing with Vue 3's defineExpose() macro. This guide explores how VuReact transforms this macro into a React-compatible format.

Understanding the Basics

Vue defineExpose() Overview

In Vue 3's <script setup>, the defineExpose() macro is pivotal for exposing internal states and methods from a child component to its parent. This functionality plays a crucial role in Vue's component interaction model.

The React Equivalent

To mirror Vue’s defineExpose() in React, VuReact employs a combination of forwardRef() and useImperativeHandle(). This approach allows React components to maintain similar exposure patterns as in Vue, ensuring a smooth transition.

Compilation Mapping

From Vue to React

In Vue, defineExpose() is utilized as follows:

<script setup lang="ts">
import { ref, defineExpose } from 'vue';

defineProps<{ title: string }>();

const count = ref(0);
const increment = () => count.value++;

defineExpose({
  count,
  increment,
});
</script>

When compiled to React with VuReact, this transforms into:

import { forwardRef, useCallback, useImperativeHandle, memo } from 'react';
import { useVRef } from '@vureact/runtime-core';

type IComponentProps = { title: string };

const Component = memo(
  forwardRef<any, IComponentProps>((props, expose) => {
    const count = useVRef(0);

    const increment = useCallback(() => {
      count.value++;
    }, [count.value]);

    useImperativeHandle(expose, () => ({
      count,
      increment,
    }));

    return <div>{count.value}</div>;
  }),
);

export default Component;

Parent Component Access

In Vue, parent components retrieve the exposed data via ref and expose. This is mirrored in React using useRef() and ref.current.

Vue Parent Example

<template>
  <Component ref="childRef" />
</template>

<script setup lang="ts">
import { onMounted, ref } from 'vue';

const childRef = ref();

onMounted(() => {
  childRef.value?.count.value; // 0
  childRef.value?.increment();
  childRef.value?.count.value; // 1
});
</script>

React Parent Example

const Parent = () => {
  const childRef = useRef();

  useMounted(() => {
    childRef.current?.count.value; // 0
    childRef.current?.increment();
    childRef.current?.count.value; // 1
  });

  return <Component ref={childRef} />;
};

VuReact ensures that the interaction model remains consistent, making the adaptation process intuitive.

Conclusion

VuReact effectively bridges the gap between Vue 3 and React, particularly in handling component state exposure. By maintaining the original Vue interaction patterns, VuReact facilitates an easier transition for developers.

Further Information

For more details, visit the VuReact GitHub repository and the official documentation.

Discussion

0 Comments

Leave a Comment

Comments are moderated and will appear after approval.