Differences from Reagent
Fundamentally UIx is different from Reagent in a way how it tries to be as close to React as possible. This way switching from JavaScript to ClojureScript becomes less of a painful process. You will end up in a somewhat familiar environment where everything you know about React is still applicable.
Functional React components by default
UIx components are compiled into functional React components (plain JS functions). It's still possible to create class-based components using uix.core/create-class
.
JSX-like static UI structure
Unlike in Reagent, React elements in UIx are created using $
macro which enforces static UI structure that is easy to reason about. While Hiccup is quite flexible, it also makes it easy to write highly dynamic code that composes vector elements at runtime which makes it harder to read and maintain.
Hooks
UIx exposes React hooks, unlike Reagent where it's common to use RAtoms as state primitives.
Syntax
There's only one way to create a component in UIx, using defui
hook. No form-1-2-3 components. With hooks you have all of the features that form-1-2-3 components provide.
Speed
UIx is generally 1.6x slower than plain React, mainly due to use of Clojure's data structures when passing data between components, while Reagent is 2.7x slower due to the same reasons and additionally because of runtime interpreted Hiccup, and a gluing layer that connects React components to RAtoms. Hooks-based Reagent components are even slower.
Here's comparison for the amount of work React, UIx and Reagent are doing when running a synthetic benchmark.
Components are not memoized by default
While it can be tempting to memoize every component because props are immutable maps, UIx does not memoize components by default. Often in React and UIx it's cheaper to re-run a component instead of comparing props map. Immutable data may still come at cost, where in the worst case data structures are fully traversed, essentially performing deep equals.
No custom scheduling mechanism
In UIx, UI update cycle is managed by React. Reagent is however using requestAnimationFrame
to enforce always asynchronous UI updates, which leads to issues when user input should be handled synchronously and thus requires additional layer in input fields to fix this problem.
Built-in linter
UIx has a built-in linter that works well thanks to non ambiguous and static UI structure enforced by $
macro.
SSR on JVM
UIx components can be rendered on JVM using serializer borrowed from Rum.
More
Learn more about differences and migration path from this slide deck.