jsx
An EXPERIMENTAL JSX runtime for describing dynamic DOM UIs with Reatom.
Core benefits
#- No extra build step needed; we use plain TSX (JSX), which is currently supported in various tools.
- Nice integrations with the platform;
<div />
returns the real element. - Rerender-less architecture with direct reactive bindings, which means extreme performance!
- Only 1kb runtime script (excluding the tiny core package).
- Built-in CSS management with a simple API and efficient CSS variables usage.
Installation
#You can use @reatom/core
instead of the framework, but we highly recommend using the framework to access the maximum features of Reatom.
tsconfig.json
:
vite.config.js
:
Using with different framework.
#You can use different JSX pragmas in different files. For example, if you have a React project and want to speedup some of you components, you can write them with reatom/jsx with a couple of simple steps:
- create a separate package for you Reatom components
- insert
tsconfig.json
as described above, you can use extends property, to use your project configurations - in every
*.tsx
file use the following code:
Example
#Advanced example with dynamic entities you can find here: https://github.com/artalar/reatom/tree/v3/examples/reatom-jsx
Define a component:
Render it:
You can create ctx
manually and use it to create a scoped render instance with reatomJsx
.
Reference
#This library implements a common TypeScript JSX factory that creates and configures native DOM elements.
By default, props passed to the JSX factory are set as properties. Add attr:
prefix to the name to set element attribute instead of property.
For all kinds of properties you can pass a primitive value or an atom with a primitive value.
The children
prop specifies the inner content of an element, which can be one of the following:
false
/null
/undefined
to render nothing- a string or a number to create a text node
- a native DOM node to insert it as-is
- an atom or a function returning any option listed above
Handling events
#Use on:*
props to add event handlers. Passed functions are automatically bound to a relevant Ctx
value: on:input={(ctx, event) => setValue(ctx, event.currentTarget.value)}
.
Models
#For simple AtomMut
bindings to the native input you can use model:value
syntax, where “value” could be: value
, valueAsNumber
, checked
.
By the way, you can safely create any needed resources inside a component body, as it calls only once when it created.
Styles
#Object-valued style
prop applies styles granularly: style={{top: 0, display: equalsFalseForNow && 'none'}}
sets top: 0;
.
false
, null
and undefined
style values remove the property. Non-string style values are stringified (we don’t add px
to numeric values automatically).
Incorrect:
Correct:
Class name utility
#The cn
function is designed for creating a string of CSS classes. It allows the use of multiple data types: strings, objects, arrays, functions, and atoms, which are converted into a class string.
The cn
function supports various complex data combinations, making it easier to declaratively describe classes for complex UI components.
CSS-in-JS
#We have a minimal, intuitive, and efficient styling engine tightly integrated with components. You can set a styles in css
prop and all relative css-variables to css:variable-name
prop.
The example below is correctly formatted by Prettier and has syntax highlighting provided by the ‘vscode-styled-components’ extension
Under the hood, it will create a unique class name and will be converted to this code:
Components
#Components in @reatom/jsx
are just functions returning JSX elements. They neither have state nor any lifecycle associated with them. Because component instantiation boils down into function calls, features like $spread
are not supported in them.
You can put an atom with a list of other elements as a children of an element to archive rendering of a dynamic list. But be note that you can’t put a as children a few atoms with a list and other elements, as the fragment is not supported to replace itself.
You should know that when you create a component which uses some atoms, it creates a subscription to those atoms immediately. The subscription will disposed only after you will put the elements to the
mount
ed node and if it will be unused after some condition rendering. Do not put the same elements as a children to other elements a few times! Recreate them with a component instead.
Spreads
#In Reatom, there is no concept of “rerender” like React. Instead, we have a special $spread
prop that can be used to spread props reactively.
SVG
#To create elements with names within the SVG namespace, you should prepend svg:
to the tag name:
If you need to use SVG as a string, you can choose from these options:
Option 1:
Option 2:
Ref
#The ref
property is used to create and track references to DOM elements, allowing actions to be performed when these elements are mounted and unmounted.
Mounting and unmounting functions are called in order from child to parent.
When this code is executed, the console will display the following result:
TypeScript
#To type your custom component props accepting general HTML attributes, for example for a div
element, you should extend JSX.HTMLAttributes
. However, if you want to define props for a specific HTML element you should use it name in the type name, like in the code below.
To type an event handler you have a few options, see below.
Limitations
#These limitations will be fixed in the feature
- No DOM-less SSR (requires a DOM API implementation like
linkedom
to be provided) - No keyed lists support
- A component should have no more than one root element. If this interferes with the layout, you can wrap the parent elements in another element with the style
display: "contents"
: