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

> Source: <https://dev.to/smirk9581/how-does-vureact-compile-vue-3s-defineexpose-to-react-1jhj>
> Published: 2026-05-23 02:25:00+00:00

[VuReact](https://github.com/vureact-js/core) is a compiler toolchain for migrating from Vue to React — and for writing React with Vue 3 syntax.

In this article, we will look at how Vue 3's `defineExpose()`

macro is mapped into React.

## 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
`defineExpose()`

.

## Compilation Mapping

### Vue `defineExpose()`

-> React `forwardRef()`

+ `useImperativeHandle()`

`defineExpose()`

is the macro used inside Vue 3 `<script setup>`

to expose internal state or methods from a child component to its parent.

VuReact compiles that pattern into React's `forwardRef()`

plus `useImperativeHandle()`

, allowing the parent component to access the exposed object through a ref.

- Vue

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

defineProps<{ title: string }>();

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

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

- Compiled React

``` js
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;
```

As the example shows, Vue `defineExpose()`

is compiled into React's `forwardRef()`

and `useImperativeHandle()`

combination.

VuReact preserves the structure of the exposed object, and exposed refs still use `.value`

, which keeps the interaction model close to Vue.

### Parent access: Vue `ref`

+ expose -> React `ref.current`

In Vue, parent components access exposed child values through `ref`

and `expose`

. In React, VuReact maps that pattern to `useRef()`

plus `ref.current`

.

- Vue parent

```
<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>
```

- Compiled React parent

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

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

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

VuReact keeps the parent access path aligned with the original Vue intent, so exposed child refs and methods remain straightforward to use.
