2015-10-28 3 views
3

Я пытаюсь попасть в ClojureScript и Om. Есть конкретный случай, который заставляет меня бегать по кругу.Установить начальное состояние для отсутствующего ключа в данных компонента

У меня есть компонент, который сначала отображается без ключа.

(defn model-view [data owner] 
    (reify 
    om/IWillMount 
    (will-mount [_] 
     (om/transact! data [:stats] (fn [] {})) 
     (go 
     (let [response ((<! (api/get-stats (data :id))) :body) 
       stats (:stats response)] 
      (om/update! data [:stats] stats)))) 
    om/IRender 
    (render [_] 
     (dom/div nil 
       (dom/h3 nil (data :title)) 
       ;; Here I want to use the :stats key in data that I 
       ;; queried for in IWillMount, but its not present 
       ;; the first time this model is rendered. It's only present 
       ;; AFTER IWillMount has ran. 
       (om/build model-stats-view (data :stats))))) 

В первый раз этот компонент называется, ключ :stats просто нет в data. Вот почему я делаю вызов API, чтобы получить его статистику. Но React по-прежнему вызывает функцию render, поэтому компонент падает.

Как я могу установить начальное состояние в этом компоненте, который дает data пустой карту под названием :stats, предотвращая тем самым пытаясь оказать nil в (om/build model-stats-view) вызова?

+1

Вы можете просто использовать '(получить данные: stats {})'? – cfrick

+0

@cfrick Это работает. Благодарю. Но я оставлю это, чтобы узнать, есть ли более «Реакт-подобное» решение с 'IInitState' или что-то в этом роде. – tolgap

ответ

1

Я предпочитаю выполнять всю свою инициализацию в исходном состоянии, а затем получить доступ к ней в режиме рендеринга. И я поставил контур в моем стиле. Когда вы обновляете свое состояние init (например, e-map) в цикле go, оно заставляет вызов визуализировать/повторять рендер компонента. Я использую это во всех моих компонентах для межкомпонентной/внутрикомпонентной передачи сообщений. Просто нажмите что-нибудь в паб/подканал, и мы отправимся на гонки.

;To update my state I use a function: 

(defn set-owner-state! [owner old-map-key old-map new-map] 
    (om/set-state! owner {old-map-key (merge old-map new-map)})) 

om/IInitState 
(init-state [_] 
    (println "queue->init-state") 
    {:e-map {:active-fsm nil}}) 

om/IDidMount 
(did-mount [_] 
    (go-loop [] 
     (let [[v _] (alts! [server-fsm-events dispatcher-events]) 
       current-state (om/get-state owner) 
       e-map (:e-map current-state)] 
     ; what goes in here is the logic to respond to a message 
     ; in my case I have a match, it could be a cond or a set of 
     ; if's. 
     (set-owner-state! owner :e-map e-map {:active-fsm :active :task-paths nil}) 
    ... 

om/IRenderState 
(render-state [_ {:keys [e-map]}] 
    (println "e-map:" e-map) 
    ... 
+0

Ваше текстовое объяснение довольно хорошее, это заставило меня выяснить, что я делаю неправильно. Но ваш пример кода слишком расплывчатый. Я отвечу на ваш ответ, но надеюсь, что ваш пример кода действительно покажет, как вы «изменяете: e-map here». – tolgap

Смежные вопросы