GitHub - abuseofnotation/vanilla-fp: The no-framework framework for building component-based purely-functional UIs. · GitHub
/" data-turbo-transient="true" />
Skip to content
Search or jump to...
Search code, repositories, users, issues, pull requests...
-->
Search
Clear
Search syntax tips
Provide feedback
--><br>We read every piece of feedback, and take your input very seriously.
Include my email address so I can be contacted
Cancel
Submit feedback
Saved searches
Use saved searches to filter your results more quickly
-->
Name
Query
To see all available qualifiers, see our documentation.
Cancel
Create saved search
Sign in
/;ref_cta:Sign up;ref_loc:header logged out"}"<br>Sign up
Appearance settings
Resetting focus
You signed in with another tab or window. Reload to refresh your session.<br>You signed out in another tab or window. Reload to refresh your session.<br>You switched accounts on another tab or window. Reload to refresh your session.
Dismiss alert
{{ message }}
abuseofnotation
vanilla-fp
Public
Notifications<br>You must be signed in to change notification settings
Fork
Star<br>124
main
BranchesTags
Go to file
CodeOpen more actions menu
Folders and files<br>NameNameLast commit message<br>Last commit date<br>Latest commit
History<br>8 Commits<br>8 Commits
README.md
README.md
app.js
app.js
index.html
index.html
user-edit.js
user-edit.js
vanilla-fp.js
vanilla-fp.js
volume-control.js
volume-control.js
View all files
Repository files navigation
The no-framework framework for building component-based purely-functional UIs.
About vanilla-fp
At the heart of vanilla-fp is not code but convention for how to build a component. A component is a pure-ish function that typically receives two parameters (called 'state' and 'setState', but can vary across components) which provide the component with a state and with a function for altering its state and returns a UI component, using the building blocks provided by the framework:
div({className:"container"}, [<br>button({text: "+", onClick: () => setVolume(volume +1)}),<br>span({className: "currentVolume", text: volume}),<br>button({text: "-", onClick: () => setVolume(volume -1)}),<br>]) ">import {div, button, span} from './vanilla-fp.js'<br>export const VolumeControl = ({volume = 0, setVolume}) =><br>div({className:"container"}, [<br>button({text: "+", onClick: () => setVolume(volume +1)}),<br>span({className: "currentVolume", text: volume}),<br>button({text: "-", onClick: () => setVolume(volume -1)}),<br>])
Each vanilla-fp , a component is in charge of keeping the states of its children, instead of utilizing some external global functions and frameworks. It does so by calling it's own 'setState' function and saving the child state in the component's own state.
div({},[<br>span({text:userInfo.name}),<br>VolumeControl({<br>volume: userInfo.credits,<br>setVolume: (volume) => setUserInfo({...userInfo, credits: volume})<br>})<br>])">import {VolumeControl} from './volume-control.js'<br>import {span ,div, button} from './vanilla-fp.js'
export const UserEdit = ({userInfo, setUserInfo}) =><br>div({},[<br>span({text:userInfo.name}),<br>VolumeControl({<br>volume: userInfo.credits,<br>setVolume: (volume) => setUserInfo({...userInfo, credits: volume})<br>})<br>])
But what's at the root of the tree? There can be many options. The reference implementation, which just replaces the DOM elements actually works rather well.
console.log('Rendering app with state', state)<br>document.getElementById("vanilla-fp")<br>.replaceChildren(component({<br>state,<br>setState: (state) => renderComponent(component, state, params),<br>fetch,<br>...params<br>}))<br>}">export const renderComponent = (component, state = {}, params) => {<br>console.log('Rendering app with state', state)<br>document.getElementById("vanilla-fp")<br>.replaceChildren(component({<br>state,<br>setState: (state) => renderComponent(component, state, params),<br>fetch,<br>...params<br>}))
Why?
Using component-based design allows you to organize your stuff better by promoting hierarchy in your code . However, it is rarely utilized to the fullest, because of the lack of a standard way of managing state when developing components (in most cases you have to have a global variable in your program, but we have to at least make sure it is just one global variable.
"Why not just Redux/MobX?"
Redux is great, but it only handles state, so a component would have to come in two parts - state handler and template - that you have to assemble every time. Because of this, Redux is not composable e.g. there is no standard way of embedding one Redux app into another. There is no such thing as a Redux component.
"Why not React useState?"
useState is not great IMO, for many reasons:
You neither have control, nor visibility of the states of your child components. which provokes endless SO debates on "How to listen to child component events", "How to change the state of the child component" etc. Encapsulation of state is important but when you have a hierarchy, the parent has to always have access to the children's state.
The...