Почему невозможно определить состояние компонента реагента в let?

Скажем, у нас есть текстовая область текста, определенная в синтаксисе hiccup.

(def written-text (reagent/atom ""))

(defn text-area []
    [:textarea
     {:value     @written-text
      :on-change #(reset! written-text (-> % .-target .-value))
      :on-click  #(println @written-text)}])

Скажем, мы хотим иметь несколько копий текстовой области в нашем документе, каждая с различным состоянием в них. Затем мы должны переместить состояние, доступное всем в текущем пространстве имен, в лексически ограниченный символ. Что-то вроде:

(defn text-area []
  (let [written-text (reagent/atom "")]
    [:textarea
     {:value     @written-text
      :on-change #(reset! written-text (-> % .-target .-value))
      :on-click  #(println @written-text)}]))

Но в нынешнем виде этот код не работает. Текстовое поле всегда остается пустым, независимо от того, что вводит пользователь. Почему это? И как я заключаю свое состояние в лексическую область компонента?

1 ответ

  1. Ответ на этот вопрос можно найти в документации re-frame, которая описывает различные формы компонентов, которые обычно находятся в проекте reagent. Он утверждает, что для обеспечения постоянной лексической области для каждого компонента состояния, чтобы жить в, Необходимо написать функцию, которая возвращает другую функцию рендеринга; иначе атом состояния будет переопределен каждый раз, когда реагент пытается повторно рендерить компонент. Так для данного компонента:

    (defn text-area []
      (let [written-text (atom "")]
        (fn []                                       
          [:textarea
            {:value     @written-text
             :on-change #(reset! written-text (-> % .-target .-value))}])))
    

    Таким образом, функция, вызываемая reagent, когда она хочет перерисовать компонент, является внутренней, анонимной функцией. Let, определяющий лексическую область, не будет перезапущен.

    Весь кредит за этот ответ идет пользователю mccraigmccraig на clojurians slack.