ClojureScript。重新渲染时重置 Reagent 中的原子
ClojureScript. Reset atom in Reagent when re-render occurs
我正在显示一组测验问题,我为每个问题分配了一个编号,以便在浏览器中显示时编号:
(defn questions-list
[]
(let [counter (atom 0)]
(fn []
(into [:section]
(for [question @(re-frame/subscribe [:questions])]
[display-question (assoc question :counter (swap! counter inc))])))))
问题是,当有人在浏览器中编辑问题时(调用调度并更新 "app-db" 地图)组件被重新渲染,但原子 "counter" 逻辑上启动从最后一个数字开始,而不是从零开始。所以我需要重置原子,但我不知道在哪里。我尝试在匿名函数中使用 let 但这没有用。
在这种情况下,我将完全删除状态。我没有测试过这段代码,但你的想法在这里是势在必行的。您尝试执行的操作的功能版本类似于:
贫穷但无国籍:
(let [numbers (range 0 (count questions))
indexed (map #(assoc (nth questions %) :index %) questions)]
[:section
(for [question indexed]
[display-question question])])
但这很丑陋,而且 nth 效率低下。所以让我们尝试一个更好的。事实证明 map 可以接受多个集合作为参数。
(let [numbers (range 0 (count questions))
indexed (map (fn [idx question] (assoc question :index idx)) questions)]
[:section
(for [question indexed]
[display-question question])])
但更好的是,事实证明有一个内置函数正是用于此目的。我实际上会写什么:
[:section
(doall
(map-indexed
(fn [idx question]
[display-question (assoc question :index idx)])
questions))]
注意:此代码的 None 实际上是 运行,因此您可能需要稍微调整一下才能运行。我建议您查看 ClojureDocs 中的所有函数,以确保您了解它们的作用。
如果您需要 counter
只是一个问题的索引,您可以改用这样的东西:
(defn questions-list
[]
(let [questions @(re-frame/subscribe [:questions])
n (count questions)]
(fn []
[:section
[:ul
(map-indexed (fn [idx question] ^{:key idx} [:li question]) questions)]])))
注意:这里我使用了[:li question]
,因为我假设question
是某种文本。
此外,您可以避免计算此组件中问题的 count
,而使用 layer 3 subscription:
(ns your-app.subs
(:require
[re-frame.core :as rf]))
;; other subscriptions...
(rf/reg-sub
:questions-count
(fn [_ _]
[(rf/subscribe [:questions])])
(fn [[questions] _]
(count questions)))
然后在组件的 let
绑定中,您需要将 n (count questions)
替换为 n @(re-frame/subscribe [:questions-count])
。
我正在显示一组测验问题,我为每个问题分配了一个编号,以便在浏览器中显示时编号:
(defn questions-list
[]
(let [counter (atom 0)]
(fn []
(into [:section]
(for [question @(re-frame/subscribe [:questions])]
[display-question (assoc question :counter (swap! counter inc))])))))
问题是,当有人在浏览器中编辑问题时(调用调度并更新 "app-db" 地图)组件被重新渲染,但原子 "counter" 逻辑上启动从最后一个数字开始,而不是从零开始。所以我需要重置原子,但我不知道在哪里。我尝试在匿名函数中使用 let 但这没有用。
在这种情况下,我将完全删除状态。我没有测试过这段代码,但你的想法在这里是势在必行的。您尝试执行的操作的功能版本类似于: 贫穷但无国籍:
(let [numbers (range 0 (count questions))
indexed (map #(assoc (nth questions %) :index %) questions)]
[:section
(for [question indexed]
[display-question question])])
但这很丑陋,而且 nth 效率低下。所以让我们尝试一个更好的。事实证明 map 可以接受多个集合作为参数。
(let [numbers (range 0 (count questions))
indexed (map (fn [idx question] (assoc question :index idx)) questions)]
[:section
(for [question indexed]
[display-question question])])
但更好的是,事实证明有一个内置函数正是用于此目的。我实际上会写什么:
[:section
(doall
(map-indexed
(fn [idx question]
[display-question (assoc question :index idx)])
questions))]
注意:此代码的 None 实际上是 运行,因此您可能需要稍微调整一下才能运行。我建议您查看 ClojureDocs 中的所有函数,以确保您了解它们的作用。
如果您需要 counter
只是一个问题的索引,您可以改用这样的东西:
(defn questions-list
[]
(let [questions @(re-frame/subscribe [:questions])
n (count questions)]
(fn []
[:section
[:ul
(map-indexed (fn [idx question] ^{:key idx} [:li question]) questions)]])))
注意:这里我使用了[:li question]
,因为我假设question
是某种文本。
此外,您可以避免计算此组件中问题的 count
,而使用 layer 3 subscription:
(ns your-app.subs
(:require
[re-frame.core :as rf]))
;; other subscriptions...
(rf/reg-sub
:questions-count
(fn [_ _]
[(rf/subscribe [:questions])])
(fn [[questions] _]
(count questions)))
然后在组件的 let
绑定中,您需要将 n (count questions)
替换为 n @(re-frame/subscribe [:questions-count])
。