Asked By: Anonymous
I am trying to sort a list of data and reflect the change, but my view isn’t refreshing if I use subcomponents to render the content.
My sort function is being called simply by a button’s onclick:
m('button', {onclick: ctrl.sort}, 'sort'),
Here’s a jsfiddle that replicates my issue. The first version uses a subcomponent to render.
https://jsfiddle.net/4trL6y22/
ctrl.names.map(function(name){
return m(Hello, {who: name});
})
If the code is rewritten without the subcomponent, the view refreshes after the sort occurs:
https://jsfiddle.net/4trL6y22/1/
ctrl.names.map(function(name){
return m('h1', name);
})
(My real-life case is more complicated and benefits from having the subcomponent). What am I missing to bubble up this sort’s diff to the page?
Solution
Answered By: Anonymous
From looking at the snippet, I think you’re misunderstanding how the controller function is run.
Afaiu the controller executes once when a component is created, but not on subsequent diffs. (Generally speaking, exceptions to this statement include when the key
changes (afaiu).)
Hence, putting options.who
directly in the view is preferable to setting it in the controller of the component (it makes it a pure component, hence why I believe it’s preferable — meaning state is maintained in less places) which fixes one of the issues.
The other issue is that the names
property is set to the result of the list
prop on initialisation but is never updated (although, if the change mentioned above is made then the correct functionality appears to happen because the list
is updated because sort()
performs and in-place sort — https://jsfiddle.net/bruce_one/1qpresbf/ vs https://jsfiddle.net/bruce_one/m3c5rn92/ demonstrates what I’m trying to explain). Hence, rather than invoking the prop in the controller, instead invoke it when retrieving the value in the view.
So the two changes (and a .slice(0)
to get make the sort non-mutating (ish)) becomes: https://jsfiddle.net/bruce_one/4trL6y22/3/
(Afaict, this is fixing your issues?)