Fork me on GitHub

Is the idea of having a user.cljs file with a dump command in it (that does @(prim/app-state (-> app deref :reconciler))) not considered necessary anymore? lein new fulcro app shadow-cljs doesn't generate a user.cljs file, which is where I was hoping to find it. If Fulcro Inspect allowed me to copy out a data structure then I wouldn't need it.


@cjmurphy with Inspect, why would you?


@tony.kay I have tests (just Clojure tests because what is tested is .cljc) of functions that create hiccup. The functions that create hiccup require the props of some component. So it would be good to just look at the state in Fulcro Inspect and copy the contents of say a link, so that it can be used as input to a particular test.


But dump does exactly what I need, so no real reason to be using Fulcro Inspect for this.


that’s fine…so you have a use for it. I’m trying to encourage use of Inspect. There is no user.cljs in shadow because it isn’t really needed in general. You can use the preloads for such functions, since that won’t get loaded in prod




What's the context for development-preloads.cljs. Which project? Is it from Shadow? Fulcro Inspect source code?


just a file in the generated project when using shadow


look in shadow-cljs.edn in your generated project


under :devtools


So will serve exactly same purpose as user.cljs, and I can write a dump function in it?


There will be a preload entry for a file there called that. Yes, you can put any kind of dev stuff in there


then just switch to that ns at the REPL and off you go


Okay thanks Tony.


I find that most of my query attributes are client side only attributes and when building components prefer to use autonamespaced keys. Any recommendation on how I might strip these from remote queries?


ah! guessing :read-local


@cjmurphy @tony.kay shadow-cljs actually supports a cljs/user.cljs. no idea why CLJS picked user.cljs when it basically disallows other single-segment namespaces. but yes using :preloads is a better option since cljs/user.cljs is global and not per-build.


you may also set :devtools {:repl-init-ns your.util} in your build config as well to switch the default from cljs.user (might make sense to have generic fulcro.repl ns?)


So calling x-1 (my little test function) works fine. So I've got what I needed. Going straight in to general.user (rather than cljs.user) does not seem to work for me. (But not too important).


[1:1]~general.user=> (x-1)


So the above is what I might have expected to work.


it should work like that? it does on my machine?


which version are you on? forgot which version I added this in. might have been 2.2.x


Not on mine. I have npx shadow-cljs watch main in one terminal and rlwrap npx shadow-cljs cljs-repl main in another.


How do I know which version again?


its printed on startup in the watch


it was added in 2.3.21 😉


I restarted them both and reloaded the page. Okay will upgrade 🙂


To upgrade I change package.json to have "shadow-cljs": "^2.4.16" then run npm install. Unfortunately I get a few errors that look like:

npm ERR! write after end


I assume that's my poor Internet connection.


never seen that but google found this


Apparently sudo npm i -g [email protected] fixes the problem, so trying that now...


Upgrading worked fine, but still :repl-init-ns does not work for me. But not that important really...


do you use lein? then updating the npm package doesn't change the actual shadow-cljs version. need to update in project.clj (or deps.edn if you use that)


Yes use lein, and didn't update in project.clj. But when doing that and then running watch I get:

ARNING: failed to handle server msg: {:type :start-autobuild}


invalid clojurescript version. requires 1.10.335 currently.


or rather invalid closure-compiler version but that most likely comes from clojurescript


All good now thanks, meaning REPL cmd prompt looks like: [1:1]~general.user=>.


What's the query to pull an entire table's contents? I've tried [:items/by-id _] which does pull the table but it's denormalised; applying the right query seems to return an empty map: {[:items/by-id _] (prim/get-query Item)}


You mean “normalized” I think. The former. The latter would be a query to pull it if they were in a vector…which they are not. The link ident points to the whole table (which itself is a map). There is no way to query for the table in a denormalized form. What is your use-case? If you really need all of the items in a to-many relation that is queryable, then you need to place a list of idents in state somewhere that points to them all…that will also establish the proper order for them to be returned.


e.g. if you put a root key like :items/sorted-by-name [[:item/by-id 1] [:item/by-id 23] ...] then the root link join you have above will work, becuase then you actually have a join..


ideally, you place such a join within the component that is interested in the link, though, so you don’t have to use the root node. The table is just meant to be a table. Sometimes you need access to it, but more often than not you should really be doing these manipulations in mutations that build the graph you want to see.


Thanks @tony.kay, I did mean normalised. My use case is just to show a listing of all known items, but in a summary view, not the main item view. There'll only be about 15-20 items so I don't need to paginate or lazy-load them from the server, just query the server for the sequence of item summaries. The summary is a subset of the full item's data, so the summary and full item share the same ident


Every time you update your table, do a postmutation to update your summary view's list of idents. Or, before showing your summary view, run the mutation to grab all the idents.


Right…as oscar says: It’s just a mutation. Create a vector of idents and drop them in your summary view. This means you can sort them, etc. Now your summary view has the correct (and locally queryable) items, in the correct order. Applying filtering (or aggregation) is also done in this step. I consider it just part of “routing to thta screen”. There’s the “change to the screen” part, and the “make sure the data on the screen is up-todate”. Classic Om Next would’ve had you write a parser for the component’s query, so you could do the work in the query…but that disconnects the logic of “what goes into the data layout of the screen” in a way that is hard to trace. That said, it has the advantage of being up to date “on query”. To me it is much simpler to “update the screen’s content” on entry to that screen, and skip the disconnected parser logic. That said, Fulcro would let you write all of that parser logic if you really want to…you can define the read parser for the client….but I’m guessing you’d pretty quickly come back to doing it the suggested way 😉


Thanks guys! I'll do that (the vector of idents updated while routing).


I feel like I'm missing something obvious... also, if you had two tables indexed by id and wanted to pull both, wouldn't the above formula mean you'd have two properties with the same name, by-id? I'd like to rename the property all-items or something similar


@uwo in Fulcro you can use the ui namespace for local only things, those will be automatically stripped from the query sent to the remote, eg: :ui/input-value


right, I know the ui namespace is stripped. I was just wondering what the best approach would be to strip other keys, since most of the widgets we have used autonamespaced keys to make it clear which widget their related to. I’m guessing the only way is to do some handling in the client parser with :read-local, no?


@uwo its fine to keep components with autonamespaced keys, in these cases I suggest you try making the join for those components a :ui/something key, this way all the component things will be stripped, like: [{:ui/my-ui-thing (prim/get-query UiComponent)}]


@liesbeth thanks for the report, I think this can also happens if you have the devtools open, and the extension is upgraded in the middle of the process, or maybe something broke the background process which might screw the communication entirely. the first think I'll suggest you try if that happens again is to restart Chrome, this will reset the background and probably get it back. That said please let me know if it happens frequently, I personally never had that but I can see some ways in which it can happen, so reports are welcome