- Prefer composition over mixins
- Prefer immutablity
- Avoid using events as they create side-effects
- Lifecycle methods should always be a single function. e.g.
button.beforeMount(cxt)
- Declarative API with everything declared the same way in the same place
- Avoid the need for deku-specific plugins, it should make composition easy
- Avoid magic and complex APIs. Functions should just be functions with no side-effects.
Last active
February 22, 2023 06:45
-
-
Save anthonyshort/dd3b115c2499b53e1e13 to your computer and use it in GitHub Desktop.
Functional API for Deku
- How do we handle things that always need to do something at the start and end of the component lifecycle? Intervals and pulling in data.
- How can we make all the hooks be declared the same way while still allowing composition and having simple functions?
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Allows composing multiple fns together into a middleware chain | |
// button.use(compose('beforeMount', store('events'), store('events'), prepare)) | |
function compose(name, ...fns) { | |
var mw = ware().use(fns) | |
return function(Component) { | |
Component[name] = function(context) { | |
mw.run(context) | |
} | |
} | |
} | |
export {compose} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {button} from './button' | |
import {scene,render} from 'deku' | |
// returns a scene | |
var app = scene(button) | |
.setProps({ text: 'Submit' }) | |
.use(channels()) | |
.debug(true) | |
// Render the scene to the body using the DOMRenderer | |
// Returns the renderer object. | |
render(app, document.body) | |
// Update the props. The renderer will re-render | |
// the app on the next frame. | |
app.setProps({ text: 'foo' }) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Override shouldUpdate to provide a small performance | |
// boost for components with pure rendering functions | |
function pure() { | |
return function(Component) { | |
Component.shouldUpdate = function(props, state, prevProps, prevState) { | |
return false; | |
} | |
} | |
} | |
export {pure} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Observe external data sources | |
function store(name) { | |
return function(context) { | |
let store = context.stores[name] | |
return store.subscribe(context) // returns an Observable | |
} | |
} | |
export {store} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {button} from './button'; | |
import {context} from 'deku'; | |
// We can execute the middleware in tests and assert the | |
// hooks have updated the context to the correct state | |
let cxt = context() | |
button.afterMount(cxt) | |
assert(cxt.props.foo) | |
// Check the result of the render method and test it to | |
// make sure events are hooked up, the structure is correct etc. | |
let cxt = context() | |
let result = button.render(cxt) | |
// Or make sure your shouldUpdate method works correctly | |
var shouldUpdate = button.shouldUpdate(props, state, prevProps, prevState) | |
assert(shouldUpdate) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
If the hooks needed to return a context or a promise that would resolve into a context, we could allow the contexts to be immutable and async.