### Install and Run Project Source: https://github.com/reagent-project/reagent/blob/master/examples/react-mde/README.md Commands to install dependencies and start the development server. ```sh npm install npm run dev ``` -------------------------------- ### Install Karma CLI Source: https://github.com/reagent-project/reagent/blob/master/doc/development.md Install the Karma command-line interface globally to manage browser testing. ```bash npm install -g karma-cli ``` -------------------------------- ### Install React with npm Source: https://github.com/reagent-project/reagent/blob/master/README.md When using tools like Shadow-cljs, install React and react-dom using npm. It is generally safe to use the latest minor or patch versions of React. ```bash npm i react@19.2.3 react-dom@19.2.3 ``` -------------------------------- ### Use reagent.dom.client API for Rendering Source: https://github.com/reagent-project/reagent/blob/master/doc/2.0-upgrade.md Replace `reagent.dom/render` with the new `reagent.dom.client` API calls. This example shows how to create a root and render a Reagent component. ```clojure (ns example.core (:require [reagent.dom.client :as rdomc])) (defn view [] [:div "Hello world"]) (defonce root (rdomc/create-root (.getElementById js/document "app"))) (defn ^:export run [] (rdomc/render root [view])) ``` -------------------------------- ### Reagent Ratom Input Example Source: https://github.com/reagent-project/reagent/blob/master/doc/WhenDoComponentsUpdate.md Demonstrates a component that takes a ratom as input. Reagent watches this ratom and re-renders the component when its value changes. ```clojure (def name (reagent.ratom/atom "Bear")) (defn ask-for-forgiveness [] ;; <--- no props [:div "Please " @name " with me"]) ``` -------------------------------- ### JSX Example Source: https://github.com/reagent-project/reagent/blob/master/doc/Security.md A basic example of rendering a title from a response object using JSX. ```jsx

{response.title}

