The 'add' and 'remove' items of shoppinglist ratom updates the 'shopping-list' component, but the 'update' doesn't.
I used cljs REPL for updating the shoppinglist ratom.
add:
shopping.app=> (swap! shoppinglist assoc 3 {:id 3, :name "Coke", :price 25})
WARNING: Use of undeclared Var shopping.app/shoppinglist at line 1 <cljs repl>
{1 {:id 1, :name "Bread", :price 23}, 2 {:id 2, :name "Milk", :price 12}, 3 {:id 3, :name "Coke", :price 25}}
remove:
shopping.app=> (swap! shoppinglist dissoc 3)
WARNING: Use of undeclared Var shopping.app/shoppinglist at line 1 <cljs repl>
{1 {:id 1, :name "Bread", :price 20}, 2 {:id 2, :name "Milk", :price 12}}
update:
shopping.app=> (swap! shoppinglist assoc 2 {:id 2, :name "Milk", :price 8})
WARNING: Use of undeclared Var shopping.app/shoppinglist at line 1 <cljs repl>
{1 {:id 1, :name "Bread", :price 20}, 2 {:id 2, :name "Milk", **:price 8**}}
shopping.app=>
The shoppinglist ratom is updated, I checked it in the REPL, but the component is not updated.
(ns shopping.app
(:require [reagent.core :as r]))
(defonce shoppinglist (r/atom (sorted-map
1 {:id 1 :name "Bread" :price 20},
2 {:id 2 :name "Milk" :price 12})))
(defn shopping-item [item]
(let [{:keys [id name price]} item]
(fn []
[:div
[:label id]
[:label (str " | " name)]
[:label (str " | " price)]])))
(defn shopping-list []
[:div.container
(for [item (vals @shoppinglist)]
^{:key (:id item)} [:div
[shopping-item item]])])
(defn init
"Initialize components."
[]
(let [container (.getElementById js/document "container")]
(r/render-component
[shopping-list]
container)))
EDITED ==================================
I found a good overview about the component designs here https://github.com/reagent-project/reagent/blob/master/docs/CreatingReagentComponents.md
Form-2: I didn't put the local state into my example, but my real app contains local stater ratom. According this, I had to put the same parameters for the embedded render functions what the component function has. I modified my example, added local state ratom and params the render function and it works well.
(ns shopping.app
(:require [reagent.core :as r]))
(defonce shoppinglist (r/atom (sorted-map
1 {:id 1 :name "Bread" :price 20},
2 {:id 2 :name "Milk" :price 12})))
(defn shopping-item [{:keys [id name price]}]
(let [loacalstate (r/atom true)]
(fn [{:keys [id name price]}]
[:div
[:label id]
[:label (str " | " name)]
[:label (str " | " price)]])))
(defn shopping-list []
[:div.container
(for [item (vals @shoppinglist)]
^{:key (:id item)} [:div
[shopping-item item]])])
(defn init
"Initialize components."
[]
(let [container (.getElementById js/document "container")]
(r/render-component
[shopping-list]
container)))
Remove the inner no-arg wrapping function in shopping-item
. It is unnecessary, but will prevent re-rendering of existing items, because the no-arg function doesn't see the changed argument.
So:
(defn shopping-item [item]
(let [{:keys [id name price]} item]
[:div
[:label id]
[:label (str " | " name)]
[:label (str " | " price)]]))
or
(defn shopping-item [{:keys [id name price]}]
[:div
[:label id]
[:label (str " | " name)]
[:label (str " | " price)]])
For more information, check out this documentation of form-2 components:
https://github.com/reagent-project/reagent/blob/master/doc/CreatingReagentComponents.md#form-2--a-function-returning-a-function
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With