62

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>
4
  • Did you try it and did it work? Commented May 25, 2015 at 4:09
  • @AliGajani dont work Commented May 25, 2015 at 4:36
  • As far as I know, you need React and JSX can't work standalone. I might be wrong. Commented May 25, 2015 at 4:37
  • 1
    but i only want to use jsx without react Commented May 25, 2015 at 4:43

8 Answers 8

33

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>
Sign up to request clarification or add additional context in comments.

5 Comments

How is it possible to compile my jsx? Or is there a way to compile it via js on runtime?
The Typscript compiler gives you the option to compile jsx (tsx) or pass it through to a transpiler such as babel.
This seems to prevent me from being able to run functions onClick, any ideas?
Here's a complete solution: github.com/nicojs/typed-html
31

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.

2 Comments

This is the correct answer and deserves all the upvotes.
You're correct about the transpilation part, but it doesn't have to be done externally. Although it's uncommon it's still possible to run babeljs right in the the browser
10

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")
)

9 Comments

thanks, but it need React.there is a single library like jsx to do this?
@SKing7 To do what? Your question doesn't make sense. JSX turns XML-looking syntax into JavaScript function calls. What do you actually want it to do?
The are separate virtual DOM libraries, like this one.
@SKing7 Does using strings work for you? return ("<div>test html code</div>"); If not, why not? Maybe that will help narrow down what you're trying to do.
@SKing7 If you're using an ES6 transpiler (such as the one that ships with the JSX Transformer), you can use template strings (with backticks) which support multiple lines. See this example: jsfiddle.net/BinaryMuse/hovssy49
|
6

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.

Comments

4

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>

Comments

4

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 => {
    // <a> was clicked
};

const el = (
    <div class="header">
        <a href="#" class="link" onClick={handleClick}>Download</a>
    </div>
);

document.body.appendChild(el);

Comments

1

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...

1 Comment

first link is dead and second link redirects to babeljs.io/setup, someone should edit in functional replacement links (i dont know them)
0

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.

4 Comments

you can only use react.js without jsx but not the other way around, jsx is just a syntax sugar for react.
thanks, is there a single library like jsx to do this?
do you mean jsx compiler? if you do then yes, react has a tools that can do the thing, npm install -g react-tools this will give you a jsx binary, you can get more information at facebook.github.io/react/downloads.html
@louisthebang i beg to differ. JSX is just syntastic sugar for hyperscript.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.