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 stateuseEffect
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
- Larger explanation on Ember lifecycle https://guides.emberjs.com/v3.3.0/getting-started/core-concepts/
- Ember Component lifecycle https://guides.emberjs.com/v3.4.0/components/the-component-lifecycle/
- Visual difference in Ember for lifecycle with Glimmer and before https://github.com/yankeeinlondon/ember-lifecycle-hooks
- Explanation of Ember.js overall https://www.smashingmagazine.com/2013/11/an-in-depth-introduction-to-ember-js/
- Explanation of React hooks https://github.com/Wavez/react-hooks-lifecycle
- Other React lifecycle hooks https://react.dev/reference/react/hooks