No-JSX
A customizable and declarative interface for creating React and React Native components without JSX syntax.
If you love React but don't quite like the embeded HTML tags this library may be what you are looking for.
const myView () =>
div('.App')(
div('.App-header')(
img('.App-logo')({src: logo, alt:'logo'}),
h2('Welcome to NJSX')
)
)()
Installation
NJSX is available as the njsx
package on npm. Just run the following line in your project root:
npm install njsx --save
Usage
NJSX provides a series of builder functions to cleanly instantiate React or React Native components. Just import the components you need from right module and you are ready to go.
import {div, p} from 'njsx/react'
import {View, Text} from 'njsx/react-native'
Building Components
Each imported NJSX builder is a function that once applied with no arguments will yield a React Component.
import {div} from 'njsx/react'
const someDiv = <div></div>
const anEqualDiv = div()
If the builders are applied with one or more arguments, these will be used to configure the generated components. Each builder can be applied any number of times (up until you apply it with no arguments to construct the component).
import {p} from 'njsx/react'
p('some text')()
p('some', ' ', 'text')()
p('some ')('text')()
p(['some', ' '],['text'])()
<p>some text</p>
Each argument is process by a set of configurable rules to decide what change it represents for the component. Here are some examples of argument applications you can use right out of the box:
-
Hashes will become component's properties.
img({src: somePath, onClick: someCallback})
Applying a builder with a second hash will result in the new properties merging with the old, keeping the later in case of repetition.
img({src: thisWillBeLost, onClick: thisWillRemain})({src: thisWillOverrideThePreviousPath})
-
Strings, Numbers, Booleans, React Components and even other NJSX Builders will become childrens.
div(
div('the answer is ', 42)
)()
Notice that, since builders can be children too, most of the time there is no need to apply them with no args to create components.
-
Strings starting with a dot will be interpreted as a classes.
div('.thisIsAClass .thisIsAnotherClass')(
'Some content'
)
-
Null and Undefined arguments are ignored.
Any unsuported argument application will raise a TypeError
.
Advanced Customization
You don't like the way arguments are being handled? No problem! You can customize the rules NJSX uses for interpreting arguments to fine tune it to your needs. Add or remove supported argument applications, change the way they are processed or throw all away and start from scratch!
import njsx from 'njsx/njsx'
import Rules from 'njsx/rules'
Each rule is just an array with two functions. The first one tells if the rule can handle an argument, the other one extracts any property or child from it.
Rules.STRING_AS_CHILD = [
arg => typeof arg === 'string',
arg => [ {}, [arg] ]
]
So you could easily create, for example, a rule that can handle anything that defines a toString()
function and adds its result as a child.
const strigableAsChild = [
arg => arg.toString && typeof(arg.toString) === 'function',
arg => [ {}, [arg.toString()] ]
]
njsx.rules.push(stringableAsChild)
Take into account that only one rule will be applied to each argument, and each rule will be tried in same order as it appears in the njsx.rules
array, so be carefull to leave the more generic rules at the bottom.
Contributions
Please report any bugs, requests or ideas on the issues section and we will try to see to it as soon as possible.
Also, pull requests are always welcome! Just try to keep it small and clean.
License
This code is open source software licensed under the ISC License by The Uqbar Foundation. Feel free to use it accordingly.