25 May 2019 • Server side React

JSX is nice. Most templating languages start with HTML and add dumpy scripting on top, while JSX adds HTML syntax to javascript. It means you (mostly) get to use normal language constructs and flow control and it's much less annoying. I'd like to see more languages go this way.

If you only want to use it server side so people don't have to enable javascript and run 10MB of react, you can do this:

function flatten( arr ) : string[] {
	let flattened = [ ];

	function flatten_impl( flattened, arr ) {
		if( Array.isArray( arr ) ) {
			for( const e of arr ) {
				flatten_impl( flattened, e );
			}
		}
		else {
			flattened.push( arr );
		}
	}

	flatten_impl( flattened, arr );
	return flattened;
}

type Attributes = { [ key : string ] : string };
type Component = ( Attributes, any ) => any;

let React = {
	createElement: function( component : Component | string, attributes : Attributes | null, ...children ) : string {
		if( typeof component == "string" ) {
			let attr = "";
			if( attributes != null ) {
				for( const k in attributes ) {
					const key = k == "className" ? "class" : k;
					attr += ` ${key}="${attributes[k]}"`;
				}
			}
			return `<${component}${attr}>` + flatten( children ).join( "" ) + `</${component}>`;
		}
		else {
			return component( attributes, children );
		}
	}
};

Then write your JSX and build your code like tsc --jsx and run it to print your pages. Not sure it exactly matches React's behaviour since I don't use it, but it seems good enough.

Rant time

JSX is a big improvement over everything else but it's still not actually good. All HTML statements should be concatenated to some implicit return value so you can use normal language constructs everywhere:

function CountTo( props ) {
	for( let i = 0; i < props.n; i++ ) {
		<div>{i}</div>
	}
}

rather than having to jam everything into one statement:

function CountTo( props ) {
	return [ ...new Array( props.n ) ].map( ( _, i ) => <div>{i}</div> );
}

I think this also lets you delete custom components from the language since it seems to just be different syntax for calling a function.