Search code examples
mithril.js

Preventing redraw in Mithril


I've made a simple FlashMessage model for mithril and I'm using it to display feedback for forms (e.g. successfully saved):

// the model
var FlashMessage = {
    messages: [],

    clear: function()
    {
        FlashMessage.messages = [];
    },

    add: function(level, message)
    {
        var mess = {level:level, message: message};
        FlashMessage.messages.push(mess);
    },

    get: function()
    {
        var messages = FlashMessage.messages;
        FlashMessage.clear();
        return messages;
    }
};

module.exports = FlashMessage


// the use
m('section.flash-messages', FlashMessage.get().map(function(mess){return m('.message-' + mess.level, mess.message);}))

When saving data, the layout displays the flash message which is fine, however as soon as I enter data into an input again on the form, the flash-message div appears to be redrawn and because the get method erases the data, the flash message disappears. This is because of Mithril redrawing when data has changed as I understand, but how do I prevent this?


Solution

  • Preventing redraw is simple, as I will show you, but in your case that is not a good solution. Instead you should change how you think about state.

    Preventing redraw

    Just add a function onbeforeupdate to your component and return false if you don't want to update.

    var Component = {
        onbeforeupdate: function (vnode, old) {
            var shouldUpdate = ???;
    
            return shouldUpdate;
        }
        ...
    };
    

    Thinking about state

    The state of your app should always be reflected in the UI. If the state changes, what is displayed should also change. This is the core principle of React and all the libraries it has inspired, amongst them Mithril. Doing it this way makes it easy to code stateful applications, and this is why these libaries are popular.

    Doing it any other ways is (very) bad practice. You will have a hard time making it work properly, not only because [Mithril] is designed to ensure state updates are always reflected in the UI, but also because it's hard to reason about. (Plus, your code will not make sense to other people.)

    In your case

    If you want the messages to stay on the sceen, they should also stay in the state.

    Only when you want the messages to go away (on screen), should you remove them from the state.

    Please post a new question, explaining what you wanted to achieve, and I will show you how to do it :)