React Native component DSL for Clojurescript
rehook is my Clojurescript library for state management in React apps.
It is a simple, 35LOC library that provides a reagent like interface for modern Cljs/React apps.
You do not need to use rehook-rn-component
with rehook
, but the two obviously pair great!
rehook-rn-component
is designed to be:
The library is only 50LOC. It makes Clojurescript development with React Native a joy!
defui
is a macro used to define rehook
components. This macro is simply syntactic sugar, all rehook
components are cljs fns.
defui
takes in three arguments:
context
: immutable, application contextprops
: any props passed to the component. This will be an untouched JS object.$
: the render fn(defui my-component [{:keys [dispatch]} _ $]
($ :Text {:onClick #(dispatch :fire-missles)} "Hello world"))
The $
render fn provides Hiccup-like syntax for expressing the DOM tree.
Its signature looks like this:
[component args? & children]
It supports lookup to components in a few ways:
:KeyboardAvoidingView
register-component
multimethodrehook
components can be referred to directly(ns example.components
(:require
[rehook.dom :as dom :refer-macros [defui]]
["imported-react-component" :refer [ImportedReactComponent]]))
(dom/register-component :ImportedReactComponent [_]
ImportedReactComponent)
(defui button [{:keys [dispatch]} _ $]
($ :Button {:title "Fire missles" :onClick #(dispatch :fire-missles)}))
(defui app [_ $]
($ :View {:style #js {:flex 1}}
($ button)
($ :ImportedReactComponent)))
Note how the $
render fn hides having to pass the context
map to its children through clever partial function application!
$
are always covnerted to JS maps via clj->js
. This fn isn't recursive, so remeber to use the #js
literal on any nested maps!rehook
does no special transformation to the keys in your props, so use onPress
over on-press
etc.You can use the component-provider
fn if you directly call AppRegistry
(ns example.core
(:require
[example.components :refer [app]]
[rehook.dom :as dom]
["react-native" :refer [AppRegistry]]))
(defn system []
{:dispatch (fn [& _] (js/console.log "TODO: implement dispatch fn..."))})
(defn main []
(.registerComponent AppRegistry "my-app" (dom/component-provider (system) app))
Alternatively if you don't have access to the AppRegistry
, you can use the boostrap
fn instead - which will return a valid React element
component-provider
optionally takes in a context fn, which is a fn applied each time the ctx map is passed to a child.
This can be incredibly useful for instrumentation.
For example:
(defn ctx-transformer [ctx component]
(update ctx :log-ctx #(conj (or % []) (dom/component-name component))))
(dom/component-provider (system) ctx-transformer app)
rehook
promotes building applications with no singleton global state.
Therefore, you can treat your components as 'pure functions', as all inputs to the component are passed in as arguments.
Testing (with React hooks) is a deeper topic that I will explore via a blog post in the coming months. Please check back!
Can you improve this documentation?Edit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close