``` -------------------------------- ### Using Hooks and RAtoms with :f> Shortcut Source: https://github.com/reagent-project/reagent/blob/master/doc/ReactFeatures.md This example demonstrates using the `:f>` shortcut to create function components that support both React Hooks and Reagent's RAtoms. Ensure the component is defined as a ClojureScript function. ```clojure ;; This is used with :f> so both Hooks and RAtoms work here (defn example [] (let [[count set-count] (react/useState 0)] [:div [:p "You clicked " count " times"] [:button {:on-click #(set-count inc)} "Click"]])) (defn root [] [:div [:f> example]]) ``` -------------------------------- ### Complete TodoMVC Example in ClojureScript Source: https://context7.com/reagent-project/reagent/llms.txt This snippet provides the full implementation of a TodoMVC application using Reagent. It includes state management for todos, input handling, editing, filtering, and rendering. Ensure Reagent and React are properly set up. ```clojure (ns todomvc.core (:require ["react" :as react] [clojure.string :as str] [reagent.core :as r] [reagent.dom.client :as rdomc])) (defonce todos (r/atom (sorted-map))) (defonce counter (r/atom 0)) (defn add-todo [text] (let [id (swap! counter inc)] (swap! todos assoc id {:id id :title text :done false}))) (defn toggle [id] (swap! todos update-in [id :done] not)) (defn save [id title] (swap! todos assoc-in [id :title] title)) (defn delete [id] (swap! todos dissoc id)) ;; Form-2: local val atom, inner fn receives updated props (defn todo-input [{:keys [title on-save on-stop]}] (let [val (r/atom title)] (fn [{:keys [id class placeholder]}] (let [commit #(let [v (str/trim @val)] (when-not (empty? v) (on-save v)) (reset! val "") (when on-stop (on-stop)))] [:input {:value @val :id id :class class :placeholder placeholder :on-blur commit :on-change #(reset! val (-> % .-target .-value)) :on-key-down #(case (.-which %) 13 (commit) 27 (do (reset! val "") (when on-stop (on-stop))) nil)}])))) ;; Functional component (:f>) using useEffect to auto-focus (defn todo-edit [props] (let [ref (react/useRef)] (react/useEffect (fn [] (.focus (.-current ref))) js/undefined)) [todo-input (assoc props :input-ref ref)]) ;; Form-2 with local editing state (defn todo-item [] (let [editing (r/atom false)] (fn [{:keys [id done title]}] [:li {:class [(when done "completed") (when @editing "editing")]} [:div.view [:input.toggle {:type "checkbox" :checked done :on-change #(toggle id)}] [:label {:on-double-click #(reset! editing true)} title] [:button.destroy {:on-click #(delete id)}]] (when @editing [:f> todo-edit {:title title :on-save #(save id %) :on-stop #(reset! editing false)}])]))) (defn todo-app [] (let [filt (r/atom :all)] (fn [] (let [items (vals @todos) done (->> items (filter :done) count) active (- (count items) done)] [:section#todoapp [:header [:h1 "todos"] [todo-input {:placeholder "What needs to be done?" :on-save add-todo}]] [:ul#todo-list (for [todo (filter (case @filt :active (complement :done) :done :done identity) items)] ^{:key (:id todo)} [todo-item todo])] [:footer [:span [:strong active] " items left"] [:ul (for [f [:all :active :done]] ^{:key f} [:li [:a {:class (when (= f @filt) "selected") :on-click #(reset! filt f)} (name f)]])] (when (pos? done) [:button {:on-click #(swap! todos (fn [m] (into {} (remove (comp :done val) m))))} "Clear completed"])]])))) (defonce root (delay (rdomc/create-root (.getElementById js/document "app")))) (defn ^:export run [] (add-todo "Learn Reagent") (add-todo "Build something great") (rdomc/render @root [todo-app])) ``` -------------------------------- ### Mount Reagent Component to DOM Source: https://github.com/reagent-project/reagent/blob/master/README.md Example of how to render a Reagent component into the browser's DOM. This typically targets the `body` element. ```clojure (defn mount-it [] (rd/render [parent] (.-body js/document))) ``` -------------------------------- ### Using handler-fn Macro - Basic Usage Source: https://github.com/reagent-project/reagent/wiki/Beware-Event-Handlers-Returning-False This example shows the basic usage of the `handler-fn` macro. By wrapping the handler's body, it ensures that the handler returns `nil` and does not accidentally trigger event propagation cancellation. ```clojure :on-mouse-out (handler-fn (reset! mouse-over-atom false)) ``` -------------------------------- ### Watch Command for Shadow-CLJS Source: https://github.com/reagent-project/reagent/blob/master/examples/react-transition-group/README.md Use this command to start the Shadow-CLJS build process in watch mode. This is often a prerequisite for running React applications built with Shadow-CLJS. ```bash npx shadow-cljs watch app ``` -------------------------------- ### Reagent Color Demo with Timing Wrapper Source: https://github.com/reagent-project/reagent/blob/master/doc/BatchingAndTiming.md This example showcases asynchronous rendering with a color chooser and a dynamic palette. It uses a timing wrapper to measure and display render times, illustrating smooth updates even with many elements. The `timing-wrapper` function instruments a component to record its render duration. ```clojure (ns example (:require [reagent.core :as r])) (defn timing-wrapper [f] (let [start-time (r/atom nil) render-time (r/atom nil) now #(.now js/Date) start #(reset! start-time (now)) stop #(reset! render-time (- (now) @start-time)) timed-f (with-meta f {:constructor start :UNSAFE_component-will-update start :component-did-mount stop :component-did-update stop})] (fn [] [:div [:p [:em "render time: " @render-time "ms"]] [timed-f]]))) (def base-color (r/atom {:red 130 :green 160 :blue 120})) (def ncolors (r/atom 20)) (def random-colors (r/atom nil)) (defn to-rgb [{:keys [red green blue]}] (let [hex #(str (if (< % 16) "0") (-> % js/Math.round (.toString 16)))] (str "#" (hex red) (hex green) (hex blue)))) (defn tweak-color [{:keys [red green blue]}] (let [rnd #(-> (js/Math.random) (* 256)) tweak #(-> % (+ (rnd)) (/ 2) js/Math.floor)] {:red (tweak red) :green (tweak green) :blue (tweak blue)})) (defn reset-random-colors [color] (reset! random-colors (repeatedly #(-> color tweak-color to-rgb)))) (defn color-choose [color-part] [:div.color-slider (name color-part) " " (color-part @base-color) [:input {:type "range" :min 0 :max 255 :value (color-part @base-color) :on-change (fn [e] (swap! base-color assoc color-part (-> e .-target .-value int)) (reset-random-colors @base-color))}]) (defn ncolors-choose [] [:div.color-slider "number of color divs " @ncolors [:input {:type "range" :min 0 :max 500 :value @ncolors :on-change #(reset! ncolors (-> % .-target .-value int))}]) (defn color-plate [color] [:div.color-plate {:style {:background-color color}}]) (defn palette [] (let [color @base-color n @ncolors] [:div [:p "base color: "] [color-plate (to-rgb color)] [:div.color-samples [:p n " random matching colors:"] (map-indexed (fn [k v] ^{:key k} [color-plate v]) (take n @random-colors))]])) (defn color-demo [] (reset-random-colors @base-color) (fn [] [:div [:h2 "Matching colors"] [color-choose :red] [color-choose :green] [color-choose :blue] [ncolors-choose] [timing-wrapper palette]])) ``` -------------------------------- ### Reagent Implementation of React Fragment Example Source: https://github.com/reagent-project/reagent/blob/master/doc/CreatingReagentComponents.md This snippet demonstrates how to define a component in Reagent that utilizes a React Fragment (`:<>`) to return multiple sibling elements, similar to the `Columns` example in React documentation. ```clojurescript (defn columns [] [:<> [:td "Hello"] [:td "World"]] ``` -------------------------------- ### Creating a Reaction with the reaction Macro Source: https://github.com/reagent-project/reagent/blob/master/doc/ManagingState.md Illustrates using the `reagent.ratom/reaction` macro for a more concise way to create reactions. This example creates a boolean reaction that checks if two input atoms are populated. ```clojure (let [username (reagent/atom "") password (reagent/atom "") fields-populated? (reagent.ratom/reaction (every? not-empty [@username @password]))] [:div "Is username and password populated ?" @fields-populated?]) ``` -------------------------------- ### Build Reagent Package Source: https://github.com/reagent-project/reagent/blob/master/doc/development.md Install the Reagent package locally after building it. This command overwrites versions released on Clojars in your local Maven repository. ```bash lein install ``` -------------------------------- ### Hydrating React DOM with Reagent Source: https://github.com/reagent-project/reagent/blob/master/doc/ReactFeatures.md This example shows how to hydrate a client-side React application using Reagent. It attaches event listeners to existing server-rendered HTML. ```clojure (react-dom/hydrate (r/as-element [main-component]) container) ``` -------------------------------- ### Reagent Timer Component (Form-2) Source: https://github.com/reagent-project/reagent/blob/master/doc/CreatingReagentComponents.md Use this form when a component needs setup or local state. The outer function initializes state, and the inner render function closes over it. ```clojure (defn timer-component [] (let [seconds-elapsed (reagent/atom 0)] ;; setup, and local state (fn [] ;; inner, render function is returned (js/setTimeout #(swap! seconds-elapsed inc) 1000) [:div "Seconds Elapsed: " @seconds-elapsed]))) ``` -------------------------------- ### Minimal dangerouslySetInnerHTML Example in Reagent Source: https://github.com/reagent-project/reagent/blob/master/doc/FAQ/dangerouslySetInnerHTML.md Use this snippet to render raw HTML content within a Reagent component. Ensure you understand the security implications before using this feature. ```clojure [:div {:dangerouslySetInnerHTML (r/unsafe-html "")}] ``` -------------------------------- ### Component with Delayed Rendering Function Source: https://github.com/reagent-project/reagent/blob/master/README.md Shows how a component function can return another function for delayed rendering, useful for setup tasks. This avoids direct use of React lifecycle methods. ```clojure (defn timer-component [] (let [seconds-elapsed (r/atom 0)] (fn [] (js/setTimeout #(swap! seconds-elapsed inc) 1000) [:div "Seconds Elapsed: " @seconds-elapsed]))) ``` -------------------------------- ### Memoized Reactive Computations with `track` and `track!` Source: https://context7.com/reagent-project/reagent/llms.txt Use `track` for lazy, cached computations that re-evaluate only when their ratom dependencies change and their output value changes. Use `track!` for eager computations that run immediately and continuously until disposed. This example demonstrates tracking lists and individual items, and an eager logger. ```clojure (ns example.tracking (:require [reagent.core :as r])) (defonce app-state (r/atom {:people {1 {:name "Alice"} 2 {:name "Bob"} 3 {:name "Carol"}}})) (defn people [] (:people @app-state)) (defn person-keys [] (-> @(r/track people) keys sort)) (defn person [id] (-> @(r/track people) (get id))) ;; Only re-renders when person-keys list changes (defn name-list [] (let [ids @(r/track person-keys)]) [:ul (for [id ids] ^{:key id} [:li @(r/track person id) " — " (:name @(r/track person id))])]) ;; Eager tracker: logs every state change until disposed (defonce logger (r/track! #(js/console.log "State:" (str @app-state)))) ;; Stop tracking: ;; (r/dispose! logger) ``` -------------------------------- ### Component with Event Listener using with-let Source: https://github.com/reagent-project/reagent/blob/master/doc/CreatingReagentComponents.md Demonstrates creating a component that sets up a mouse move event listener and cleans it up when the component unmounts, using `r/with-let` for managing the listener and a local atom. ```clojure (defn mouse-pos-comp [] (r/with-let [pointer (r/atom nil) handler #(swap! pointer assoc :x (.-pageX %) :y (.-pageY %)) _ (.addEventListener js/document "mousemove" handler)] [:div "Pointer moved to: " (str @pointer)] (finally (.removeEventListener js/document "mousemove" handler)))) ``` -------------------------------- ### Prepare Test Environments Source: https://github.com/reagent-project/reagent/blob/master/doc/development.md Execute the script to set up different environments required for running tests. ```bash ./prepare-tests.sh ``` -------------------------------- ### Creating a Reaction with make-reaction Source: https://github.com/reagent-project/reagent/blob/master/doc/ManagingState.md Shows how to create a reaction using `reagent.ratom/make-reaction` to derive a value from a state atom. This reaction will update automatically when the relevant part of the `app-state` changes. ```clojure (def app-state (reagent/atom {:state-var-1 {:var-a 2 :var-b 3} :state-var-2 {:var-a 7 :var-b 9}})) (def app-var2a-reaction (reagent.ratom/make-reaction #(get-in @app-state [:state-var-2 :var-a]))) (defn component-using-make-reaction [] [:div [:div "component-using-make-reaction"] [:div "state-var-2 - var-a : " @app-var2a-reaction]]) ``` -------------------------------- ### Continuous State Monitoring with track! Source: https://github.com/reagent-project/reagent/blob/master/doc/ManagingState.md Shows how to use `r/track!` to continuously monitor changes in application state. The provided function is invoked immediately and whenever its dependencies change. Use `r/dispose!` to stop the tracking. ```clojure (defn log-app-state [] (prn @app-state)) ``` ```clojure (defonce logger (r/track! log-app-state)) ``` ```clojure (r/dispose! logger) ``` -------------------------------- ### Reagent Hiccup Data Structures Source: https://github.com/reagent-project/reagent/blob/master/doc/Security.md Demonstrates regular use of Hiccup for creating nested elements and an example of potentially unsafe HTML injection. ```clojure ;; Regular use (let [h [:h1 "Hello"]] [:div h [:p "world"]]) ``` ```clojure ;; Data from an API (def title (r/atom nil)) ;; Some code that retrieves an EDN/Transit value from an external API or localStorage ;; and stores the decoded value into the atom: (reset! title [:div {:dangerouslySetInnerHTML {:__html ""}}]) [:div [:h1 @title]] ``` ```clojure ;; One safe approach [:div [:h1 (str @title)]] ``` -------------------------------- ### Tracked Component with Event Listener using with-let Source: https://github.com/reagent-project/reagent/blob/master/doc/CreatingReagentComponents.md Shows how to combine `r/with-let` with `r/track` to create a component that tracks a reactive value, ensuring cleanup logic runs when the tracked component is unmounted. ```clojure (defn mouse-pos [] (r/with-let [pointer (r/atom nil) handler #(swap! pointer assoc :x (.-pageX %) :y (.-pageY %)) _ (.addEventListener js/document "mousemove" handler)] @pointer (finally (.removeEventListener js/document "mousemove" handler)))) (defn tracked-pos [] [:div "Pointer moved to: " (str @(r/track mouse-pos))]) ``` -------------------------------- ### Parent Component Using a Reagent Component Source: https://github.com/reagent-project/reagent/blob/master/doc/WhenDoComponentsUpdate.md Illustrates a parent component rendering multiple instances of a child component ('greet'). One instance receives a static prop, while the other receives a dynamically generated prop, demonstrating how props can change over time and trigger re-renders. ```clojure (defn greet-family [] [:div [greet "Dad"] [greet (str "Bro-" (rand-int 10))]]) ``` -------------------------------- ### Create and Use Reagent Compiler Source: https://github.com/reagent-project/reagent/blob/master/doc/ReagentCompiler.md Defines a compiler with functional component support and demonstrates its usage with `reagent.dom/render` and `reagent.core/as-element`. It also shows how to set this compiler as the default. ```clojure (def functional-compiler (reagent.core/create-compiler {:function-components true})) ;; Using the option (reagent.dom/render [main] div functional-compiler) (reagent.core/as-element [main] functional-compiler) ;; Setting compiler as the default (reagent.core/set-default-compiler! functional-compiler) ``` -------------------------------- ### Create React Elements using Reagent Source: https://github.com/reagent-project/reagent/blob/master/doc/InteropWithReact.md Demonstrates multiple ways to create React elements using Reagent's `create-element` and `as-element` functions, suitable for direct use or within Hiccup forms. ```clojure (defn integration [] [:div [:div.foo "Hello " [:strong "world"]] (r/create-element "div" #js{:className "foo"} "Hello " (r/create-element "strong" #js{} "world")) (r/create-element "div" #js{:className "foo"} "Hello " (r/as-element [:strong "world"])) [:div.foo "Hello " (r/create-element "strong" #js{} "world")]]) (defn mount-root [] (rdom/render [integration] (.getElementById js/document "app"))) ``` -------------------------------- ### Creating a Parent Component with Multiple Children (Square Brackets) Source: https://github.com/reagent-project/reagent/blob/master/doc/UsingSquareBracketsInsteadOfParens.md This function creates a parent component that renders multiple child `greet` components. Using square brackets ensures each `greet` child is a distinct React component, allowing independent re-renders. ```clojure (defn greet-family-square [member1 member2 member3] [:div [greet member1] [greet member2] [greet member3]]) ``` -------------------------------- ### Correctly Using HTML Entity with goog.string Source: https://github.com/reagent-project/reagent/blob/master/doc/FAQ/UsingAnEntity.md Require the `goog.string` module and use `unescapeEntities` to correctly render HTML entities. This method relies on the DOM, so it may not work in Node.js environments without additional setup. ```clojure (:require [goog.string :as gstring]) ``` ```clojure [:div "hello" (gstring/unescapeEntities " ") "there"] ``` -------------------------------- ### Reagent Context Provider and Consumer Source: https://github.com/reagent-project/reagent/blob/master/doc/ReactFeatures.md Demonstrates creating a React context in Reagent and using its Provider and Consumer components. ```cljs (defonce my-context (react/createContext "default")) (def Provider (.-Provider my-context)) (def Consumer (.-Consumer my-context)) (rdom/render [:> Provider {:value "bar"} [:> Consumer {} (fn [v] (r/as-element [:div "Context: " v]))]] container) ``` -------------------------------- ### Focused Atom Slices with `cursor` Source: https://context7.com/reagent-project/reagent/llms.txt Use `cursor` to create a focused view into a nested ratom. Components dereferencing a cursor re-render only when their specific path within the parent ratom changes, improving performance. This example shows editing and toggling nested state. ```clojure (ns example.cursors (:require [reagent.core :as r] [reagent.dom.client :as rdomc])) (defonce state (r/atom {:user {:name "Alice" :age 30} :settings {:theme "dark"}})) ;; Cursor into nested path (def name-cursor (r/cursor state [:user :name])) (def theme-cursor (r/cursor state [:settings :theme])) (defn name-editor [] [:div [:label "Name: "] [:input {:value @name-cursor :on-change #(reset! name-cursor (-> % .-target .-value))}]]]) (defn theme-toggle [] [:button {:on-click #(swap! theme-cursor {"dark" "light" "light" "dark"})} "Theme: " @theme-cursor]) ;; name-editor re-renders only when [:user :name] changes ;; theme-toggle re-renders only when [:settings :theme] changes (defonce root (rdomc/create-root (.getElementById js/document "app"))) (rdomc/render root [:div [name-editor] [theme-toggle]]) ``` -------------------------------- ### Creating and Using Reagent Cursors Source: https://github.com/reagent-project/reagent/blob/master/doc/ManagingState.md Demonstrates how to create a state atom and then derive cursors from it. Components using cursors only re-render when the specific part of the state they are interested in changes. ```clojure ;; First create a ratom (def state (reagent/atom {:foo {:bar "BAR"} :baz "BAZ" :quux "QUUX"})) ;; Now create a cursor (def bar-cursor (reagent/cursor state [:foo :bar])) (defn quux-component [] (js/console.log "quux-component is rendering") [:div (:quux @state)]) (defn bar-component [] (js/console.log "bar-component is rendering") [:div @bar-cursor]) (defn mount-root [] (rdom/render [:div [quux-component] [bar-component]] (.getElementById js/document "app")) (js/setTimeout (fn [] (swap! state assoc :baz "NEW BAZ")) 1000) (js/setTimeout (fn [] (swap! state assoc-in [:foo :bar] "NEW BAR")) 2000)) ``` -------------------------------- ### Run Full Test Suite Source: https://github.com/reagent-project/reagent/blob/master/doc/development.md Execute the script to run all tests in the Reagent project. ```bash ./run-tests.sh ``` -------------------------------- ### Form-2 Components with Local State and Cleanup Source: https://context7.com/reagent-project/reagent/llms.txt Form-2 components use an outer function to initialize per-instance local state and return an inner render function. Use `r/with-let` for managing resources with cleanup via `finally`. ```clojure (ns example.timer (:require [reagent.core :as r])) ;; Outer fn runs once; inner fn runs on every re-render (defn timer-component [] (let [seconds (r/atom 0) interval (js/setInterval #(swap! seconds inc) 1000)] (r/with-let [_ nil] ; Use `with-let` for resource management [:div "Elapsed: " @seconds "s"] (finally (js/clearInterval interval))))) ; Cleanup via finally ;; Alternative using explicit Form-2 with cleanup via lifecycle (defn stopwatch [] (let [elapsed (r/atom 0)] (fn [] ;; <-- inner render function; must repeat params if any [:div [:span "Time: " @elapsed "s"] [:button {:on-click #(reset! elapsed 0)} "Reset"]]))) ``` -------------------------------- ### Creating a Parent Component with Multiple Children (Parentheses) Source: https://github.com/reagent-project/reagent/blob/master/doc/UsingSquareBracketsInsteadOfParens.md This function also creates a parent component rendering multiple `greet` children, but uses parentheses `()` for the hiccup. This approach incorporates all children into a single data structure, causing them to re-render with the parent. ```clojure (defn greet-family-round [member1 member2 member3] [:div (greet member1) (greet member2) (greet member3)]) ``` -------------------------------- ### React Fragment Syntax Source: https://github.com/reagent-project/reagent/blob/master/doc/ReactFeatures.md Shows the equivalent JSX and Reagent syntax for React Fragments. ```js function example() { return ( ); } ``` ```cljs (defn example [] [:<> [child-a] [child-b] [child-c]]) ``` -------------------------------- ### Local State with Cleanup using `with-let` Source: https://context7.com/reagent-project/reagent/llms.txt Use `with-let` for bindings that execute once per component instance and include an optional `finally` clause for cleanup on unmount. This is useful for managing local state and side effects like event listeners. ```clojure (ns example.mouse (:require [reagent.core :as r])) (defn mouse-tracker [] (r/with-let [pos (r/atom {:x 0 :y 0}) handler (fn [e] (reset! pos {:x (.-pageX e) :y (.-pageY e)})) _ (.addEventListener js/document "mousemove" handler)] [:div "Mouse: " (:x @pos) ", " (:y @pos)] (finally (.removeEventListener js/document "mousemove" handler)))) ``` -------------------------------- ### Create React Components from Reagent Components Source: https://github.com/reagent-project/reagent/blob/master/doc/InteropWithReact.md Illustrates how to convert Reagent components into React components using `reagent/reactify-component`. This is useful for exporting Reagent logic to be used in pure React contexts. ```clojure (defn exported [props] [:div "Hi, " (:name props)]) (def react-comp (r/reactify-component exported)) (defn could-be-jsx [] (r/create-element react-comp #js{:name "world"})) ``` -------------------------------- ### Integrate Higher-Order React Components with Reagent Source: https://github.com/reagent-project/reagent/blob/master/doc/InteropWithReact.md Demonstrates how to use both `adapt-react-class` and `reactify-component` to integrate React components that employ the decorator pattern, such as those from React DnD. ```clojure (def react-dnd-component (let [decorator (DragDropContext HTML5Backend)] (reagent/adapt-react-class (decorator (reagent/reactify-component top-level-component))))) ``` ```javascript import HTML5Backend from 'react-dnd-html5-backend'; import { DragDropContext } from 'react-dnd'; class TopLevelComponent { /* ... */ } export default DragDropContext(HTML5Backend)(TopLevelComponent); ``` -------------------------------- ### State Management with Atoms Source: https://github.com/reagent-project/reagent/blob/master/README.md Demonstrates state management in Reagent using `reagent.core/atom`. Components that dereference atoms automatically re-render when the atom's value changes. ```clojure (defonce click-count (r/atom 0)) (defn state-ful-with-atom [] [:div {:on-click #(swap! click-count inc)} "I have been clicked " @click-count " times."]) ``` -------------------------------- ### Reagent State Management with track Source: https://github.com/reagent-project/reagent/blob/master/doc/ManagingState.md Demonstrates how to use `r/track` to create reactive values from functions that depend on Reagent atoms. This optimizes component re-renders by only updating when the tracked value changes. Ensure the first argument to `track` is a named function. ```clojure (ns example.core (:require [reagent.core :as r])) (defonce app-state (r/atom {:people {1 {:name "John Smith"} 2 {:name "Maggie Johnson"}}})) (defn people [] (:people @app-state)) (defn person-keys [] (-> @(r/track people) keys sort)) (defn person [id] (-> @(r/track people) (get id))) (defn name-comp [id] (let [p @(r/track person id)] [:li (:name p)])) (defn name-list [] (let [ids @(r/track person-keys)] [:ul (for [i ids] ^{:key i} [name-comp i])])) ``` -------------------------------- ### Server-Side Rendering with Reagent Source: https://github.com/reagent-project/reagent/blob/master/doc/ReactFeatures.md This code demonstrates how to perform server-side rendering using Reagent. It converts a main Reagent component into an HTML string. ```clojure (reagent.dom.server/render-to-string (reagent.core/as-element [main-component])) ``` -------------------------------- ### Compose Reagent Components Source: https://github.com/reagent-project/reagent/blob/master/README.md Illustrates how to use one Reagent component within another, enabling hierarchical UI structures. Ensure the called component is defined. ```clojure (defn calling-component [] [:div "Parent component" [some-component]]) ``` -------------------------------- ### Define a Simple Reagent Component Source: https://github.com/reagent-project/reagent/blob/master/doc/CreatingReagentComponents.md Create a basic component by defining a ClojureScript function that accepts data as parameters and returns Hiccup (HTML structure). This is the most straightforward method for component creation. ```clojurescript (defn greet [name] [:div "Hello " name]) ``` -------------------------------- ### Reagent Render Loop Hooks Source: https://context7.com/reagent-project/reagent/llms.txt Schedule callbacks using `r/next-tick` (before next paint) or `r/after-render` (after render completes). `r/flush` forces an immediate synchronous render, useful for testing. ```clojure (ns example.timing (:require [reagent.core :as r])) (defonce ui-state (r/atom {:value "" :focused false})) (defn timed-input [] [:input {:value (:value @ui-state) :on-change (fn [e] (let [v (-> e .-target .-value)] (swap! ui-state assoc :value v) ;; Run before next paint — good for reading layout (r/next-tick #(js/console.log "pre-render value:" v)) ;; Run after render completes — good for DOM side-effects (r/after-render #(js/console.log "post-render DOM updated"))))}]) ;; Force immediate synchronous render (useful in tests) (defn set-and-flush! [new-val] (reset! ui-state {:value new-val :focused false}) (r/flush) ;; DOM is now updated synchronously (js/console.log "DOM updated:" (.-value (.getElementById js/document "my-input")))) ``` -------------------------------- ### Adapt React Class Components for Reagent Source: https://github.com/reagent-project/reagent/blob/master/doc/InteropWithReact.md Shows how to use `reagent/adapt-react-class` to wrap React class components, allowing them to be used within Reagent's Hiccup syntax. The `:>` shorthand is also demonstrated. ```clojure (defn top-articles [articles] [(reagent/adapt-react-class FlipMove) {:duration 750 :easing "ease-out"} articles]) ``` ```clojure (defn top-articles [articles] [:> FlipMove {:duration 750 :easing "ease-out"} articles]) ``` ```javascript const TopArticles = ({ articles }) => ( {articles} ); ``` -------------------------------- ### Mounting Reagent Components with React 19 Client API Source: https://context7.com/reagent-project/reagent/llms.txt Primary entry point for React 19 applications. Creates a React root attached to a DOM node and renders a Reagent component tree. Use `defonce` for the root to persist across hot-reloads. ```clojure (ns example.app (:require [reagent.core :as r] [reagent.dom.client :as rdomc])) (defn app [] [:div.container [:h1 "Hello, Reagent!"] [:p "Built with React 19 + ClojureScript"]]) ;; Create root once; re-render on hot-reload (defonce react-root (rdomc/create-root (.getElementById js/document "app"))) (defn ^:export ^:dev/after-load run [] (rdomc/render react-root [app])) ;; To unmount: ;; (rdomc/unmount react-root) ;; Optional: enable React StrictMode ;; (rdomc/render react-root [app] nil true) ``` -------------------------------- ### `reagent.dom.client/create-root` and `reagent.dom.client/render` — Mount components (React 19) Source: https://context7.com/reagent-project/reagent/llms.txt Creates a React root attached to a DOM node and renders a Reagent component tree into it. This is the primary entry point for React 19 applications. ```APIDOC ## `reagent.dom.client/create-root` and `reagent.dom.client/render` — Mount components (React 19) Creates a React root attached to a DOM node and renders a Reagent component tree into it. This is the primary entry point for React 19 applications. ```clojure (ns example.app (:require [reagent.core :as r] [reagent.dom.client :as rdomc])) (defn app [] [:div.container [:h1 "Hello, Reagent!"] [:p "Built with React 19 + ClojureScript"]]) ;; Create root once; re-render on hot-reload (defonce react-root (rdomc/create-root (.getElementById js/document "app"))) (defn ^:export ^:dev/after-load run [] (rdomc/render react-root [app])) ;; To unmount: ;; (rdomc/unmount react-root) ;; Optional: enable React StrictMode ;; (rdomc/render react-root [app] nil true) ``` ``` -------------------------------- ### Render a Form-3 Component Source: https://github.com/reagent-project/reagent/blob/master/doc/CreatingReagentComponents.md Demonstrates how to render a Form-3 component directly or as a child within another Reagent component. Ensure the Reagent class is placed in square brackets to trigger rendering. ```clojure (reagent/render [my-component 1 2 3] ;; pass in x y z (.-body js/document)) ``` ```clojure (defn homepage [] [:div [:h1 "Welcome"] [my-component 1 2 3]]) ;; Be sure to put the Reagent class in square brackets to force it to render! ``` -------------------------------- ### Generating Hiccup Programmatically with `into` and `map` Source: https://github.com/reagent-project/reagent/blob/master/doc/UsingSquareBracketsInsteadOfParens.md This rewrite of `greet-family-round` demonstrates generating hiccup more dynamically. It uses `into` to prepend a `:div` to a sequence of hiccup generated by mapping the `greet` function over a list of members. ```clojure (defn greet-family-round-2 [& members] (into [:div] (map greet members))) ``` -------------------------------- ### Add Static Methods/Properties to `create-class` Source: https://github.com/reagent-project/reagent/blob/master/doc/ReactFeatures.md Modify the return value of `r/create-class` to add custom static methods or properties. While `create-class` handles built-in static methods, others require manual assignment using `set!`. ```clojure (let [klass (r/create-class ...)]) (set! (.-static-property klass) "foobar") (set! (.-static-method klass) (fn [param] ...)) klass) ``` -------------------------------- ### Component with Dynamic Class Names Source: https://github.com/reagent-project/reagent/blob/master/README.md Demonstrates how to use dynamic class names in Reagent components, supporting collections of classes and automatic removal of nil values since version 0.8. ```clojure [:div {:class ["a-class" (when active? "active") "b-class"]}]) ``` -------------------------------- ### reagent.core/adapt-react-class and :> shorthand Source: https://context7.com/reagent-project/reagent/llms.txt Enables the use of React components within Reagent's Hiccup syntax by wrapping them. The `:>` shorthand provides an inline alternative for the same functionality. ```APIDOC ## `reagent.core/adapt-react-class` and `:>` shorthand — Use React components in Hiccup Wraps a native React component so it can be used in the first position of a Hiccup vector. The `:>` shorthand does the same thing inline. ```clojure (ns example.interop (:require ["react-flip-move" :default FlipMove] ["react-select" :default Select] [reagent.core :as r])) (def flip-move (r/adapt-react-class FlipMove)) (defn animated-list [items] [flip-move {:duration 750 :easing "ease-out"} (for [item items] ^{:key (:id item)} [:div.item (:name item)])]) ;; Using the :> shorthand — equivalent to adapt-react-class (defn select-input [value on-change] [:> Select {:value value :onChange on-change :options [{:value "clj" :label "Clojure"} {:value "cljs" :label "ClojureScript"}]} ]) ``` ``` -------------------------------- ### Creating Non-Standard HTML Attributes Source: https://github.com/reagent-project/reagent/blob/master/doc/UsingHiccupToDescribeHTML.md Shows how to define custom HTML attributes that are not standard keywords by using string keys in the attribute map. This allows for flexibility with non-standard attributes. ```clojure [:span {"custom-attribute" "value"}] ``` -------------------------------- ### Child Component: greet-number Source: https://github.com/reagent-project/reagent/blob/master/doc/WhenDoComponentsUpdate.md A simple child component that displays a greeting with a number. It expects an integer as a prop. ```clojure (defn greet-number "I say hello to an integer" [num] ;; an integer [:div (str "Hello #" num)]) ``` -------------------------------- ### Create Reagent Component Class with `create-class` Source: https://github.com/reagent-project/reagent/blob/master/doc/ReactFeatures.md Use `r/create-class` to define Reagent components that require custom methods or properties, ensuring compatibility when passed as classes to other React components. Avoid `r/reactify-component` for functions that return classes to maintain correct class recognition. ```clojure ;; Correct way (def editor (r/create-class {:get-input-node (fn [this] ...) :reagent-render (fn [] [:input ...])})) [:> SomeComponent {:editor-component editor}] ``` ```clojure ;; Often incorrect way (defn editor [parameter] (r/create-class {:get-input-node (fn [this] ...) :reagent-render (fn [] [:input ...])})) [:> SomeComponent {:editor-component (r/reactify-component editor)}] ``` -------------------------------- ### Run Figwheel Tests Source: https://github.com/reagent-project/reagent/blob/master/doc/development.md Use Figwheel to run tests in the browser during development. Open http://0.0.0.0:3449 and check the console for output. ```clojure lein figwheel client # For Cljsjs ``` ```clojure lein figwheel client-npm # NPM ``` -------------------------------- ### CSS Custom Properties Syntax for Style Source: https://github.com/reagent-project/reagent/blob/master/doc/UsingHiccupToDescribeHTML.md Demonstrates how to set CSS custom properties within the 'style' attribute by using a string key for the custom property name in the style map. This is a workaround due to keyword-to-property name conversion. ```clojure [:span {:style {"--custom-property" "value"}}] ``` -------------------------------- ### Create and Use a Reagent Atom Source: https://github.com/reagent-project/reagent/blob/master/doc/ManagingState.md Define a Reagent atom using `r/atom` and use it within a component. Components that dereference the atom will re-render when its value changes. ```clojure (ns example (:require [reagent.core :as r])) (def click-count (r/atom 0)) (defn counting-component [] [:div "The atom " [:code "click-count"] " has value: " @click-count ". " [:input {:type "button" :value "Click me!" :on-click #(swap! click-count inc)}]]) ``` -------------------------------- ### Handle Function-as-child React Components in Reagent Source: https://github.com/reagent-project/reagent/blob/master/doc/InteropWithReact.md Shows how to pass a function as a child to React components that expect this pattern, using `reagent/adapt-react-class` and `reagent/as-element` for components like React AutoSizer. ```clojure [(reagent/adapt-react-class AutoSizer) {} (fn [dims] (let [dims (js->clj dims :keywordize-keys true)] (reagent/as-element [my-component (:height dims)])))] ``` -------------------------------- ### Using Parentheses: Function Call and Return Value Source: https://github.com/reagent-project/reagent/blob/master/doc/UsingSquareBracketsInsteadOfParens.md When a function like `greet` is called using parentheses (), it executes and returns a hiccup vector. This return value is then inserted into the parent structure. ```clojurescript (greet "You") ;; => [:div "Hello " "You"] ;; a vector of a keyword and two strings ``` ```clojurescript (first (greet "You")) ;; => :div ``` ```clojurescript (second (greet "You")) ;; => "Hello" ``` -------------------------------- ### Implement Suspense with Fallback Element Source: https://github.com/reagent-project/reagent/blob/master/doc/ReactFeatures.md Use `r/as-element` to provide a fallback UI for suspended components, similar to React's `Suspense`. This is useful for components from JavaScript libraries that utilize suspending. ```clojure (def data #js {:current nil}) (def slow-data-request (js/Promise. (fn [resolve _reject] (js/setTimeout (fn [] (set! (.-current data) "ready!") (resolve)) 2000)))) (defn slow-component [] (when (nil? (.-current data)) ;; React 18, in 19 react/use replaces throwing Promises to suspend ;; an component. (throw slow-data-request)) [:div (.-current data)]) (defn simple-component [] [:div [:> react/Suspense {:fallback (r/as-element [:div "loading"])} [slow-component]]]) ``` -------------------------------- ### Handle Events with rswap! Source: https://github.com/reagent-project/reagent/blob/master/doc/ManagingState.md Use `rswap!` for event handling, as it always returns `nil` and allows recursive calls, preventing potential issues with React's event handling. ```clojure (defn event-handler [state [event-name id value]] (case event-name :set-name (assoc-in state [:people id :name] value) :add-person (let [new-key (->> state :people keys (apply max) inc)] (assoc-in state [:people new-key] {:name ""})) state)) ``` ```clojure (defn emit [e] ;; (js/console.log "Handling event" (str e)) (r/rswap! app-state event-handler e)) ``` ```clojure (defn name-edit [id] (let [p @(r/track person id)] [:div [:input {:value (:name p) :on-change #(emit [:set-name id (.. % -target -value)])}]])) ``` ```clojure (defn edit-fields [] (let [ids @(r/track person-keys)] [:div [name-list] (for [i ids] ^{:key i} [name-edit i]) [:input {:type 'button :value "Add person" :on-click #(emit [:add-person])}])) ```