Skip to content

Instantly share code, notes, and snippets.

@Jannis
Last active March 25, 2018 21:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Jannis/3eed40e5cc3e085d3e1f8fa20d716ded to your computer and use it in GitHub Desktop.
Save Jannis/3eed40e5cc3e085d3e1f8fa20d716ded to your computer and use it in GitHub Desktop.
[WIP] Groom: A React/GraphQL framework for ClojureScript

[WIP] Groom: A React/GraphQL framework for ClojureScript

Principles

  • React for components
  • Component definitions with co-located queries and mutations
  • GraphQL for client-side state management
  • GraphQL for server queries and mutations
  • Prefer data over code (i.e. Hiccup-style UI definitions)
  • Two-level API:
    • Low-level: Functions for creating components, mutations, queries
    • High-level: Macro-based DSL for creating components, mutations, queries
  • Server-side rendering (SSR)
  • React Native support out of the box
  • Encourage spec-driven development

Foundations

  • Sablono (for Hiccup-style UI composition)
  • Apollo (for everything GraphQL)

Elements

  • groom.graphql: ClojureScript bindings for everything Apollo and GraphQL
    • groom.graphql.apollo: ClojureScript bindings for Apollo
    • groom.graphql.graphql: ClojureScript bindings for GraphQL
  • groom.resolvers: Library for defining client-side query and mutation resolvers conveniently
  • groom.ui: Low-level library for defining and rendering components
  • groom.dsl: High-level macro-based DSL for defining components, queries and mutations
  • groom.specs.v1: Specs for whatever makes sense (TODO: Work this out in more detail)
    • :groom.specs.v1/queries for Groom's Clojure-style query definitions
    • :groom.specs.v1/mutations for Groom's Clojure-style mutation definitions

Examples

Setup

TODO

Low-Level API

Defining Components

(def starship
  (groom.ui/component
    {:queries '[(starship {?id ID!}
                  [:id
                   :name
                   :length
                   :isSelected +client])]
     :mutations '[(selectShip {?id ID!}
                    (selectShip {id ?id} +client [:id]))]
     :render (fn [{:keys [data selectShip]}]
               (if (:loading data)
                 [:div "Loading..."]
                 (let [starship (:starship data)]
                   [:div {:on-click selectShip
                          :style (when (:isSelected starship)
                                   {:background-color "orange"})}
                    (:name starship)])))}))

(def starwars-ships
  (groom.ui/component
   {:render (fn [props]
              [:ul
               [:li [starship {:id "3000"}]]
               [:li [starship {:id "3001"}]]
               [:li [starship {:id "3002"}]]])}))

Defining Client-Side Query Resolvers

TODO

Defining Client-Side Mutation Resolvers

TODO

High-Level API

Defining Components

(require '[groom.dsl :refer [defcomponent]])

(defcomponent starship
  (queries
    [(starship {?id ID!}
       [:id
        :name
        :length
        :isSelected +client])])
  (mutations
    [(selectShip {?id ID!}
       (selectShip {id ?id} +client [:id]))])
  (render
    (if loading?
      [:div "Loading..."]
      [:div {:on-click selectShip
             :style (when (:isSelected starship) {:background-color "orange"})}
       (:name starship)])))

(defcomponent starwars-ships
  (render
    [:ul
      [:li [starship {:id "3000"}]]
      [:li [starship {:id "3001"}]]
      [:li [starship {:id "3002"}]]]))

Spec-Driven Development

TODO

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment