DEV Community

Ryan John
Ryan John

Posted on • Originally published at vureact.top

How does VuReact optimize Vue 3's top-level constants and variables for React?

VuReact 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 VuReact optimizes top-level constants and variables when compiling Vue 3 code to React.

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 top-level const declarations and expression-based variable semantics in Vue 3.

Compilation Mapping

Top-level Vue const -> static hoisting outside the React component

In Vue, top-level constants inside <script setup> are often used for static configuration values, defaults, or fixed flags.

VuReact performs static analysis on those declarations. If the initializer is a simple literal such as a string, number, or boolean, it can hoist that value outside the React component so it is not recreated on every render.

  • Vue
<script setup lang="ts">
const defaultValue = 1;
const isEnabled = true;
</script>
Enter fullscreen mode Exit fullscreen mode
  • Compiled React
const defaultValue = 1;
const isEnabled = true;

const Comp = memo(() => {
  return <></>;
});
Enter fullscreen mode Exit fullscreen mode

As the example shows, simple top-level constants can be lifted out of the component body, which avoids repeated initialization during React renders.

Top-level computed variables -> React useMemo() with automatic dependency analysis

When a top-level variable is created from an expression that depends on reactive state, VuReact can compile it into useMemo() and generate the dependency array automatically.

Purely static expressions are left as normal values instead of being wrapped unnecessarily.

  • Vue
<script setup lang="ts">
const count = ref(0);
const state = reactive({ foo: 'bar', bar: { c: 1 } });

const memoizedObj = {
  title: 'test',
  bar: count.value,
  add: () => {
    state.bar.c++;
  },
};

const staticObj = {
  foo: 1,
  state: { bar: { c: 1 } },
};

const reactiveList = [count.value, 1, 2];
</script>
Enter fullscreen mode Exit fullscreen mode
  • Compiled React
const count = useVRef(0);
const state = useReactive({ foo: 'bar', bar: { c: 1 } });

const memoizedObj = useMemo(
  () => ({
    title: 'test',
    bar: count.value,
    add: () => {
      state.bar.c++;
    },
  }),
  [count.value, state.bar.c],
);

const staticObj = {
  foo: 1,
  state: {
    bar: { c: 1 },
  },
};

const reactiveList = useMemo(() => [count.value, 1, 2], [count.value]);
Enter fullscreen mode Exit fullscreen mode

In this example:

  • memoizedObj is compiled into useMemo() because it depends on count.value and state.bar.c
  • staticObj stays a normal static object because it does not depend on reactive state
  • reactiveList is also compiled into useMemo() with an automatically generated dependency array

That gives React the memoization it needs without forcing developers to write the dependency logic by hand.

Related Links

Top comments (0)