All Projects → ptaoussanis → tengen

ptaoussanis / tengen

Licence: EPL-1.0 license
Simple let-based Reagent component fns for Clojure/Script

Programming Languages

clojure
4091 projects

Projects that are alternatives of or similar to tengen

tailwind-hiccup
tailwindcss + hiccup = 👍👍
Stars: ✭ 34 (-32%)
Mutual labels:  reagent, rum
Sente
Realtime web comms for Clojure/Script
Stars: ✭ 1,626 (+3152%)
Mutual labels:  epl, taoensso
re-frame-semantic-ui-react-github-widget
Using semantic-ui-react with re-frame - sample project
Stars: ✭ 21 (-58%)
Mutual labels:  reagent
reagent-shadow-cljs-starter
A minimal starter pack for Reagent-based projects
Stars: ✭ 29 (-42%)
Mutual labels:  reagent
compound
A micro structure for reframe data
Stars: ✭ 116 (+132%)
Mutual labels:  reagent
re-frame-realword-example-app
Exemplary real world application built with Clojurescript and re-frame
Stars: ✭ 16 (-68%)
Mutual labels:  reagent
ornament
Clojure Styled Components
Stars: ✭ 92 (+84%)
Mutual labels:  reagent
reagent-quill
Basic reagent recipe for quill rich text editor
Stars: ✭ 16 (-68%)
Mutual labels:  reagent
entitydb
EntityDB library
Stars: ✭ 19 (-62%)
Mutual labels:  reagent
rn-shadow-steroid
React Native with shadow-cljs on steroids
Stars: ✭ 57 (+14%)
Mutual labels:  reagent
quinto
a board game lost to the sands of time
Stars: ✭ 27 (-46%)
Mutual labels:  reagent
goldly
dynamic web dashboards with clojure
Stars: ✭ 21 (-58%)
Mutual labels:  reagent
roll
RPG dice roller with both Rust CLI and ClojureScript Web interfaces
Stars: ✭ 14 (-72%)
Mutual labels:  reagent
threeagent
ClojureScript library for building Three.js apps in a reagent-like fashion
Stars: ✭ 124 (+148%)
Mutual labels:  reagent
learn-re-frame-course-files
🎦 Learn re-frame course files for building Cheffy app
Stars: ✭ 51 (+2%)
Mutual labels:  reagent
ember-appmetrics
Ember library used to measure various metrics in your Ember app with ultra simple APIs.
Stars: ✭ 16 (-68%)
Mutual labels:  rum
baking-soda
baking-soda is an interface between clojurescript's reagent and reactstrap (i.e., bootstrap 4 react components) and react-bootstrap (i.e., bootstrap 3 react components)
Stars: ✭ 74 (+48%)
Mutual labels:  reagent
breaking-point
BREAKING-POINT lets you quickly define and subscribe to screen (i.e. window) breakpoints in your re-frame application
Stars: ✭ 36 (-28%)
Mutual labels:  reagent
shadow-firebase
shadow-cljs and firebase using google auth and persisting state to realtime database
Stars: ✭ 26 (-48%)
Mutual labels:  reagent
re-pressed
re-pressed is a clojurescript library that handles keyboard events for re-frame applications.
Stars: ✭ 150 (+200%)
Mutual labels:  reagent
Taoensso open-source

CHANGELOG | API | current Break Version:

[com.taoensso/tengen "1.1.0"] ; See CHANGELOG for details

See here if you're interested in helping support my open-source work, thanks! - Peter Taoussanis

Tengen: let-based Reagent components for Clojure/Script

Ten-gen (天元) is a Japanese Go term for the central, and only unique point on the Go board.

Reactjs has its pros and cons. Overall, it can be a good fit for web/native application development with Clojure/Script.

But while React's lifecycle methods are flexible, using them correctly can be a little unintuitive.

One of the sharper edges I've found in practice, is the difficulty of managing simple state flow through the component lifecycle process. This can actually be harder to do in Clojure/Script than vanilla JS since Clojure intentionally discourages the kind of disposable mutable state that could be handy here.

Net result: one sees a lot of weird contortions using atoms and core.async channels just to get the basic kind of data flow that you'll routinely need in a real application.

As an alternative: Tengen gives you a small, simple, lightweight component constructor that uses the unique capabilities of Lisp macros to get this:

(def-cmptfn my-example-component
  "Optional docstring"
  [first-name last-name] ; Args given to component (will rerender on changes)

  :let-mount ; Optional bindings established on each mount, available downstream
  [norm-fn (fn [s] (str/upper-case (str s)))
   _ (do ) ; Any side-effects on mount (fetch data from server, etc.)
   ]

  :let-render ; Optional bindings established on each render, available downstream
  [norm-first-name (norm-fm first-name)
   norm-last-name  (norm-fn last-name)

   ;;; We also have access to two magic symbols:
   currently-mounting? this-mounting? ; Magic `this-mounting?` binding
   current-cmpt        this-cmpt      ; Magic `this-cmpt` binding
  ]

  :render ; Have all above bindings
  [:div "Full name is: "
   (str norm-first-name " " norm-last-name)]

  :post-render (do) ; Optional: modify state atoms, etc. Have all above bindings.
  :unmount     (do) ; Optional: any cleanup jobs, etc.   Have all above bindings.
  )

That is:

  • :let-mount and :let-render bindings automatically flow down through all later lifecycle stages.
  • Magic this-mounting? and this-cmpt bindings are automatically available through all lifecycle stages.

These two small features can help cut out a lot of unnecessary complexity when writing real applications. In particular, you'll almost never need to touch or even be aware of the underlying React lifecycle methods.

Quickstart

Add the necessary dependency to your project:

Leiningen: [com.taoensso/tengen "1.1.0"] ; or
deps.edn:   com.taoensso/tengen {:mvn/version "1.1.0"}

And setup your namespace imports:

(ns my-cljs-ns
  (:require [taoensso.tengen.reagent :as tengen :refer-macros [cmptfn def-cmptfn]]))

And you're good to go, you've already seen the entire API!

Check the cmptfn, def-cmptfn docstrings for more info.

FAQ

Why only Reagent support?

Just the most familiar with Reagent, so started there. Haven't had time yet to look at extending to other libs, but should be trivial if there's demand (please ping to let me know).

I'll note that Rum's design in particular looks quite pleasant.

How's the performance?

Tengen doesn't add any detectable overhead to your components, it's just a lightweight macro wrapper to Reagent's usual constructor.

How does this affect my reactive atoms, etc.?

It doesn't, you can continue to use whatever higher-level state management strategies you prefer.

How to access DOM nodes?

As usual for Reagent, use ref callbacks:

(def-cmptfn my-example-component [arg1 arg2]
  [:div
   {:ref
    (fn [node]
      (when node
        ;; node is mounted in DOM
        ))}])

You can also use (reagent.core/dom-node this-cmpt), etc. - but would strongly recommend preferring ref callbacks in general since they're a lot more reliable and React's findDOMNode method is expected to become deprecated soon.

Contacting me / contributions

Please use the project's GitHub issues page for all questions, ideas, etc. Pull requests welcome. See the project's GitHub contributors page for a list of contributors.

Otherwise, you can reach me at Taoensso.com. Happy hacking!

- Peter Taoussanis

License

Distributed under the EPL v1.0 (same as Clojure).
Copyright © 2016-2020 Peter Taoussanis.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].