omcljs / om

ClojureScript interface to Facebook's React
6.66k stars 362 forks source link

No queries exist for component path #895

Open roti opened 6 years ago

roti commented 6 years ago

The code below throws "No queries exist for component path (om-tutorial.core/RootView om-tutorial.core/Counter)" when clicking on the button.

To me it's quite strange that this is happening, since this is a very simple case, so maybe I'm doing something wrong, but if that's the case I couldn't figure out what.

Error occurs here.

(ns om-tutorial.core
  (:require [goog.dom :as gdom]
            [om.next :as om :refer-macros [defui]]
            [om.dom :as dom]))

(def app-state (atom {:page :counter
                      :count 0  }))

(defn read [{:keys [state] :as env} key params]
  (let [st @state]
    (if-let [[_ value] (find st key)]
      {:value value}
      {:value :not-found})))

(defn mutate [{:keys [state] :as env} key params]
  (if (= 'increment key)
    {:value {:keys [:count]}
     :action #(swap! state update-in [:count] inc)}
    {:value :not-found}))

(defui Counter
  static om/IQuery
  (query [this]
    [:count])
  Object
  (render [this]
    (let [{:keys [count]} (om/props this)]
      (dom/div nil
               (dom/span nil (str "Count: " count))
               (dom/button
                 #js {:onClick #(om/transact! this '[(increment)])}
                 "Click me!")))))

(def counter (om/factory Counter))

(defui RootView
  static om/IQuery
  (query [this]
    [:count :page])
  Object
  (render [this]
    (let [props (om/props this)]
      (dom/div nil
               (counter (om/props this))))))

(def reconciler
  (om/reconciler
    {:state app-state
     :parser (om/parser {:read read :mutate mutate})}))

(om/add-root! reconciler
              RootView (gdom/getElement "app"))

:class-path->query apparently does not contain the expected path:

dev:om-tutorial.core=> @(om/get-indexer reconciler) 
{:class->components
 {om-tutorial.core/RootView #{#object[om-tutorial.core.RootView]},
  om-tutorial.core/Counter #{#object[om-tutorial.core.Counter]}},
 :data-path->components
 {[]
  #{#object[om-tutorial.core.RootView]
    #object[om-tutorial.core.Counter]}},
 :ref->components {},
 :prop->classes
 {:count #{om-tutorial.core/RootView},
  :page #{om-tutorial.core/RootView}},
 :class-path->query
 {[om-tutorial.core/RootView] #{[[:count :page] nil]}}}

I tested on beta1 and the latest snapshot.

decoursin commented 6 years ago

Your RootView query, I believe, has to explicity reference the Counter query with get-query. So, I think, it should be like this then:

(defui RootView
  static om/IQuery
  (query [this]
    [:page (om/get-query Counter])
  Object
  (render [this]
    (let [props (om/props this)]
      (dom/div nil
               (counter (om/props this))))))

then it should work

seltzer1717 commented 6 years ago

I don't think there is an issue with your query construction. Can you provide your project.clj dependency list?

roti commented 6 years ago

Here it is. It's basically the one from the figwheel template with om added as dependency.

In case this is helpful, with an older om version (1.0.0-alpha46) I get a different error, but the transact! action is executed. Invariant Violation: transact! should be called on a componentthat implements IQuery or has a parent thatimplements IQuery

(defproject omtest "0.1.0-SNAPSHOT"
  :description "FIXME: write this!"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}

  :min-lein-version "2.7.1"

  :dependencies [[org.clojure/clojure "1.9.0-beta4"]
                 [org.clojure/clojurescript "1.9.946"]
                 [org.clojure/core.async  "0.3.443"]
                 [org.omcljs/om "1.0.0-beta1"]]

  :plugins [[lein-figwheel "0.5.14"]
            [lein-cljsbuild "1.1.7" :exclusions [[org.clojure/clojure]]]]

  :source-paths ["src"]

  :cljsbuild {:builds
              [{:id "dev"
                :source-paths ["src"]

                ;; The presence of a :figwheel configuration here
                ;; will cause figwheel to inject the figwheel client
                ;; into your build
                :figwheel {:on-jsload "omtest.core/on-js-reload"
                           ;; :open-urls will pop open your application
                           ;; in the default browser once Figwheel has
                           ;; started and compiled your application.
                           ;; Comment this out once it no longer serves you.
                           :open-urls ["http://localhost:3449/index.html"]}

                :compiler {:main omtest.core
                           :asset-path "js/compiled/out"
                           :output-to "resources/public/js/compiled/omtest.js"
                           :output-dir "resources/public/js/compiled/out"
                           :source-map-timestamp true
                           ;; To console.log CLJS data-structures make sure you enable devtools in Chrome
                           ;; https://github.com/binaryage/cljs-devtools
                           :preloads [devtools.preload]}}
               ;; This next build is a compressed minified build for
               ;; production. You can build this with:
               ;; lein cljsbuild once min
               {:id "min"
                :source-paths ["src"]
                :compiler {:output-to "resources/public/js/compiled/omtest.js"
                           :main omtest.core
                           :optimizations :advanced
                           :pretty-print false}}]}

  :figwheel {;; :http-server-root "public" ;; default and assumes "resources"
             ;; :server-port 3449 ;; default
             ;; :server-ip "127.0.0.1"

             :css-dirs ["resources/public/css"] ;; watch and update CSS

             ;; Start an nREPL server into the running figwheel process
             ;; :nrepl-port 7888

             ;; Server Ring Handler (optional)
             ;; if you want to embed a ring handler into the figwheel http-kit
             ;; server, this is for simple ring servers, if this

             ;; doesn't work for you just run your own server :) (see lein-ring)

             ;; :ring-handler hello_world.server/handler

             ;; To be able to open files in your editor from the heads up display
             ;; you will need to put a script on your path.
             ;; that script will have to take a file path and a line number
             ;; ie. in  ~/bin/myfile-opener
             ;; #! /bin/sh
             ;; emacsclient -n +$2 $1
             ;;
             ;; :open-file-command "myfile-opener"

             ;; if you are using emacsclient you can just use
             ;; :open-file-command "emacsclient"

             ;; if you want to disable the REPL
             ;; :repl false

             ;; to configure a different figwheel logfile path
             ;; :server-logfile "tmp/logs/figwheel-logfile.log"

             ;; to pipe all the output to the repl
             ;; :server-logfile false
             }

  ;; Setting up nREPL for Figwheel and ClojureScript dev
  ;; Please see:
  ;; https://github.com/bhauman/lein-figwheel/wiki/Using-the-Figwheel-REPL-within-NRepl
  :profiles {:dev {:dependencies [[binaryage/devtools "0.9.4"]
                                  [figwheel-sidecar "0.5.14"]
                                  [com.cemerick/piggieback "0.2.2"]]
                   ;; need to add dev source path here to get user.clj loaded
                   :source-paths ["src" "dev"]
                   ;; for CIDER
                   ;; :plugins [[cider/cider-nrepl "0.12.0"]]
                   :repl-options {:nrepl-middleware [cemerick.piggieback/wrap-cljs-repl]}
                   ;; need to add the compliled assets to the :clean-targets
                   :clean-targets ^{:protect false} ["resources/public/js/compiled"
                                                     :target-path]}})
roti commented 6 years ago

I tried to explicity reference the Counter query in RootView. Doesn't work.