Reagent

Reagent 소개

  • Reagent는 React ClojureScript 라이브러리
  • ClojureScript 함수와 데이터로 React를 사용할 수 있음
  • Hiccup 문법으로 UI 구성
  • 기본적인 Reagent 컴포넌트 예

    (defn simple-component []
      [:div
        [:p "I am a component!"]
        [:p.someclass
          "I have " [:strong "bold"]
          [:span {:style {:color "red"}} " and red "] "text."]])
    
  • 컴포넌트는 다른 컴포넌트를 포함해서 작성 할 수 있음

    (defn simple-parent []
      [:div
       [:p "I include simple-component."]
       [simple-component]])
    
  • 컴포넌트에 클로저 데이터 전달 할 수 있음

    (defn hello-component [name]
      [:p "Hello, " name "!"])
    
    (defn say-hello []
      [hello-component "world"])
    
  • 컴포넌트에서 다른 컴포넌트를 사용할 때 일반 함수로 부를 수도 있지만 []형태로 컴포넌트를 사용하는 것은 데이터 변경에 따른 자동 re-rendering 처리가 되지 않는 문제가 있음

  • React의 키는 메타데이터로 줄 수 있음 (안주면 자동으로 생성)

    (defn lister [items]
      [:ul
        (for [item items]
          ^{:key item} [:li "Item " item])])
    
    (defn lister-user []
      [:div
       "Here is a list:"
       [lister (range 3)]])
    

Reagent 상태 관리

  • Reagent에서 제공하는 atom을 사용하면 쉽게 상태 관리를 할 수 있음
  • Reagent atom을 사용하는 컴포넌트는 값이 바꼈을 때 자동으로 re-rendering이 됨
  • 예제

    (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)}]])
    
  • 컴포넌트 안에서 사용하는 상태가 필요할때 도 atom을 사용
  • 컴포넌트를 리턴하는 함수?

    (defn timer-component []
      (let [seconds-elapsed (r/atom 0)]
        (fn []
          (js/setTimeout #(swap! seconds-elapsed inc) 1000)
          [:div
           "Seconds Elapsed: " @seconds-elapsed])))
    
  • atom을 전달하는 식으로 다른 컴포넌트와 상태를 공유

    (ns example
      (:require [reagent.core :as r]))
    (defn atom-input [value]
      [:input {:type "text"
               :value @value
               :on-change #(reset! value (-> % .-target .-value))}])
    
    (defn shared-state []
      (let [val (r/atom "foo")]
        (fn []
          [:div
           [:p "The value is now: " @val]
           [:p "Change it here: " [atom-input val]]])))