Simplify React code using Babel transpiling: useState

Hi devs,

I've been working with react hooks for several years now, more or less since the beginning. It is a huge improvement compared to class components you had to use before, but it still has a lot of code to write, especially compared to Svelte.

This made me think: is it possible to reduce React syntax in order to make it more concise? The short answer is yes. The solution that I decided to adopt is to write a Babel plugin (since you need Babel in any case with React) to leverage some work during the build.

The first thing I worked on is useState. My goal was to remove destructuring of the useState hook and to have a simple variable declaration to be reactive by itself. As the result I got this:

// useState import is not necessary

function Example() {
    let $value = 5;
    return (
        <button onClick={() => $value++}>{$value}</button>
    );
}

The snippet above is equivalent to this:

import { useState } from "react";

function Example() {
    const [value, setValue] = useState(5);
    return (
        <button onClick={() => setValue(value+1)}>{value}</button>
    );
}

As you can see, the gains here are:

  • simpler, more concise declaration of reactive property
  • no need for setter, assigning new value to the property will trigger reactivity
  • no need to import useState (not a big deal, it's done automatically in any case, but still).
  • better readability (imo)

After I was done with useState (with initial prototype), I started thinking about useEffect and useMemo. The problem is that they are much trickier to simplify, and it's hard to come with a cleaner syntax for them. This is what I had in mind:

function Example() {
    let $value = 5;
    const $memo = $value * 2;
    // eq: const memo = useMemo(() => $value * 2, [$value]);

    $ => {
        // effect body
        return () => {
            // effect cleanup
        }
    }
    /** the above is the same as:
     * useEffect(() => {
     *     // effect body
     *     return () => {
     *         // effect cleanup
     *     }
     * }, []);
     */

    $ => {
        console.log($memo);
    }
    /** the above is the same as:
     * useEffect(() => {
     *     console.log($memo);
     * }, [$memo]);
     */

    return (
        <button onClick={() => $value++}>{$value}</button>
    );
}

Notice there is no need for dependencies for both useMemo and useEffect alternatives. They will be injected during build.

Said that, my questions are:

  • Does it make sense? Or, would you use something like this, or would you stick with classic hooks?
  • If yes, what syntax would you like it to be?
  • Is there already something similar?

32