You do it just like in plain clojure, using update-in
. First start at the Clojure CheatSheet:
http://jafingerhut.github.io/cheatsheet/clojuredocs/cheatsheet-tiptip-cdocs-summary.html
or the ClojureScript version: http://cljs.info
Look at the docs for update-in
: https://clojuredocs.org/clojure.core/update-in
You need 2 componenents
- A path to navigate the the site of the mutation
- A function to perform the mutation given the point from (1).
You didn't fully specify your data. I'm assuming it looks like this:
(def db {:questions [
{:33 {:question "one", :id 33,
:answers [{:id 22, :question_id 33, :answer "one", :correct false}
{:id 4, :question_id 33, :answer "two", :correct false}]}},
{:39 {:question "two", :id 39, :answers []}},
{:41 {:question "three", :id 41,
:answers [{:id 29, :question_id 41, :answer "one", :correct false}
{:id 35, :question_id 41, :answer "two", :correct true}]}}]})
I'll make up a new answer
map to add:
(def new-answer {:id 42, :question_id 442, :answer "The Ultimate", :correct false})
This code shows the process in pieces.
(let [submap (get-in db [:questions 0 :33 :answers])
modified (conj submap new-answer)
final-answer (update-in db [:questions 0 :33 :answers] conj new-answer) ]
First the navigation to get submap
:
submap =>
[{:id 22, :question_id 33, :answer "one", :correct false}
{:id 4, :question_id 33, :answer "two", :correct false}]
And the way you add the new answer:
modified =>
[{:id 22, :question_id 33, :answer "one", :correct false}
{:id 4, :question_id 33, :answer "two", :correct false}
{:id 42, :question_id 442, :answer "The Ultimate", :correct false}]
And putting it all together into one operation:
final-answer =>
{:questions
[{:33
{:question "one",
:id 33,
:answers
[{:id 22, :question_id 33, :answer "one", :correct false}
{:id 4, :question_id 33, :answer "two", :correct false}
{:id 42, :question_id 442, :answer "The Ultimate", :correct false}]}}
{:39 {:question "two", :id 39, :answers []}}
{:41
{:question "three",
:id 41,
:answers
[{:id 29, :question_id 41, :answer "one", :correct false}
{:id 35, :question_id 41, :answer "two", :correct true}]}}]}
All of this works identically in ClojureScript as in Clojure.
Don't worry about using the path
interceptor. I think it confuses things more than it helps. And don't worry about render speed unless:
- You have it working and tested and know it is right.
- You have measured the render speed and can document that there is a problem and the amount you need to speed up.
- For long lists of things look at the
key
metadata you can add to each list element for Reagent. See: Reagent React Clojurescript Warning: Every element in a seq should have a unique :key
Update
Note that submap
and modified
are shown only for demonstration purposes to show pieces of how update-in
works. The update-in
expression is the only thing you would actually include in your code. Also, note that the update-in
only uses db
and new-answer
.