Can I use jsx without React to inline HTML in script?

JavascriptReactjs

Javascript Problem Overview


Can I use inline HTML in a script as below by using a library like jsx:

<script src="jsx-transform.js"></script>
<script type="text/jsx">
define('component', function () {
   return (<div>test html code</div>);
});
</script>

Javascript Solutions


Solution 1 - Javascript

I was able to write JSX files and inject them into an HTML page using a 'fake' React file.

no-react.js

/**
 * Include this script in your HTML to use JSX compiled code without React.
 */

const React = {
    createElement: function (tag, attrs, children) {
        var element = document.createElement(tag);

        for (let name in attrs) {
            if (name && attrs.hasOwnProperty(name)) {
                let value = attrs[name];
                if (value === true) {
                    element.setAttribute(name, name);
                } else if (value !== false && value != null) {
                    element.setAttribute(name, value.toString());
                }
            }
        }
        for (let i = 2; i < arguments.length; i++) {
            let child = arguments[i];
            element.appendChild(
                child.nodeType == null ?
                    document.createTextNode(child.toString()) : child);
        }
        return element;
    }
};

Then compile your jsx.

test.jsx

const title = "Hello World";
document.getElementById('app').appendChild(
    <div>
        <h1>{title}</h1>
        <h2>This is a template written in TSX, then compiled to JSX by tsc (the Typescript compiler), and finally
            injected into a web page using a script</h2>
    </div>
);

Resulting compiled 'test.js'

var title = "Hello World";
document.querySelector('#app').appendChild(React.createElement("div", null,
    React.createElement("h1", null, title),
    React.createElement("h2", null, "This is a template written in TSX, then compiled to JSX by tsc (the Typescript compiler), and finally" + " " + "injected into a web page")));

And finally, the HTML page that includes both scripts.

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>no-react</title>
    <script src="no-react.js"></script>
</head>
<body>
<div id="app"></div>
</body>
</html>

<script src="test.js"></script>

Solution 2 - Javascript

React renders JSX html syntax to JS using functions such as React.createElement (among others for Fragments and so on). But that all boils down to the @babel/plugin-transform-react-jsx plugin which does the transpiling of this:

return(<div id="hello">Hello World</div>)

into this...

return React.createElement('div', {id: 'hello'}, 'Hello World');

However you can replace React.createElement with you're own function to do this. You can read more on that here: https://babeljs.io/docs/en/next/babel-plugin-transform-react-jsx.html

You should also look at libraries which do exactly this such as nervjs, jsx-render and deku. All of these use a JSX html syntax without react. Some (such as jsx-render) are only focused on converting JSX to the final JS, which might be what you're looking for.

The author of that package wrote an article on it here: https://itnext.io/lessons-learned-using-jsx-without-react-bbddb6c28561

Also Typescript can do this if you use that...but I've no first hand experience with it.

To sum up

You can do it without React, but not without Babel or Typescript.

Solution 3 - Javascript

JSX is not a string-based templating language; it compiles to actual JavaScript function calls. For example,

<div attr1="something" attr2="other">
  Here are some <span>children</span>
</div>

transpiles to

React.createElement("div", {attr1: "something", attr2: "other"}, 
  "Here are some ", React.createElement("span", null, "children")
)

Solution 4 - Javascript

I was looking for something like this myself. A way to write Components and JSX like for simple projects. Didn't find one that I liked so I've built this: https://github.com/SagiMedina/Aviya#aviya Have a look, maybe it will answer your problem as well.

Solution 5 - Javascript

You will need something to transform the JSX into JS function calls. React uses Babel to do this -- you would probably be best off with that too.

There's a library by the creators of Preact that essentially does what you're after called vhtml. The tagline is "Render JSX/Hyperscript to HTML strings, without VDOM".

Here is a copy of the Readme at time of writing:

Usage

// import the library:
import h from 'vhtml';

// tell babel to transpile JSX to h() calls:
/** @jsx h */

// now render JSX to an HTML string!
let items = ['one', 'two', 'three'];

document.body.innerHTML = (
  <div class="foo">
    <h1>Hi!</h1>
    <p>Here is a list of {items.length} items:</p>
    <ul>
      { items.map( item => (
        <li>{ item }</li>
      )) }
    </ul>
  </div>
);

New: "Sortof" Components!

vhtml intentionally does not transform JSX to a Virtual DOM, instead serializing it directly to HTML. However, it's still possible to make use of basic Pure Functional Components as a sort of "template partial".

When vhtml is given a Function as the JSX tag name, it will invoke that function and pass it { children, ...props }. This is the same signature as a Pure Functional Component in react/preact, except children is an Array of already-serialized HTML strings.

This actually means it's possible to build compositional template modifiers with these simple Components, or even higher-order components.

Here's a more complex version of the previous example that uses a component to encapsulate iteration items:

let items = ['one', 'two'];

const Item = ({ item, index, children }) => (
  <li id={index}>
    <h4>{item}</h4>
    {children}
  </li>
);

console.log(
  <div class="foo">
    <h1>Hi!</h1>
    <ul>
      { items.map( (item, index) => (
        <Item {...{ item, index }}>
          This is item {item}!
        </Item>
      )) }
    </ul>
  </div>
);

The above outputs the following HTML:

<div class="foo">
  <h1>Hi!</h1>
  <ul>
    <li id="0">
      <h4>one</h4>This is item one!
    </li>
    <li id="1">
      <h4>two</h4>This is item two!
    </li>
  </ul>
</div>

Solution 6 - Javascript

It looks like the dom-chef package can do this. From the readme:

> - No API, JSX gets auto transformed into actual DOM elements. > > ---- > > // babel.config.js >
> const plugins = [ > [ > '@babel/plugin-transform-react-jsx', > { > pragma: 'h', > pragmaFrag: 'DocumentFragment', > } > ] > ]; >
> // ... > > > ---- > > const {h} = require('dom-chef'); >
> const handleClick = e => { > // was clicked > }; >
> const el = ( >

> ); >
> document.body.appendChild(el);

Solution 7 - Javascript

You can have a look at documentation: in-browser JSX transform, and also see Babel documentation

You can achieve what you want, but it is discouraged in production...

Solution 8 - Javascript

Jsx parse the return (<div>test html code</div>); to something like this return React.createElement('div', {...});

then if you don't using react.js, then browser will not know what React is and trigger an error.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSKing7View Question on Stackoverflow
Solution 1 - JavascriptSteven SpunginView Answer on Stackoverflow
Solution 2 - JavascriptLuke WattsView Answer on Stackoverflow
Solution 3 - JavascriptMichelle TilleyView Answer on Stackoverflow
Solution 4 - JavascriptSagi MedinaView Answer on Stackoverflow
Solution 5 - JavascriptJulian SuggateView Answer on Stackoverflow
Solution 6 - JavascriptjtbandesView Answer on Stackoverflow
Solution 7 - JavascriptMike AskiView Answer on Stackoverflow
Solution 8 - JavascriptChengluView Answer on Stackoverflow