Convert Figma logo to code with AI

omcljs logoom

ClojureScript interface to Facebook's React

6,647
361
6,647
80

Top Related Projects

6,647

ClojureScript interface to Facebook's React

A ClojureScript framework for building user interfaces, leveraging React

Devcards aims to provide a visual REPL experience for ClojureScript

Quick Overview

Om is a library for building user interfaces with ClojureScript and React. It provides a powerful and flexible way to build complex, interactive web applications using the Clojure programming language.

Pros

  • Functional Programming Approach: Om embraces the functional programming paradigm, which can lead to more maintainable and testable code.
  • React Integration: Om is built on top of React, allowing developers to leverage the rich ecosystem and features of React.
  • Performance: Om's efficient diffing algorithm and optimized rendering can lead to high-performance user interfaces.
  • Immutable Data Structures: Om encourages the use of immutable data structures, which can simplify state management and improve overall application stability.

Cons

  • Steep Learning Curve: Clojure and the functional programming paradigm can have a steeper learning curve compared to more traditional web development approaches.
  • Limited Ecosystem: While Clojure and ClojureScript have a growing community, the ecosystem is smaller than that of more mainstream web development technologies.
  • Tooling Maturity: The tooling and development environment for Clojure and ClojureScript may not be as mature as those for other popular web development languages.
  • Interoperability Challenges: Integrating Om-based components with non-ClojureScript libraries or frameworks can sometimes be more challenging.

Code Examples

Here are a few code examples demonstrating the usage of Om:

  1. Rendering a Simple Component:
