WedX - журнал о программировании и компьютерных науках

clojurescript + проблема с реагентом

Я работаю над простым веб-приложением, используя clojurescript и реагент. Я хотел бы создать простой компонент «вкладка», который будет содержать (для начала) компонент ввода текста.

В приложении есть 2 вкладки, и у пользователя есть возможность выбрать вкладку, и я хочу «сохранить» значения на каждой из этих двух вкладок.

Вот код:

(defn atom-input [value]
  [:input {:type "text"
           :value @value
           :on-change #(reset! value (-> % .-target .-value))}])

(defn simple-tab [index]
  (let [pg-index (atom 1)
        a (atom 0)]
    (fn []
    [:div
     [:h4 (str "index: " @index)]
     [atom-input a]])))

(defn main-page []
  (let [index (atom 0)]
    [:div.container
     [:div.row
      [:button {:on-click (fn [] (reset! index 0))} "select tab 1"]
      [:button {:on-click (fn [] (reset! index 1))} "select tab 2"]]
     [:div.row
      [simple-tab index]]]))

(defn ^:export run []
  (reagent/render-component
   (fn [] [main-page])
   (.-body js/document)))

Проблема в том, что когда я переключаю вкладку, компоненты разделяют значения поля ввода - что я здесь делаю не так?

Большое вам спасибо за вашу помощь!


Ответы:


1

Проблема в том, что вы передаете a (atom 0) элементу управления atom-input: [atom-input a]. Это привело к тому, что одно и то же значение атома было разделено между вашими вкладками.

Если вы не хотите делиться значением, вам нужно изменить a на карту: a (atom {}) и передать карту и индекс в atom-input, например:

(defn atom-input [value index]
  [:input {:type "text"
           :value (or (get @value index) "")
           :on-change #(swap! value assoc index (-> % .-target .-value))}])

(defn simple-tab [index]
  (let [pg-index (atom 1)
        a (atom {})]
    (fn []
      [:div
       [:h4 (str "index: " @index)]
       [atom-input a @index]])))

ИМХО, лучший подход - использовать курсор, поэтому вам не нужно передавать индекс и всю карту в atom-input, например:

(defn atom-input [value]
  [:input {:type "text"
           :value (or @value "")
           :on-change #(reset! value (-> % .-target .-value))}])

(defn simple-tab [index]
  (let [pg-index (atom 1)
        a (atom {})]
    (fn []
      [:div
       [:h4 (str "index: " @index)]
       [atom-input (reagent/cursor [@index] a)]])))
06.01.2015

2

Я думаю, здесь есть пара проблем, потому что вы смешиваете данные приложения (состояние) и данные логики отображения (то есть DOM). Если вы сохраните две разные вещи, то есть поддерживаете состояние вашего приложения в одном атоме и данные, относящиеся к отображению компонентов, в другом, тогда все может быть немного чище.

Компоненту простой вкладки не нужно ничего знать о состоянии вкладки. Ему просто нужно знать о состоянии приложения, то есть о значении, введенном / сохраненном через атомный ввод. Поэтому вместо того, чтобы передавать ему индекс, передайте ему атом, который вы хотите использовать. это потребует некоторой логики более высокого уровня для определения вызова. например, если у вас было несколько вкладок, у вас может быть что-то вроде

(condp = @index
  0 [simple-tab tab0-atom]
  1 [simple-tab tab1-atom]
  ...
  n [simple-tab tabn-atom])

или вы можете изменить простую вкладку так, чтобы значение, переданное, то есть значение индекса, использовалось в качестве ключа в состоянии приложения - курсор был бы самым простым, я думаю, т.е.

(def app-state (r/atom {:tabs {0 nil 1 nil}}})

(defn simple-tab [index]
  (let [val-cur (r/cursor app-state [:tabs index])]
    [atom-input val-cur]))
07.10.2015

3

Вы используете компонент form-2, то есть компонент, возвращающий функцию.

Подробнее здесь: https://github.com/Day8/re-frame/wiki/Creating-Reagent-Components#form-2--a-function-returning-a-function

При этом вызывается только возвращенная функция, поэтому ваши входные атомы используют один и тот же атом.

Кроме того, вы должны использовать тот же аргумент во внутренней функции

 (defn simple-tab [index]
      (let [pg-index (atom 1)
            a (atom {})]
        (fn [index]
          [:div
           [:h4 (str "index: " @index)]
           [atom-input a @index]])))

В вашем случае вы передаете атом, поэтому это не важно, но в будущем у вас может быть ошибка, если вы это забудете.

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

Вы также можете называть свои вкладки следующим образом: product: users и использовать мультиметод для отображения правильной вкладки на основе выбранной. Это легче читать и легче добавлять новые вкладки в будущем.

19.02.2017
Новые материалы

Как создать диаграмму градиентной кисти с помощью D3.js
Резюме: Из этого туториала Вы узнаете, как добавить градиентную кисть к диаграмме с областями в D3.js. Мы добавим градиент к значениям SVG и применим градиент в качестве заливки к диаграмме с..

Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что это выглядит сложно…
Просто начните и учитесь самостоятельно Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что он кажется мне сложным, и я бросил его. Это в основном инструмент..

Лицензии с открытым исходным кодом: руководство для разработчиков и создателей
В динамичном мире разработки программного обеспечения открытый исходный код стал мощной парадигмой, способствующей сотрудничеству, инновациям и прогрессу, движимому сообществом. В основе..

Объяснение документов 02: BERT
BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

Как проанализировать работу вашего классификатора?
Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

Работа с цепями Маркова, часть 4 (Машинное обучение)
Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..


Для любых предложений по сайту: [email protected]