This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-01-19
Channels
- # announcements (14)
- # babashka (16)
- # beginners (81)
- # calva (18)
- # chlorine-clover (8)
- # cider (4)
- # clj-kondo (11)
- # cljdoc (4)
- # cljsrn (5)
- # clojure (163)
- # clojure-europe (30)
- # clojure-nl (3)
- # clojure-spec (7)
- # clojure-uk (4)
- # cursive (3)
- # emacs (12)
- # events (1)
- # figwheel-main (3)
- # fulcro (60)
- # introduce-yourself (3)
- # jackdaw (12)
- # juxt (3)
- # lsp (77)
- # malli (23)
- # mid-cities-meetup (9)
- # music (2)
- # off-topic (12)
- # portal (6)
- # releases (2)
- # shadow-cljs (3)
- # spacemacs (7)
- # sql (1)
- # tools-deps (2)
- # vim (3)
Hello Fulcro lovers. I try to use https://github.com/necolas/react-native-web with Fulcro (without expo) but I have some trouble to register the app. I try this code:
(defn -mount-app []
(.registerComponent AppRegistry "App" (fn [] (mroot/floating-root-react-class entry/Root app)))
(let [root-component (interop/react-factory (.-element (.getApplication AppRegistry "App")))]
(app/mount! app (root-component nil) "app")))
I use .registerComponent
of react-native-web to register the main component. Internaly, react-native-web wrap this component with an internal component. The .getApplication
return an object with a key element
(whish is the react element). I miss something. I got this error on the console
Uncaught Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
Someone already tried to use this lib with Fulcro?I have no experience here but the same error happens in the browser. What exactly threw this error? React or Fulcro? And where, during mount! or earlier? Essentially somewhere you are passing something that should be turnable to a React element and thus needs to be a DOM element such as "div" or a class for a class-based component or a function for a pure, fn-based one. Do you need to go through the React interop factory here? You already have something that perhaps is a React element, the .-element thing. Can't your use it as is?
Hi @U0522TWDA, thanks to answer me. The error is threw by React during the mount!. Yes .-element
is a React element but this is a plain JS React element. If I remove the react-factory
I got the same error.
Makes sense actually since element is not class/fn
Forgetting all the React native stuff, if you have a plain React element - whether in native or Web - you should be able to mount it IMO. According to https://reactjs.org/docs/react-dom.html#render that seems indeed be the case. So I believe that is not render that is failing but something else. The key question is : what?!
I don't know if this is an acceptable code but it works:https://gist.github.com/jeans11/9f86af3d458b16d0e1f6851b3c67b906
Ah, I see, you are right. There must be a better way, but I don't know it.
Perhaps mount! is not really needed? Isn't the element returned by the getApplication
already mounted? If not, you could perhaps call instead ReactDOM.render (or its native alternative) directly instead of fulcro's mount? And run separately (app/set-root! app Root {:initialize-state? true})
? Not sure what is the expected interaction between native and Fulcro here...
No, the element returned by .getApplication isn't mounted. React Native Web offer a .renderApplication for mount the app but I wanted to use mount! fulcro function to correctly setup the mount.
Study its code to find out whether it actually does anything you need. I doubt it somehow, if you run set-root. But I'm just guessing...
I will do that. Thanks again @U0522TWDA
I keep using the mount! function with my hack code for the moment because I don't know what to use otherwise.
Much better version without the atom: https://gist.github.com/jeans11/5a7ea1541401b412db7de868ef4e1851
Nice!!! Though I think you miss ))
at the end of https://gist.github.com/jeans11/5a7ea1541401b412db7de868ef4e1851#file-core-cljs-L18 🙂
@U0CKQ19AQ Do you have experience with react native? Does ☝️ look good to you?
Hello guys! Re update the gist (https://gist.github.com/jeans11/5a7ea1541401b412db7de868ef4e1851) with the idea of @U0522TWDA . Don’t use the mount!
function of Fulcro. Just set the root component with set-root!
it works
@UHZPYLPU1 I would like to add the gist to https://fulcro-community.github.io/main/awesome-fulcro/README.html if it's ok for you - see https://github.com/fulcro-community/awesome-fulcro/pull/8/files
might also have to call install in that ns…don’t remember, but it isn’t tied to react or mount
Thanks for the advice @U0CKQ19AQ
because it only gets called once, but multiple apps can be on a page…each of those sends an app-started
Getting more adventurous with state machines - I like the idea of them being where the logic lives.. I'm playing with a pattern where I run multiple instances of the same machine on a page - multiple objects, each having its own copy of the machine I'm using uism/begin! app machine ident when ident is in the form [::session/session object-id] This is working well but I have hit a small problem I now want to be able to pull the state machine into a component and check it's active state In accordance with the guide, it suggests adding the state machine to the query of the component so that changes in the state machine trigger a re-render but.. how do I construct the query in the component if the ident is "dynamic" I'm using routing so the object-id is in the url and available in :will-enter, not sure if that's going to helpful here...??
You could do that with dynamic queries but simpler will be to fetch all state machines (with '_, as you do for load markers) and just look up the relevant one in there. The cons is that change to any uism will rerender all these components but likely you can afford that.
I want to implement navigation with two routers named RootRouter (DataList["c"], BigDetail["d" :data/id]) and TabRouter (Pic["pic" :data/id], Txt["txt" :data/id]). So if I want to see Txt of :data/id=2 item the path should be like: d/2/txt/2 I am working on this problem several days, and I am still unable to pass :data/id from BigDatil to Pic. Another problem is that will-enter is triggered 3 times on one click. https://github.com/janezj/fulcro/blob/tab-card/src/workspaces/com/fulcrologic/fulcro/cards/nested_dynamic_routing_tree_cards.cljs
I am not sure if passing the :data/id from one component to another is the correct way, From Datalist -> BigDetail it works,
Do you have the code on a public git repo? it's hard to understand what exactly you're asking for, as well as what you're trying to do.
It seems like you already have the fulcro repo locally - the router is a pretty simple state machine so you can add prints and inline defs to debug as well: https://github.com/fulcrologic/fulcro/blob/7c88b0966671382786e19ade95e9113b5d72ba2b/src/main/com/fulcrologic/fulcro/routing/dynamic_routing.cljc#L347 ready-handler and route-handler manipulate the state on change route
The will-enter
is triggered several times. In order to write side-effecting code, use route-deferred
and the completion function takes no arguments and should invoke target-ready
.
@U051V5LLP This is how I pass id from one parent route BigDetail to child Pic https://github.com/janezj/fulcro/blob/0bcdd435883b499f4d6fb0ceacdd6ad0be6839d7/src/workspaces/com/fulcrologic/fulcro/cards/nested_dynamic_routing_tree_cards.cljs#L163 Pic receives the param in will-enter, but it is not able to fetch the data from data/id table. But Pic and BigDetail are very very similar, I see the difference only in render fun
You forgot to do (comp/get-initial-state TabRouter)
in BigDetail
. Might cause a problem as well
Are you suggesting replacing :initial-state {:ui/router {}}
with :initial-state (fn [_] {:ui/router (comp/get-initial-state TabRouter)})
They are equivalent.
My bad, I didn't remember it's an empty map as well. I've implemented a lot of master/Detail views in fulcro and just looked at your code for a minute. It looked fine but this line stood out to me. I can try to run you code locally, haven't worked with workspaces yet though, so it might take a minute
@U012ADU90SW with calva is very simple:
[email protected]:janezj/fulcro.git
cd fulcro
git checkout tab-card
yarn install
jack-in .... select; shadow-cljs -> :workspacesI got the workspaces running. I just noticed that the TabRouter props aren't passed through to the BigDetail
component, I don't know why though yet. Have to take a closer look.
If you click on txt
or pic
and force a re-render, it'll switch to the correct tab
How do you force re-render? I noticed it shows correct tab when shadow-cljs remounts ui.
In Fulcro Inspect - DB there is a button for it, I think it is a circular arrow
Thanks, I didn't know that.
I tried with (app/schedule-render! SPA
it is probably the same but button is more convenient
> Pic receives the param in will-enter, but it is not able to fetch the data from data/id table.
Why/how is it not able to fetch the data? You can run something like db->tree
inside the dr/deferred-route callback to get it, no? But why do you need to fetch the data in will-enter? If you have them in query then fulcro will fetch them for you?
> But Pic and BigDetail are very very similar, I see the difference only in render fun
Then perhaps have a single component with (if <cond> (render-pic ..) (render-detail ...)
? Not sure whether it makes sense here just wanted to point out that you don't need separate components for everything, esp. if they have the same query and props.
So all your targets display different views of the same data entity, right? You don't really need routers for that (and I believe they were not designed for this use case - the main advantage of routers is avoiding fetching subtrees of data you don't need). You can more simply implement the same thing with a single component (or two) with a conditional. Instead of passing route params, you can simply set a well-known places in the DB such as :ui/selected-item [:data/id 123]
+ :ui/current-view {:left :Pic, :right :BigDetail}
at the root. And you could even sync that with the URL using custom code (if you don't care about user friendliness then adding ?state=<base64-encoded transit or edn>
is a simple way.
You can still do it with routers I believe but want to open your mind to other possibilities.
There are going to me much more tabs/components And i want to load the requred data on will-enter
Every tab will have some other data, imagine for exampke youtube video with id, on every tab, I will have details about video, (comments), technical propertis, tools to share, .... . But all sharing just id.
> But component is not able to fetch the data,
You mean it runs df/load!
but it fails or what?
> i want to load the requred data on will-enter
well, you could instead load them in onClick, just before "routing" to the component/view. So I think it is still valid approach but if you want routers then routers be it! 🙂
I am afraid you are asking for troubles since both BigDetail
and its grandchildren Pic
, Txt
use the same ident. Perhaps it is messing up already now. But certainly after you switch over to deferred routing - then both BigDetail's and Pic's will-enter is eventually expected to transact (dr/route-ready [:data/id 2]
So how should Fulcro know which of the two targets it is that is ready if both have the same ID? I might be wrong but I suspect strongly this will mess up.
Now I I route in the card to D.pic and look at the data in F.Inspect - DB Explorer, I can go from root at :root/router -> [::dr/id ::RootRouter] - :current-route -> [:data/id 2]
- which contains various :data/* props but no :ui/router
as BigDetail expects so here is your disconnect.
From (comp/get-initial-state Root)
I see the initial state has no :data/id
data. I see the data is added by the merge/merge-component!
So I have to point you to the pre-merge info here https://fulcro-community.github.io/guides/tutorial-advanced-minimalist-fulcro/#_a_router_inside_a_newly_loaded_component
For some deeper understanding it is valuable to study https://blog.jakubholy.net/2020/fulcro-divergent-ui-data/#_inserting_a_stateful_ui_component_between_a_parent_child_entities
BTW https://github.com/holyjak/fulcro-troubleshooting might have warned you about the missing connection
Also under https://blog.jakubholy.net/2020/troubleshooting-fulcro/#_backend_pathom there is the (obviously misplaced) useful point 2.a.i.B
> both `BigDetail` and its grandchildren `Pic` , `Txt` use the same ident. If I understand you correctly: in the hierarchy of routers there must be no duplicated [:data/id x] pairs. target-ready will fail. I agree, I was lookung for trouble. > From `(comp/get-initial-state Root)` I see the initial state has no `:data/id` data. I don't see it as an error, ids of data items are loaded from database in my real app I am using load! This just like example in the book - PeopleList
As I understand routing: "targets" in router are not linked to the root. ident in target is just table pointer to query data from.
Routers do no break with basic principles. So targets must be connected to the root (though your problem is that the component containing the router lacked connection to the router data, not anything with targets? )