Почему реагент не воспроизводит мою форму реагента повторно при изменении состояния

Мне нужно создать форму, содержащую поле выбора, где параметры зависят от доступных в настоящее время учетных записей электронной почты. Я получаю эти почтовые аккаунты в запросе API после загрузки страницы.

Следующая функция создает форму с элементом выбора.

(defn create-options [mail-accounts]
  (for [m mail-accounts]
    [:option {:key (keyword (str (:id m)))
              :value (:id m)}
     (:name m)]))

(defn render-mail-account-select [mail-accounts]
  (let [form-state (r/atom {})]
    (fn [mail-accounts]
      (let [form [:form.mailing-form.form-horizontal
                  (into [:select.form-control {:field :list :id :mail-account}]
                        (create-options mail-accounts))]]
        (pprint form)
        [bind-fields form form-state]))))

pprint дает мне следующий результат:

;; Before the mail-accounts are loaded
[:select.form-control {:field :list, :id :mail-account}]

;; After the state update containing the mail accounts
[:select.form-control
 {:field :list, :id :mail-account}
 [:option {:key :24, :value 24} "First mail account name"]
 [:option {:key :25, :value 25} "Second mail account name"]]

Моя проблема в том, что выбор на моей странице остается пустым, как если бы выбор не был повторно отрисован.

Дополнение

Кажется, я забыл добавить код: я оборачиваю эту форму в компонент KIOO, где разыменовываю свой state атом.

(defsnippet choose-account-panel "html/static-panel.html" [:div.panel]
  []
  {[:h4.panel-title] (content "3. Mail Account wählen")
   [:div.panel-body] (content [render-mail-account-select (:mail-accounts @state)])})

Затем этот компонент вызывает мою функцию render-mail-account-select и должен правильно повторно отобразить форму.


person Kungi    schedule 22.10.2015    source источник
comment
(Отказ от ответственности: я не знаю, о чем я говорю). Вы закрываете новый атом реагента в привязке let, но как что-то может обновить этот атом, чтобы сообщить форме об обновлении? Насколько я понимаю, вам нужно закрыть атомы, определенные снаружи, чтобы можно было распространять изменения?   -  person zimablue    schedule 22.10.2015
comment
Закрыв атом form-state, я могу создать локальное состояние компонента.   -  person Kungi    schedule 22.10.2015


Ответы (2)


Вам нужно разыменовать Ratom для Reagent, чтобы знать, какие функции нужно вызывать снова, когда этот Ratom изменится. Это разыменование должно происходить внутри анонимной функции внутри render-mail-account-select или одной из функций, которые она вызывает. Я не вижу здесь разыменования?

См. Документы здесь для получения дополнительных сведений о рендеринге Reagent.

person Daniel Compton    schedule 22.10.2015
comment
Имеет смысл в качестве ответа, но как получилось переформулировать указанную ссылку на документ? - person Chris Murphy; 23.10.2015
comment
В документации по изменению кадра есть действительно полезные советы по использованию реагента. - person Daniel Compton; 23.10.2015

Как уже указывалось, ваша функция рендеринга должна ссылаться на что-то в вашем атоме состояния, чтобы знать, когда это нужно повторно рендерить. Однако, если вы также хотите, чтобы в отображаемой форме было выбрано значение «по умолчанию», вам также необходимо установить атом состояния.

Вызов bind-fields свяжет вашу форму с атомом состояния. Если в состоянии атома ничего нет, форма будет пустой, т.е. ни один из выбранных элементов не будет. Если это то, что вы хотите, тогда все будет в порядке. Однако, если вы хотите выбрать значение, вы должны поместить это значение в атом. Например, если вы хотите, чтобы первый элемент был уже выбран, поместите: 24 в атом состояния, т.е.

(swap! form-state assoc :mail-account :24)

Обратите внимание, что я не уверен, что определение вашего варианта правильное. Документы, похоже, указывают, что вам нужен только атрибут: key со значением (в виде ключевого слова) в этом атрибуте. Я не просматривал источник, чтобы подтвердить это, но ни один из примеров также не использует атрибут: value.

Если вы выполните замену в начале своей функции рендеринга, тогда будет ссылка на атом состояния, и ваш компонент должен повторно рендерить каждый раз, когда он вызывается с новыми аргументами. Когда я говорю «функция рендеринга», в данном случае я имею в виду анонимную функцию, а не внешнюю, которая создает атом состояния.

person Tim X    schedule 22.10.2015
comment
Что такое «вызов добрых полей»? Я не могу найти в вопросе ничего даже похожего на слово gind. Я удалю этот комментарий позже (что, как я предполагаю, означает, что не помещайте комментарий ниже этого, иначе я не смогу - не уверен) - person Chris Murphy; 23.10.2015