fulcro

Book: http://book.fulcrologic.com, Community Resources: https://fulcro-community.github.io/, RAD book at http://book.fulcrologic.com/RAD.html
Mr. Savy 2020-12-26T03:47:49.335500Z

I make some component X with some param represented as Y. In X's body I have a ui factory that I pass Y into so I can build the data. In general, I would suspect that if Y is null when it's not supposed to be, the cause would be either that its parent isn't calling it right, or the query is incorrect.

tony.kay 2020-12-26T18:05:04.336500Z

I suspect you’re mental model of Fulcro isn’t complete. A lot of people think Fulcro does more “Magic” for you than it does. The steps are literally: On mount: a. It pulls your initial-state tree (which is a literal representation of your view tree data). b. Uses your query, which has the exact same shape as initial-state, to normalize that tree (there are a few more steps, but that’s basically it). c. It then denormalizes that tree via the same query…it literally uses your query, from root to get the props tree. Nearly the exact opposite of (b). d. It calls render and passes that tree of data to your root component. That’s it. On each transaction there is a lot of interesting full-stack stuff going on in terms of making your life more sane (serial processing by default, writes prioritized over reads etc etc), BUT when a transaction has modified the database, Fulcro: a. Gets your root query (which can be dynamic, but usually isn’t) b. Uses that query + db to get UI data tree c. Passes it to root render. Which is very similar to what it does on mount. That is again, it. Rinse, repeat. If you use an alt renderer like ident-optimized or multi-root, then there are some extra features. So you see the model is very very simple: Db change -> denormalize using Root query + db -> Render root -> Loop Don’t confuse yourself thinking there’s this magic part of the query or this magic part of the subtree rendering, or that all sorts of weird side-magic is going on, etc. The mental model is: There is a UI tree, there is a data tree. They must match. The render is a visual reification of the data tree using your render. The query engine in 99% of apps is doing nothing more than following and idents (the main complications are recursion, dynamic queries, wildcards, and unions, which many apps do not even use, and are really nothing very complicated). To get Fulcro “right”, 90% of the time, is to get the shape of your data graph to match the shape of the query (which initial state makes trivial), and then keep it that way (which is up to your application’s logic). load is exactly the initial state+query mechanism, on some sub-graph. You’re making a new part of the tree match some UI that you are about to show.

❤️ 2
Mr. Savy 2020-12-26T19:19:24.336700Z

yeah I've struggled at grasping the data pattern for some time, at least when it comes to troubleshooting. stuff like this helps though, so thanks for taking the time to write it! I wish there was an faq page or something with explanations like these. I suspect there's a lot problem/solution/insight topics that get lost in the archives here which might help connect some of the dots.

tony.kay 2020-12-26T21:22:59.342300Z

The chapter I just revived in the book (3) might help. But I agree, some more docs never hurt

👍 1
JAtkins 2020-12-28T16:13:02.367Z

@ajsnow2012 I'm (slowly) grabbing them and putting them on this doc. https://roamresearch.com#/app/CommunityFulcro/page/12-26-2020

👍 1
Mr. Savy 2020-12-26T03:51:21.335600Z

if it's not that the function is being called wrong, and if it happens when loading in data, I would then want to test it against static data.

Gleb Posobin 2020-12-26T19:32:02.338100Z

Is there a way to make a catch-all route in the dynamic router? Say I want to have routes /main /settings and /:username, not /user/:username.

Gleb Posobin 2020-12-26T19:34:02.338800Z

And how do you handle parameters in URL, like /:username?all-posts=true ?

tony.kay 2020-12-27T17:31:07.349Z

The curse of too much documentation. I could easily add 100+ pages to the book covering these kinds of little details that are in docstrings.

👍 1
Jakub Holý 2020-12-26T19:36:13.339100Z

Look at the docstring of the route fn, it takes extra params. Or/and look at how RAD reports use it

Jakub Holý 2020-12-26T19:36:58.339300Z

I suspect that might be a problem.

Jakub Holý 2020-12-26T19:37:37.339500Z

I'd look into the function doing the target selection based on the route

Gleb Posobin 2020-12-26T19:46:25.339700Z

I have tried adding the catch-all in the end of the defrouter's routes vector, this didn't work (all routes were going to the catch-all then), but it works if I add it at the front.

