
JSnoX
Enjoy React.js, but not a fan of the JSX?
JSnoX gives you a concise, expressive way to build ReactElement trees in pure JavaScript.
Works with
- React.js v0.12 and above
- React Native
Example
var React = require('react')
var MyOtherComponent = require('./some/path.js')
var d = require('jsnox')(React)
var LoginForm = React.createClass({
submitLogin: function() { ... },
render: function() {
return d('form[method=POST]', { onSubmit: this.submitLogin },
d('h1.form-header', 'Login'),
d('input:email[name=email]'),
d('input:password[name=pass]'),
d(MyOtherComponent, { myProp: 'foo' }),
d('button:submit', 'Login')
)
}
})
API
var React = require('react')
var ReactDOM = require('react-dom')
var d = require('jsnox')(React)
var myDom = d('div.foo', {}, 'hello')
ReactDOM.render(myDom, myElement)
JSnoX's specStrings let you specify your components' HTML in a way resembling
CSS selectors:

Each property referenced in the string is passed along in the props argument to
React.createElement()
. You can pass along additional props in the second argument
(a JavaScript object). jsnox will merge the className attribute from both arguments
automatically, useful if the element has a mix of static and dynamic classes.
Bonus features
- append a
^
to your specString to have a key
prop automatically generated
from the spec string. This can help when you have dynamic
children
where they all have unique specStrings, eg:
render() {
return d('ul',
categories.map(cat => d(`li.category.${cat.id}^`, cat.title))
)
}
- you can add '@foo' to a specString to point
a ref named foo
to that element:
return d('input:email@emailAddr')
var email = this.refs.emailAddr.value
- You can pass a special
$renderIf
prop to your components or DOM elements.
If it evaluates to false, the element won't be rendered:
return d('div.debugOutput', { $renderIf: DEV_MODE }, 'hi')
Install
npm install jsnox
Npm is the recommended way to install. You can also include jsnox.js
in your
project directly and it will fall back to exporting a global variable as
window.jsnox
.
Why this instead of JSX?
- No weird XML dialect in the middle of your JavaScript
- All your existing tooling (linter, minifier, editor, etc) works as it does
with regular JavaScript
- No forced build step
Why this instead of plain JS with React.DOM
?
- More concise code; specify classes/ids/attributes in a way similar to CSS selectors
- Use your custom ReactComponent instances on React 0.12+ without needing
to wrap them
with
React.createFactory()
everywhere
Notes/gotchas
-
Your top-level component should also be wrapped by the jsnox client, to
prevent warnings about createFactory
. For example:
var d = require('jsnox')(React)
React.render(d(MyTopLevelComponent, { prop1: 'foo'}), document.body)
React.render(MyTopLevelComponent({ prop1: 'foo'}), document.body)
-
All attributes you specify should be the ones that React understands. So, for
example, you want to type 'input[readOnly]'
(camel-cased), instead of
'readonly'
like you'd be used to with html.
-
JSnoX gives you a saner default type
for button
elements– unless you specify
'button:submit'
their type will be "button"
(unintentionally form-submitting
buttons is a personal pet peeve).
See also