Skip to main content

Lifecycle Methods

Lifecycle methods run at different points of time for rendering components. In Ember, modifiers are often used in Glimmer (doc). In React, useEffect and other hooks are used to handle state and run side effects (doc).

Ember

In Ember, we use the {{did-insert}} modifier to run code when the component is first inserted into the DOM.

The @tracked decorator makes the property reactive, and the @action decorator is required for methods that will be called from templates or modifiers.

template.hbs
<div {{did-insert this.initComponent}}>
{{this.loadingState}}
</div>
component.js
import { tracked } from '@glimmer/tracking';
import Component from '@glimmer/component';
import { action } from '@ember/object';

export default class LoadingIndicator extends Component {
// loading is the initial state
@tracked loadingState = 'Loading...';

// action is needed to respond to the didInsert modifier
@action
initComponent() {
// can add a delay just to see it happen:
setTimeout(() => {
this.loadingState = 'Component initialized';
}, 2000); // 2 seconds
}
}

React

In React, we use useState to manage component state and useEffect to handle side effects. The empty dependency array [] ensures the effect only runs once after the initial render, equivalent to Ember's {{did-insert}}.

The key differences:

  • useState replaces @tracked properties for reactive state
  • useEffect with empty dependencies [] replaces {{did-insert}} modifier
  • No need for @action decorator - regular functions work fine
  • State updates use setter functions (setLoadingState) instead of direct assignment
Live Editor
// update code to see this re-run
// automatically included but you'll have to import them to use them
// import { useEffect, useState } from 'react';

function LoadingIndicator() {
	// loading is the initial state
  const [loadingState, setLoadingState] = useState('Loading...');

	function initComponent() {
    setTimeout(() => {
      setLoadingState('Component initialized');
    }, 2000); // 2 seconds
  }

  // only after first render
  // don't want to keep on initializing so empty array
  useEffect(() => {
    initComponent();
  }, []);

  return <div>{loadingState}</div>;
}
Result
Loading...

Further notes