Skip to content

Instantly share code, notes, and snippets.

@fiatjaf
Last active November 10, 2023 01:16
Show Gist options
  • Save fiatjaf/ece86e33b1f8846c8f8c318778b0895a to your computer and use it in GitHub Desktop.
Save fiatjaf/ece86e33b1f8846c8f8c318778b0895a to your computer and use it in GitHub Desktop.
idea of a framework that takes the best of Cycle, React and Mobx

The idea is that we will use React for the virtual DOM rendering (so we can make use of all React components out there), but all the DOM events would be routed semi-automatically to a state function that would get them as streams and, along with other data and other streams (we will use xstream to wire all that), will produce a state.

The state will then be emitted in parts to each virtual DOM component (only the updated parts will be emitted to the components that is using those parts, and only those components will be rerendered), so that UI composition will look like MobX.

What you gain is a cleaner state representation, and much more customizable/complex states are possible, much finer grained state updates and composition (there's no "computed" since everything is computed, there's no "action" since all DOM events potentially trigger actions). Also, it's much better to compose components as functions, that's only possible if you don't have to write event handling code inside each component or keep local state for each component.


Local state, however, is sometimes desirable, even Cycle acknowledges that with their isolate() function.

Maybe we could use a function similar to track that will instead route events to a local state that is just like the global state, but only visible to the component instance that owns it. I don't know.

window.xtend = require('xtend')
const {h, run, reactive, track, select} = require('.')
var state = reactive({
name: select('.name-type')
.events('change')
.map(e => e.target.value),
desc: select('.desc-type')
.events('change')
.map(e => e.target.value)
})
function Main () {
let name = state.$.name
return h('div.root', [
h('input.name-type', {
placeholder: 'type your name...',
onChange: track
}),
h('h1', `hello ${name}`),
h(Description)
])
}
function Description () {
let desc = state.$.desc
let name = state.$.name
return h('div.description', [
h('textarea.desc-type', {
value: desc,
onChange: track
}),
h('div', `${name}, you are ${desc}`)
])
}
run(document.getElementById('root'), Main)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment