GithubHelp home page GithubHelp logo

scrum's Introduction

scrum logo

State Coordination for Rum

Table of Contents

Motivation

Have a simple, re-frame like state management facilities to build web apps with Rum library while leveraging its API.

Features

  • Decoupled application state in a single atom
  • Reactive queries
  • A notion of controller to keep application domains separate

Installation

Add to project.clj: [org.roman01la/scrum "0.1.0-SNAPSHOT"]

How it works

With Scrum you build everything around a well known architecture pattern in modern SPA development:

DISPATCH EVENT

HANDLE EVENT

QUERY STATE

RENDER

Dispatcher

Dispatcher communicates intention to perform an action, whether it is state update or a network request.

(scrum.dispatcher/dispatch! :controller-name :action-name &args)

Controllers

Controller is a multimethod which performs intended actions against application state. A controller usually have at least an initial state and :init method.

(def initial-state 0)

(defmulti control (fn [action] action))

(defmethod control :init [action &args db]
  (assoc db :counter initial-state))

(scrum.dispatcher/register! :counter control)

Subscriptions

A subscription is a reactive query into application state. It is basically an atom which holds a part of the state value. Optional second argument is an aggregate function which computes a materialized view. You can also do parameterized and aggregate subscriptions.

Actual subscription happens in Rum component via rum/reactive mixin and rum/react function which hooks in a watch function to update a component when an atom gets an update.

;; normal subscription
(def fname (scrum.core/subscription [:users 0 :fname]))

;; a subscription with aggregate function
(def full-name (scrum.core/subscription [:users 0] #(str (:fname %) " " (:lname %))))

;; parameterized subscription
(defn user [id]
  (scrum.core/subscription [:users id]))

;; aggregate subscription
(def discount (scrum.core/subscription [:user :discount]))
(def goods (scrum.core/subscription [:goods :selected]))

(def shopping-cart
  (rum/derived-atom [discount goods] ::key
    (fn [discount goods]
      (let [price (->> goods (map :price) (reduce +))]
        (- price (* discount (/ price 100)))))))

;; usage
(rum/defc NameField < rum/reactive []
  (let [user (rum/react (user 0))])
    [:div
     [:div.fname (rum/react fname)]
     [:div.lname (:lname user)]
     [:div.full-name (rum/react full-name)]
     [:div (str "Total: " (rum/react shopping-cart))]])

Usage

(ns counter.core
  (:require [rum.core :as rum]
            [scrum.dispatcher :as d]
            [scrum.core :refer [subscription]]))

;;
;; define controller & event handlers
;;

(def initial-state 0)

(defmulti control (fn [action] action))

(defmethod control :init [_ _ db]
  (assoc db :counter initial-state))

(defmethod control :inc [_ _ db]
  (update db :counter inc))

(defmethod control :dec [_ _ db]
  (update db :counter dec))


;;
;; define subscription
;;

(def counter (subscription [:counter]))


;;
;; define UI component
;;

;; create dispatcher for particular controller
(def dispatch-counter! (partial d/dispatch! :counter))

(rum/defc Counter < rum/reactive []
  [:div
   [:button {:on-click #(dispatch-counter! :dec)} "-"]
   [:span (rum/react counter)]
   [:button {:on-click #(dispatch-counter! :inc)} "+"]])


;;
;; start up
;;

;; register controller
(d/register! :counter control)

;; initialize registered controllers
(defonce dispatched-init (d/broadcast! :init))

;; render
(rum/mount (Counter)
           (. js/document (getElementById "app")))

Libraries

Routing

Check out scrum.router, a minimal routing library for Scrum.

Roadmap

  • Get rid of global state
  • Storage agnostic architecture? (Atom, DataScript, etc.)
  • Better effects handling (network, localStorage, etc.)

License

Copyright © 2017 Roman Liutikov

Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.