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.
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
.
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.
UIx exposes React hooks, unlike Reagent where it's common to use RAtoms as state primitives.
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.
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.
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.
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.
UIx has a built-in linter that works well thanks to non ambiguous and static UI structure enforced by $
macro.
UIx components can be rendered on JVM using serializer borrowed from Rum.
Learn more about differences and migration path from this slide deck.