Closed YerkoPalma closed 7 years ago
The ides is state down, actions up. Fundamentally state gets passed down from the 'top' and is used and shaped as it traverses down your views/components. You use 'emit' to pass state updates up from the bottom. At any point in your view tree, you can change the shape of what you pass along, for example only passing the state that owned components need to render. Generally its not a good idea to modify app level state in views and you should be using the emitter bus to pass around events with values and do it all in one place. Its totally okay to re-shape state for the needs of owned components.
So, the key should be to pass the choo emitter object to the component and keep manipulating state through events?
I've tried passing the emitter.emit function to my nanocomponent and it works :D But I encountered something weird, I'm stuck in an endless loop when firing events from nanocomponent. With this code
// component
function Navlink (opt) {
if (!(this instanceof Navlink)) return new Navlink(opt)
this.direction = opt
this.current = null
this._emit = null
this.navigate = this.navigate.bind(this)
Nanocomponent.call(this)
}
Navlink.prototype = Object.create(Nanocomponent.prototype)
Navlink.prototype.navigate = function (e) {
e.preventDefault()
this._emit('navigate', this.current + 1)
}
Navlink.prototype.createElement = function (state, emit) {
this._emit = emit
this.current = state.current
return html`
<a href="#" onclick=${this.navigate}>
<span class="icon-${this.direction}-open"></span>
</a>
`
}
Navlink.prototype.update = function (state, emit) {
return true
}
// app
var app = choo()
app.use(function (state, emitter) {
state.current = 1
emitter.on('navigate', function (year) {
// if (year && state.current !== year) {
state.current = year
emitter.emit('log:info', 'Going to ' + year)
emitter.emit(state.events.PUSHSTATE, '/?year=' + year)
// }
})
})
When I click in my component link, What is inside the 'navigate'
handler get fired for ever until the browser throws an exception, only when I uncomment the condition in my handler it works, because of those intinite calls, only the first one has the correct data, the others have undefined
as state.
Do I have to check my state in every event handler? Or there is something I'm missing?
@YerkoPalma choo@6
has its own navigate
event that fires whenever a route changes. If you name your event something else that might solve your problem. Please let me know if that helps!
https://github.com/choojs/choo/blob/master/CHANGELOG.md#600-same-as-it-ever-was
Basically your navigate
event is causing a pushstate
event, which is causing an internal navigate
event, which is causing a pushstate
event, which is causing a navigate
event... etc
(note: edited the above a little bit when I read your example a bit more)
@bcomnes might be a good idea to namespace the internal choo events, like with a __navigate
or choo-navigate
or something, so it's less likely there will be namespace collisions like this.
Oh! I see, will check it asap. Thanks @ungoldman and @bcomnes for your time :)
@bcomnes also https://github.com/choojs/choo/blob/master/CHANGELOG.md looks like it hasn't been updated since june, is choo@6 officially out?
No problem @YerkoPalma! I think you found something worth rethinking in terms of choo's internal architecture 👍
Well, I think that my doubts/issues about Nanocomponent are resolved now, so I'm closing this. I'm also opening an issue in choo to discuss about namespacing events.
Choo issue here: https://github.com/choojs/choo/issues/547
Hi :wave: I'm just starting with nanocomponent so this might be a repeated/silly question. I was wondering how can I call a method from a component that change the whole choo app state. Going further, it would be cool to share state between components and choo app, because in the
createElement
function I'm always passing some or all of the state. Maybe there is an easy way to do this, but I just can figure it out.