(require '[om.core :as om :include-macros true]
         '[om.dom :as dom :include-macros true])

(defn hello-component [data owner]
  (reify
    om/IRender
    (render [_]
      (dom/div nil "Hello, " (om/get-shared owner :name) "!"))))

(om/root
  hello-component
  {:name "World"}
  {:target (. js/document (getElementById "app"))
   :shared {:name "World"}})

This code defines a simple Om component that displays a "Hello, World!" message.

  1. Handling User Interactions:
(defn counter-component [data owner]
  (reify
    om/IInitState
    (init-state [_] {:count 0})

    om/IRenderState
    (render-state [_ state]
      (dom/div nil
        (dom/button
          #js {:onClick #(om/update-state! owner :count inc)}
          "Increment")
        (dom/span nil (str "Count: " (:count state)))))))

(om/root
  counter-component
  {}
  {:target (. js/document (getElementById "app"))})

This code creates a simple counter component that allows the user to increment a value.

  1. Communicating Between Components:
(defn parent-component [data owner]
  (reify
    om/IInitState
    (init-state [_] {:message ""})

    om/IRenderState
    (render-state [_ state]
      (dom/div nil
        (dom/input
          #js {:type "text"
               :value (:message state)
               :onChange #(om/set-state! owner :message (.. % -target -value))})
        (om/build child-component (:message state))))))

(defn child-component [data owner]
  (reify
    om/IRender
    (render [_]
      (dom/div nil "Received message: " data))))

(om/root
  parent-component
  {}
  {:target (. js/document (getElementById "app"))})

This code demonstrates how to communicate between a parent and child component in Om.

Getting Started

To get started with Om, you'll need to have Clojure and ClojureScript set up on your development environment. Here's a quick overview of the steps:

  1. Install Leiningen, a popular Clojure build tool.

  2. Create a new ClojureScript project using Leiningen:

    lein new app my-om-app
    
  3. Add Om as a dependency in your project.clj

Competitor Comparisons

6,647

ClojureScript interface to Facebook's React

Pros of Om

  • Simpler and more lightweight than Om Next
  • Provides a more straightforward approach to building React-like applications
  • Easier to learn and understand for beginners

Cons of Om

  • Lacks some of the advanced features and flexibility of Om Next
  • May not be suitable for larger, more complex applications
  • Potentially less scalable than Om Next

Code Comparison

Om

(defui Counter
  static om/IQuery
  (query [this] [:count])
  static om/IOmRecord
  (initial-state [_] {:count 0})
  Object
  (render [this]
    (let [{:keys [count]} (om/props this)]
      (dom/div nil
        (dom/button #js {:onClick #(om/update-state! this update :count inc)}
          "Increment")
        (dom/span nil (str "Count: " count))))))

(om/root
  Counter
  {:count 0}
  {:target (. js/document (getElementById "app"))})

Om Next

(defui Counter
  static om/IQuery
  (query [this] [:count])
  static om/IOmRecord
  (initial-state [_] {:count 0})
  Object
  (render [this]
    (let [{:keys [count]} (om/props this)]
      (dom/div nil
        (dom/button #js {:onClick #(om/transact! this `[(counter/increment {:count ~count})])}
          "Increment")
        (dom/span nil (str "Count: " count))))))

(def reconciler
  (om/reconciler
    {:state {:counter {:count 0}}
     :parser (om/parser {:read read-counter :mutate mutate-counter})}))

(om/add-root! reconciler Counter (. js/document (getElementById "app")))

The main difference between the two examples is the use of Om Next's reconciler and transaction-based approach, which provides more flexibility and scalability for larger applications.

A ClojureScript framework for building user interfaces, leveraging React

Pros of re-frame

  • Modular Design: re-frame encourages a modular and decoupled architecture, making it easier to manage and scale complex applications.
  • Reactive Programming: re-frame's event-driven approach and reactive programming model can lead to more responsive and efficient applications.
  • Comprehensive Documentation: re-frame has extensive documentation, providing clear guidance and best practices for building Clojure/ClojureScript applications.

Cons of re-frame

  • Steeper Learning Curve: re-frame's architectural patterns and concepts may have a steeper learning curve compared to Om's simpler approach.
  • Dependency on re-frame: re-frame is a core dependency for applications built with it, which can make it more difficult to migrate to other libraries or frameworks in the future.
  • Verbosity: re-frame's event-driven architecture can sometimes lead to more boilerplate code compared to Om's more straightforward approach.

Code Comparison

Here's a brief comparison of a simple component in Om and re-frame:

Om:

(defui SimpleComponent
  static om/IQuery
  (query [this] [:text])
  Object
  (render [this]
    (let [{:keys [text]} (om/props this)]
      (dom/div nil text))))

(def simple-component (om/factory SimpleComponent))

re-frame:

(defn simple-component []
  [:div (get @(re-frame/subscribe [:text]) 0)])

(re-frame/reg-sub
 :text
 (fn [db _]
   (:text db)))

In the Om example, the component is defined using the defui macro and the om/IQuery protocol is used to specify the data dependencies. In the re-frame example, the component is a simple function that subscribes to the :text subscription, which is defined separately.

Devcards aims to provide a visual REPL experience for ClojureScript

Pros of Devcards

  • Devcards provides a powerful live development environment, allowing developers to quickly iterate and test their components in isolation.
  • The library offers a rich set of features, including support for hot-reloading, interactive documentation, and visual regression testing.
  • Devcards integrates well with other ClojureScript libraries, making it a versatile tool for building complex web applications.

Cons of Devcards

  • Devcards has a steeper learning curve compared to Om, as it introduces additional concepts and configuration requirements.
  • The library may be overkill for smaller projects or simple use cases, where the overhead of setting up Devcards may outweigh the benefits.
  • Devcards is primarily focused on the development workflow and may not provide the same level of production-ready features as Om.

Code Comparison

Om:

(defui Counter
  static om/IQuery
  (query [this] [:count])
  static om/IOmRecord
  (initial-state [this] {:count 0})
  Object
  (render [this]
    (let [{:keys [count]} (om/props this)]
      (dom/div nil
        (dom/button #js {:onClick #(om/update-state! this update-in [:count] inc)}
          "Increment")
        (dom/span nil (str "Count: " count))))))

(def counter (om/factory Counter))

Devcards:

(defcard-rg counter
  (fn [data _]
    (r/create-class
     {:reagent-render
      (fn []
        [:div
         [:button {:on-click #(swap! data update :count inc)}
          "Increment"]
         [:span "Count: " (:count @data)]])}))
  {:count 0})

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

Om

NOTE: This project is no longer under active development. If you'd like to use a library that's well maintained that was inspired by some of the ideas presented here see Fulcro

A ClojureScript UI framework and client/server architecture over Facebook's React.

Om UIs are out of the box snapshotable and undoable and these operations have no implementation complexity and little overhead.

Om borrows ideas liberally from Facebook's Relay and Netflix's Falcor with a dash of inspiration from Datomic pull syntax to avoid the typical incidental complexity that arises from client/server state management.

Dependency Information

Latest release: 1.0.0-beta1

Leiningen and Boot dependency information:

[org.omcljs/om "1.0.0-beta1"]

Maven dependency information:

<dependency>
  <groupId>org.omcljs</groupId>
  <artifactId>om</artifactId>
  <version>1.0.0-beta1</version>
</dependency>

Example

(ns example
  (:require [goog.dom :as gdom]
            [om.dom :as dom]
            [om.next :as om :refer [defui]]))

(defui Hello
  Object
  (render [this]
    (dom/h1 nil "Hello, world!")))

(def hello (om/factory Hello))

(.render js/ReactDOM (hello) (gdom/getElement "example"))

Tutorials

There is an Quick Start tutorial that will introduce you to the core concepts of Om here. There are also a variety of other guides here.

Documentation

There is documentation here

Contributing

Please contact me via email to request an electronic Contributor Agreement. Once your electronic CA has been signed and returned to me I will accept pull requests.

Community

If you are looking for help please get in touch either on the clojurians.slack.com #om channel or the om-cljs Google Group.

References

Copyright and license

Copyright © 2013-2017 David Nolen

Licensed under the EPL (see the file epl.html).

NPM DownloadsLast 30 Days