State

Local state is represented as Atom-like data type wrapping React's state hook.

(defn form []
  (let [value (uix.core/state "")]
    [:input {:value @value
             :on-change #(reset! value (.. % -target -value))}]))

state takes initial value and schedules component's update every time it is updated with either reset! or swap!.

When initial value has to be computed before it’s used, it is recommended to pass it in a callback to state. The callback will be executed only once, in component’s initialization stage.

(defn calculate-initial-value []
  ;; expensive computation here)

(uix.core/state calculate-initial-value)

Initializing and interacting with local state is only possible from within UIx components. But that doesn't mean that state cannot be declared in a separate function that gets called from a component.

Reusable state

Because state is not directly coupled with components it is possible to build reusable behaviors on top of it. In the example below we create use-validation function that encapsulates logic that keeps track of a value and applies updates when the value satisfies provided validation function.

(defn use-validation [initial-value valid?]
  (let [value (uix.core/state initial-value)]
        on-change #(let [v (.. % -target -value)]
                    (when (valid? v)
                      (reset! value v)))]
    [@value on-change]))

(defn form []
  (let [[value on-change] (use-validation "" #(not (empty? %)))]
    [:input {:value value
             :on-change on-change}]))

Last updated