Search code examples
grapesjs

Difference between init() and onRender() lifecycle hooks in grapesjs?


Grapesjs provide two lifecycle methods: init() and onRender(), I am actually quite confused with those two hooks:

As the doc said:

  • Local hook: view.init() method, executed once the view of the component is initiliazed
  • Local hook: view.onRender() method, executed once the component is rendered on the canvas
init({ model }) {
  // Do something in view on model property change
  this.listenTo(model, 'change:prop', this.handlePropChange);

  // If you attach listeners on outside objects remember to unbind
  // them in `removed` function in order to avoid memory leaks
  this.onDocClick = this.onDocClick.bind(this);
  document.addEventListener('click', this.onDocClick)
},

// Do something with the content once the element is rendered.
// The DOM element is passed as `el` in the argument object,
// but you can access it from any function via `this.el`
onRender({ el }) {
  const btn = document.createElement('button');
  btn.value = '+';
  // This is just an example, AVOID adding events on inner elements,
  // use `events` for these cases
  btn.addEventListener('click', () => {});
  el.appendChild(btn);
},

For example, i can access this.el in both methods to get dom element. if I want to attach a event listener on this.el, which one is more appropriate to do such operation?

In general, what's difference between those two methods, and in what scenario should i use them?


Solution

  • Use onRender when you need the element in the DOM before the hook executes.

    Example:

    var el = document.createElement('DIV');
    el.style = 'height: 10px';
    
    // logs 0
    console.log(el.clientHeight);
    
    document.body.appendChild(el);
    
    // logs 10
    console.log(el.clientHeight);
    

    clientHeight returns the height of the element in the DOM. It does not compute the height of the element if it is not already in the DOM. There are many properties and functions for HTML elements for which this is relevant.

    Use init when you want your hook to execute as soon as the component initializes without waiting for the render.

    This can be helpful for setting up event listeners. If you set up event listeners in onRender, then any events that fire after init and before onRender won't be caught.

    If the code in your hook doesn't need to be called as soon as the component is initialized and is not dependent on the element being in the DOM, then it doesn't really matter which you choose. In most cases these events will be milliseconds apart.

    I would typically lean towards init though so the hook executes ASAP and doesn't wait around if there is an issue with rendering.