Нет, это не сработает, как вы ожидаете. Чтобы понять разницу, рассмотрим следующие два компонента:
(defn test-component-if []
(let [a (atom 1)
_ (.log js/console "let in -if")]
(if (odd? @a)
[:div
[:p "odd"]
[:button {:on-click #(swap! a inc)}
"inc"]]
[:div
[:p "even"]
[:button {:on-click #(swap! a inc)}
"inc"]])))
(defn test-component-fn []
(let [a (atom 1)
_ (.log js/console "let in -fn")]
;; I dub thee test-inner
(fn []
(if (odd? @a)
[:div
[:p "odd"]
[:button {:on-click #(swap! a inc)}
"inc"]]
[:div
[:p "even"]
[:button {:on-click #(swap! a inc)}
"inc"]]))))
test-component-fn
работает как положено, а test-component-if
- нет. Это почему? Хорошо, когда компонент реагента может возвращать одну из двух вещей (я игнорирую компоненты типа 3, так как это влияет на знание реакции). Может вернуть
- вектор
- другая функция
Если он возвращает вектор, сама функция становится функцией рендеринга, в нашем случае test-component-if
. Когда он возвращает функцию, функция, которая была возвращена, а не исходная функция, является функцией рендеринга. В этом случае, что я назвал test-inner
Когда Reagent вызывает функцию рендеринга, он отслеживает атомы, к которым обращается функция, и всякий раз, когда этот атом изменяется, он вызывает функцию рендеринга. Так что же происходит, когда мы используем test-component-if
?
- Реагентные вызовы
test-component-if
- Наш оператор let связывает новый атом
a
с 1.
- Вектор возвращается
- нажимаем на кнопку
- Атом
a
увеличивается
- Реагент видит изменение на
a
и звонит test-component-if
- В нашем предложении let связывается новый атом
a
с 1 (атом, отличный от нашего предыдущего a
)
- по электронной почте Ой!
Так что a
всегда 1. Вы можете убедиться в этом, посмотрев на консоль и увидев, что сообщение печатается каждый раз, когда вы нажимаете кнопку.
А как насчет test-component-fn
?
- Реагентные вызовы
test-component-fn
- Наш оператор let связывает новый атом
a
с 1.
test-component-fn
возвращает test-inner
, который закрывается на a
- Реагентные вызовы
test-inner
- Нажимаем на кнопку
a
увеличивается
- Реагент видит изменение на
a
и звонит test-inner
- Повторите столько раз, сколько вы хотите.
Вы можете проверить, что let выполняется еще раз на консоли. Нажмите на кнопку столько раз, сколько вы хотите, сообщение будет напечатано только при первом его отображении.
В терминах if
без предложения else
это действительно вернет ноль. В таких случаях принято использовать , когда вместо if
, что дает понять, что подразумевается отсутствие else
. Он также имеет преимущество включения неявного do . Что касается того, что будет делать Реагент, когда он обнаружит, что nil
, в большинстве случаев он будет молча удалять его и ничего не отображать .