Gleb Posobin 2020-12-26T19:47:16.339900Z

So just add the catch-all as the first route in the router, seems like it tries routes from the end.

Gleb Posobin 2020-12-26T20:28:56.341500Z

Is the only way to get the route params of the current route in a component is to receive them in the :will-enter function, and return a deferred mutation/load with those params? I am trying to understand how the person/id prop gets passed into the person component in the router example in the book: https://book.fulcrologic.com/#DynamicRouter Is it because the :person/id key is both in the query and the route-segment, it gets exctracted form the route segment and put into the props?

Gleb Posobin 2020-12-29T06:09:31.375800Z

What about the first page load? I am not using SSR.

Gleb Posobin 2020-12-29T06:11:14.376Z

I can live with the delay between when the component is rendered and when it learns its route params, just curious.

Gleb Posobin 2020-12-29T06:13:01.376200Z

Hmm, though not sure why the component gets rendered before the path param is loaded if I call dr/target-ready in the mutation after the swap! on state that adds the param.

tony.kay 2020-12-29T07:12:23.377100Z

so, the ideal pattern for a production-ready first page load, IMO, is to have the html render something that shows a loader. The app loads with a flag that is false in initial state (:ui/ready? for example). The rendering when that flag is false is exactly what is already in the app div the HTML generated. So, the user doesn’t really see the transition from static HTML to running app. You do your initialization, route, and then some aspect of your final initialization (which might be route-deferred) changes the flag to true. Now your app renders, and you’re right where you want to be. You are making a frame-by-frame animation via state. Fulcro does not know what you want to show when. It just renders each frame as it happens. You’re ultimately in control of what renders. Dynamic routing has a central set of concerns: composable UI switches that let you have some control over what happens as things come and go from the screen. Nothing’s perfect, and there are certainly imperfections in D.R. I initially wrote that because ppl were complaining they didn’t know how to go about making a ui router, and so I built that as an example, but it was good enough that I released it. It’s since gone through some revision, but it still isn’t ideal in every way. Fulcro’s rendering, as I’ve said at least 3x this week alone, is very very naive: mutation -> render -> mutation -> render. Component’s don’t have much control over when they render, only what. The state machines behind D.R. essentially run mutations to move from state to state, meaning that some (unintentional) frames of state might be rendered…this is where some refinement in the internals would be nice. That said, my expectation is that if you return a route-deferred then that route will not be visible until you say target-ready. The route params are passed in before you can even say route-deferred, so I honestly don’t know what you’re talking about, unless I’m misunderstanding you’re description, or your code doesn’t match your description.

2020-12-29T09:24:02.377300Z

Stepping through state transitions with fulcro inspect can be a good way to gain insight into what is happening in your app.

Gleb Posobin 2020-12-26T20:29:57.341600Z

You mean dr/change-route!?

✅ 1
Gleb Posobin 2020-12-26T20:30:22.341800Z

(it is in the docstring there and solves the problem, thank you, just making sure)

tony.kay 2020-12-26T21:25:17.342500Z

DR has no concept of URLs. Query parameters can be augmented, and can be placed in vector of strings. DR is not tied to the web. It works for native, electron, or whatever other target you might want. HTML5 “interpretation” is up to you

👍 1
tony.kay 2020-12-26T21:25:36.342700Z

When you change routes you can put anything in the route params to pass through

Jakub Holý 2020-12-26T22:41:19.343100Z

The first one is the default, used I suppose when nothing else matches. Surest is to read the code.

2020-12-26T23:04:09.344500Z

After quite an extended break, I published another post in my gift list series detailing how to deploy a fulcro app using dokku: https://chrisodonnell.dev/posts/giftlist/deployment/. Always happy to hear any feedback.

👍 5
Jakub Holý 2020-12-27T19:39:12.349400Z

Care to send a PR to add it to https://github.com/holyjak/awesome-fulcro?

🤘 1
2020-12-27T20:40:45.349700Z

Yeah sure

❤️ 1
2020-12-26T23:14:05.344700Z

I believe the dr/target-ready mutation sets its ident.

2020-12-26T23:17:13.344900Z

And dr/route-deferred, too, I guess.

2020-12-26T23:21:51.345100Z

There's some explanation in this section: https://book.fulcrologic.com/#_deferred_routing