Fork me on GitHub

I have a component that uses a state machine to trigger a remote mutation on button click. The result of this mutation is in another component. How do I pass this back to the originating component? I tried making the downstream component a part of the originating component, and I tried adding a field to the originating component and updating that by swapping on the state atom directly in the state machine’s ok event, neither seem to work. What am I doing wrong, again?


Component "A" has :onClick #(uism/trigger! this :sessions/session :event/create-session! {...}) mutates a Session component. Component A needs to react to changes in the Session component


I've made the Session component a part of Component A's props and query, and invented a duplicate prop in Component A and tried to update that via the state map. Both seemed to do nothing 😞


Your last part seems okay though, can you share some code? Also, is ComponentA included all the way up to your root component?


This is the Session component:

(defsc Session
  [this {:keys [session/token session/current-user session/error] :as props}]
  {:query [:session/token :session/current-user :session/error]
   :ident (fn [] [:component/id :session])
   :initial-state {}}
  (when token
    (dom/div (:current-user/email-addr current-user))))
I want to be able to "use" :session/error in another component, Component A. Component A isn't anything special. It is routable. Neither component is included all the way up to the root. I haven't tried that, yet. I can see in the inspector that the data I expect is indeed in the Session component. It's a singleton. I know it's ident. However, I can't figure out how to make use of it within Component A


So if I understand correctly your mutation is directly modifying Session and you wan't ComponentA to react on it(?). But I think you should turn it around. Your mutation needs to update the data in ComponentA's edge to Session and then ComponentA will get the updated properties and can pass it down to Session. At least that's how I've always done it. So your state map might look like

{:component/id ::ComponentA {:session-props {...}}}
But let me try something real quick


(It's my first fulcro project, so I'm still learning a lot)


I rather naively tried:

(defsc ComponentA
-  [this {:keys [component/id email/addr user/password] :as props}]
-  {:query [:component/id :email/addr :user/password form-state/form-config-join]
+  [this {:keys [component/id email/addr user/password sessions/session] :as props}]
+  {:query [:component/id :email/addr :user/password {:sessions/session (get-query Session)} form-state/form-config-join]
@@ -372,6 +372,7 @@
+                    (dom/h1 (:session/error session))


Appreciate the help @U012ADU90SW!


The state machine looks like:

(defstatemachine session-machine


     (merge session-events
              (fn [{:keys [::uism/app ::uism/state-map] :as env}]
                (if-let [error (get-in state-map [:component/id :session :session/error])]
                  (io/pprint {:session/error error}))
                (when (get-in state-map [:component/id :session :session/token])
                  (hist/route-to! routes/default-route))
              (fn [env]
                (io/pprint {:check-session-error env})


The Session component is the actor for session-token, and ComponentA is the actor for create-session


Ah yes, I'd swap the session state on :component/id ::ComponentA :sessions/session and then pass it along to to your session component


Sorry, I don't quite understand 😞


I'm just writing an example, hang in there


The Session component, I'm hoping, can just represent the session state, and not be required to render anything. While, ComponentA, for example, renders a signin form and triggers a remote mutation to create the session


Ah I missed that part, sorry. Yes it doesn't have to render anything. In that case you may want to look at the RAD demos auth system. It isn't fully fleshed out, but it's a start


I think you're trying to do exactly the same


> I think you're trying to do exactly the same Thanks. At least I know I'm not going off in some wildly ridiculous direction 🙂 I'll try attaching things to the Root component Thanks!


What's happening here is that the ui-authenticator on line #105 renders the login form for you. That's configured here: And as you can see you still need to include your session component somwhere in your UI tree and pass it the props. So the {:authenticator (comp/get-query Authenticator)} in the RAD demo is the "edge" I was speaking of earlier. Hope that helps a bit, sorry for having a slow brain today haha 🙂


> Hope that helps a bit, sorry for having a slow brain today haha I really appreciate you taking the time to help me with this! I'm not using RAD, but I'll look though these pointers to see what I can learn


Ah true, I forgot about this! I'm using it myself to pull in stuff like global options for dropdowns n stuff


The follow up is quite important: > This one bit me the first time


(defsc ComponentA
  [this {:keys [component/id email/addr user/password sessions/session] :as props}]
  {:query [:component/id :email/addr :user/password {[:sessions/session '_] (get-query Session)} form-state/form-config-join]


This is working


Nice, glad you figured it out!


Thanks again for your help, @U012ADU90SW!