It's better than cjsx.
Build React element trees by composing functions.
You get full javascript control flow, and minimal boilerplate.
It's also quite simple, just a thin wrapper around React.createElement like JSX, making it fast and lightweight (2KB gzipped).
{crel} = require 'teact'
crel 'div', '#root.container', ->
unless props.signedIn
crel 'button', onClick: handleOnClick, 'Sign In'
crel.text 'Welcome!'
Transforms into:
React.createElement('div',
{id: root, className: 'container'}, [
(props.signedIn ? React.createElement('button',
{onClick: handleOnClick}, 'Sign In'
) : null)
'Welcome!'
]
)
Use it from your component's render method:
{Component} = require 'react'
{crel} = require 'teact'
class Widget extends Component
render: ->
crel 'div', className: 'foo', =>
crel 'div', 'bar'
Or in a stateless component:
module.exports = (props) ->
crel 'div', className: 'foo', ->
crel 'div', props.bar
crel
is just a thin wrapper around React.createElement,
so you can pass it components instead of crel names:
class DooDad extends Component
render: ->
crel 'div', className: 'doodad', =>
crel 'span', @props.children
class Widget extends Component
handleFiddle: =>
# ...
render: ->
crel 'div', className: 'foo', =>
crel DooDad, onFiddled: @handleFiddle, =>
crel 'div', "I'm passed to DooDad.props.children"
If you need to build up a tree of elements inside a component's render method, you can
escape the element stack via the pureComponent
helper:
{crel, pureComponent} = require 'teact'
Teas = pureComponent (teas) ->
teas.map (tea) ->
# Without pureComponent, this would add teas to the element tree
# in iteration order. With pureComponent, we just return the reversed list
# of divs without adding the element tree. The caller may choose to add
# the returned list.
crel 'div', tea
.reverse()
class Widget extends Component
render: ->
crel 'div', Teas(@props.teas)
Teact exports bound functions for elements, giving you options for terser syntax if you're into that:
T = require 'teact'
T.div className: 'foo', ->
T.text 'Blah!'
or the Teacup / CoffeeCup signatures:
{div, text} = require 'teact'
div '.foo', ->
text 'Blah!'
A super-basic performance test suggests that teact has no discernible impact on React rendering performance:
$ npm run benchmark
> native x 5,197 ops/sec ±3.30% (76 runs sampled)
> teact x 5,339 ops/sec ±2.23% (82 runs sampled)
> Fastest is teact,native
It's also lightweight, at 5KB minified, 2KB gzipped.
No extraneous enclosing tags required:
renderHeader: ->
unless @props.signedIn
crel 'a', href: '...', 'Sign in'
crel 'h1', 'Tea Shop'
Just works.
Other folks have reached similar conclusions. They were later bit by using the React API directly when the implementation changed. A thin wrapper like Teact should minimize this risk.
Markaby begat CoffeeKup begat CoffeeCup and DryKup which begat Teacup which begat Teact.
$ git clone https://github.com/hurrymaplad/teact && cd teact
$ npm install
$ npm test