clojureclojurescripttransit

Reagent atom value is stil nil after reset function


I made service endpoint api for getting single object by id and it works as expected. I tested it with Postman and in handler function. I use cljs-ajax library for asynchronous client. I cant change the state of Reagent atom when I get response. Here is the code:

(ns businesspartners.core
  (:require [reagent.core :as r]
            [ajax.core :refer [GET POST]]
            [clojure.string :as string]))

(def business-partner (r/atom nil))

(defn get-partner-by-id [id]
  (GET "/api/get-partner-by-id"
       {:headers {"Accept" "application/transit+json"}
        :params {:id id}
        :handler #(reset! business-partner (:business-partner %))}))

When I tried to access business-partner atom I got nil value for that atom. I can't figure out why because another method is almost the same except it get's list of business partners and works fine.

When I change the get-partner-by-id function:

(defn get-partner-by-id [id]
  (GET "/api/get-partner-by-id"
       {:headers {"Accept" "application/transit+json"}
        :params {:id id}
        :handler (fn [arg]
                   (println :handler-arg arg)
                   (reset! business-partner (:business-partner arg))
                   (println "Business partner from handler: " @business-partner))}))

Output in the browser console:

 :handler-arg {:_id 5e7ad2c84b5c2d44583e8ecd, 
               :address Main Street, 
               :email nenmit@gmail.com, 
               :phone 555888, 
               :name Nen Mit}

Business partner from handler:  nil

So, as you can see, I have my object in handler as desired, but when I try to reset my atom nothing happens. That's the core of the problem I think. Thank you Alan.


Solution

  • When in doubt, use debug print statements. Make your handler look like this:

    :handler (fn [arg]
               (println :handler-arg arg)
               (reset! business-partner (:business-partner arg)))
    

    You may also want to use clojure.pprint/pprint to pretty-print the output, or also add (type arg) to the output.

    You may also want to initialize the atom to a specific value like :bp-default so you can see if the nil you observe is the original one or if it is being reset to nil.


    Update

    So it is clear the key :business-partner does not exist in the map you are receiveing. This is what you must debug.

    Trying to pull a non-existent key out of a map always returns nil. You could also use the 3-arg version of get to make this explicit. Convert

    (:business-partner arg)  =>  (get arg :business-partner ::not-found)
    

    and you'll see the keyword ::not-found appear in your atom, verifying what is occurring.

    In order to catch these problems early, I nearly always use a simple function grab from the Tupelo library like so:

    (:business-partner arg)  =>  (grab :business-partner arg)
    

    The grab function will throw an exception if the expected key is not found. This provides early-warning of problems so you can track them down faster.

    Another hint: next time use prn instead of println and it will retain double-quotes on string output like:

    "Main Street"