1

I would like to do something similar to Reagent form-3 components, which enable me to define some shared (static) vars to use in lifecycle functions.

Basically my question is how do I construct something equivalent to the let in the Reagent code snippet below? I can't seem to figure out how to do this properly using Om's defui macro.

A simple example would be to generate an internal id I can access in all lifecycle functions of a specific instance of my component via gdom/getElement.

(defn my-component
  [x y z]  
  (let [id (gensym "my-component-")]  ;; <-- how to do this in Om?
     (reagent/create-class                 
       {:component-did-mount (...)
        :component-will-mount (...)          
        :reagent-render
         (fn [x y z] (js/console.log id)))) ;; <-- id is available
Marc Claesen
  • 16,778
  • 6
  • 27
  • 62

2 Answers2

1

You can use om.next/set-state!, om.next/update-state! and om.next/get-state to write to, alter and read from component local state.

However component local state is the poor cousin to app state. To use app state give your defui component an ident and simply make up a keyword that is part of the component's query. Then setup read and mutate multimethods that dispatch on the keyword you have invented.

As a side note - if you are using Fulcro rather than Om Next you won't need the read multimethod.

Chris Murphy
  • 6,411
  • 1
  • 24
  • 42
  • I probably used the wrong terminology, but I'm not looking for a way to modify the component's state. I want to parametrize components once upon instantiation. Om's state-related functions will trigger rerenders etc., which is not what I want. In the Reagent example in OP, every instantiation of `my-component` will have a different `id`, but that `id` will be available in all lifecycle functions of each instantiation. Putting these things in app state seems like major overkill for what I'm trying to do, but maybe I am not entirely in the right mindset yet ... – Marc Claesen Nov 08 '17 at 14:35
  • Are you saying that some lifecycle functions won't have access to component local state? Another option I didn't mention is a convenient global part of state known as a 'link', that is not related to any particular component, but can be easily accessed from all. Anything that is queried will trigger a render (including these links), however that is academic really. – Chris Murphy Nov 08 '17 at 14:50
  • Thanks a lot for your input, you've helped me find the solution! – Marc Claesen Nov 09 '17 at 07:26
0

After a while of digging I found the solution to be a combination of using react's initLocalState lifecycle method and om.next/get-state as hinted to in Chris' answer.

The general outline becomes as follows:

(defui MyComponent
    Object
    (initLocalState [this] {:id (gensym "") ...}) ; <-- the key
    (render [this]
     (let [id (om/get-state this :id)] ...))
    (componentDidmount [this]
     (let [id (om/get-state this :id)] ...))
    ...

This approach is more verbose than in Reagent, but I'm fine with that, as it provides equivalent functionality. I use this all the time, so am a little surprised I couldn't find any discussion about this elsewhere.

Marc Claesen
  • 16,778
  • 6
  • 27
  • 62