Vanilla-FP: A no-framework framework for component-based purely-functional UIs
github.com
github.com
I always find that if I want to write an app in the Elm style (or with Redux), I have to traverse up the tree every time I am working on a leaf node. Each input field in a form should not necessarily cause me to have to rework everything up to the root node right? Am I doing it wrong, or am I just missing what benefits this approach brings to offset this extra development cost?
The root node can intercept all messages but its main responsibility (TEA) is to dispatch the messages to the right component(s).
(Each component consists of a view, a model and an update function, the model contains wrapped versions of the children models and dispatched updates get passed into the children updates)
Classic example: if you have a notification bubble near the top of the page, and a notification gets created by some component hidden deep inside the app structure, that message can't be handled in a local sub-model; it must travel all the way to the root node to update the notification bubble stack in the main model.
(Which is why nowadays I prefer to skip the nesting and just have a flat list of all messages in the app. With good spacing and naming, it's quite maintainable and just as solid.)
F(f_1(x_1), f_2(x_2), …, f_n(x_n))
The root function is a collection of projections acting on (x_1, x_2, …).
And the components receive the right set of coordinates to act on.
I’m not sure if it’s clearer that way though.
And no, you don't need to to prop drilling when using contexts or a state manager.
the issue is that current frameworks make global state awkward to pass around. if this were fixed then global has all of the advantages.
In Elm specifically, you should not have state in the form elements. They should only have component-specific update functions like "Checked" / "Unchecked" that are mapped to form level messages and of course the view function.
Especially for server-centric CRUD apps with forms and lists, this is often abused. If you're reloading lists when navigating to them, and fetching form data when updating a record, then you don't really need global state. If you want to cache, perhaps a plain cache is enough.
If you need some piece of data to affect multiple components in different parts of the hierarchy, sure, make it global, but if you can get away with mostly local state the codebase will be simplified. IMO.
There's zero need to make everything be the same. There's not even the need to keep state in one single place: you can control all the state and its transitions locally but then "copy" to state management if you need it somewhere else. This is a perfectly valid solution too.
Another problem of using global state for everything is that it reduces the possibility of using a lot of component-level or hook-level abstractions that would be otherwise very useful. You're now forced to do everything through Redux or something like that.
There's no need to rush for an "absolute" solution with all that overhead as if it was a golden bullet. It's not.
I agree that this project misses the mark.
Anyways, the tide turned again and everyone said, "functional programming is the bees knees! [don't mind these strange hooks that inject side-effects and state]". Then they said, why are we storing state in these pure functional entities. Let's separate out the state and the control..
Back to model-view-controller. Yay?
It would be so nice to just have a way to specify which part of the markup is owned by which component, and the basic life cycle events they need to agree on to work together, but then allow the internal considerations of each component to be handled by any framework or even plain JS if you prefer.
I’ve described it as a “programming language for designers”. The idea is to allow designers to specify the graphical layer of apps, without specifying any behavior.
The core language itself is platform-agnostic, with platform-specific dialects. So you could use it to spec out a web/iOS/android/etc app.
And the cool thing about it is that it compiles to an intermediate representation, which will be a JSON data structure. So you could use it to generate a React component library, or Vue, or Angular, or web components, etc etc.
1. Change the "div" "span" etc. to be just "createElement('div'..."
2. At the "render" function, do "reactDOM.render" instead of "replaceChildren"
Really, how is this different from a top-level useState call, that then gets passed down via props drilldown to children components? The repo mentions that the "heart" is not a code but a convention, but you can do the same convention in React. In fact I believe you can do much better with context - prop drilldown absolutely sucks when the complexity of your component tree grows.
Am I missing something?
As far as "prop drilling" goes, I never understood what is the problem that some people have with it.
If you just put your state in one object its just one more param that you have to pass to components. Do we really need a big-ass framework just because of one extra param.
Also, by passing state explicitly, you get a clear visibility over which component needs what. And it also allows you to restrict which component uses which parts of the state.
React is not "just one extra param". One thing it does and your "no-framework framework" does not is figuring out what needs to be updated when the state changes. Add some console.log statements to your components and you'll see that clicking on any button on the demo page results in all components being updated, causing update of DOM nodes. How can this possible work in a complex web page? I click on the "Close Modal" button, and every single DOM node on the page gets updated, from the menu bar down to each and every button?
That's the very basic thing that React does. I am not talking about anything else, like component lifecycle or hooks. This not-framework doesn't even begin to approach what React does. If you don't want the "big-ass framework" for whatever reason, there are Inferno and Preact already. Both are great projects and have all the things a developer expects from React replacement.
I think the point is a "no-state handling framework". It seems like you can combine this with something like morphdom to get React-like merging for pure DOM updates, and the state-handling is via this hierarchical approach. Or your DOM construction can be via a vDOM library which then handles the merges for you.
Nope. I've got nothing. "Functional" something?
Anyone?
I guess acronyms should be considered bad in general?
Consider this, you have a slider input, and oninput, you update the state, which creates a new slider input, which causes your mouse drag to get invalidated.
Another consideration - a textarea where you update state each keystroke; will that reset the cursor or have unintended consequences?