Remix.run Logo
kqr 9 hours ago

You certainly don't need JSX for React, nor a build chain. My ship investor Kelly trainer game[1] is a simple React application in a single HTML file. The initial page load is slow because I experimented with using built-in browser module support to pull in React, but if you change it to serve a pre-built library from a CDN instead then also the initial page load is fast.

You can view the source on that page to see how simple it can be, but here is the essence:

1. Import React. This is the step you can do from a CDN instead of you want a faster initial page load. (Okay apparently I'm using Preact here, but it's effectively the same thing.)

    import { h, render, createContext } from 'https://unpkg.com/preact@latest?module';
    import { useState, useMemo } from 'https://unpkg.com/preact@latest/hooks/dist/hooks.module.js?module';
2. Render React components in HTML elements. This is where the progressiveness comes in. You don't have to render the entire web page as one React component; you can choose to only render some components in some locations of the page.

    const appDiv = document.getElementById('app');
    render(h(App, null), appDiv);
3. The React components are plain ES functions that can use hooks etc. from React, as usual.

    function App() {
        let [state, setState] = useState(initial_state);
        // --------------->8------
        return h('main', null, [
             h(Description, {
                 turn: state.turn,
                 strait: state.straits[state.shipment.strait]
             }),
             h(Bankroll, { wealth: state.wealth.first() }),
             h(Investment, { invest, state }),
             h(WealthHistory, { wealth: state.wealth }),
         ]);
    }
Instead of JSX we use the h function, which takes either tag name in a string, or another React component, takes an attribute dictionary as the second argument, and a list of children as the third. That's it. Super easy.

[1]: https://xkqr.org/ship-investor/ship-investor.html

(There is at least one bug in the game logic that prevents this game from being any fun at the moment. I have not taken the time to investigate why that happens, because I have not offered the training that used this tool to anyone in a few years.)

((If you enjoyed the game anyway and want more of a challenge, you might want to try the continuous version: https://xkqr.org/ship-investor/ship-investor-2.html. There is also a secret third version simulating futures which I have never shared with anyone before. It is playable, but not finished: https://xkqr.org/ship-investor/ship-investor-3.html))

actinium226 2 hours ago | parent | next [-]

You've given this example about how to use React without JSX but actually you're not using React but Preact, which is a different library. Preact, to its credit, actually has instructions for using it without JSX right in their getting started guide: https://preactjs.com/guide/v10/getting-started/#alternatives.... In fact it's the very first paragraph.

React itself buries this information in a reference (https://react.dev/reference/react/createElement#creating-an-...), and the reference doesn't even give a complete example because the example still uses JSX to render the root component.

And I'm not sure if Preact is really a viable alternative to React. If a library I want to use can't work via preact/compat, what then? Do stackoverflow solutions for React problems apply to Preact? I imagine at least some might not. Given these limitations, is there a reason someone would choose Preact over a framework that has its own ecosystem, like Vue for example?

chrismorgan 7 hours ago | parent | prev [-]

> 1. Import React. This is the step you can do from a CDN instead of you want a faster initial page load.

Using a CDN is very unlikely to get you a faster initial page load. Initialising an HTTPS connection to a new host is almost always going to take longer than serving that file first-party; there’s even a decent chance of this if your server is on the other side of the world.

kqr 7 hours ago | parent [-]

The problem in this case is not the HTTPS connection, but the fact that browsers, when importing ES6 modules, import all their transitive dependencies one by one. This means they can make a bazillion requests under the hood when importing just one library. A CDN is likely to have the library bundled and minified with its dependencies, turning those bazillion requests into a single one, which is much faster.

chrismorgan 6 hours ago | parent [-]

In that case, if you’re actually talking about bundled versus many-files, please don’t say “CDN … if you want a faster initial page load”. Public CDNs made some sense as performance advice long ago, but now they never really do, but there are still many people who don’t realise it.

kqr 5 hours ago | parent [-]

You're right. That was a bad choice of wording on my part. Thanks for clarifying!