Should Components Load Data?

Last reviewed in August 2015 with Ember 3.0 Update to Ember Octane in progress!

There is a strong consensus that components should not be responsible for fetching data. For instance as this Ember Data document suggests:

“In general, looking up models directly in a component is an anti-pattern, and you should prefer to pass in any model you need in the template that included the component.”

The recommended pattern being:

“Components are isolated entities that consume data through their interface, react to data changes that flow via data binding, and possibly send up named actions”.

{{awesome-data-grid-component data=model.items}}

The answer to our question seems to be a resounding no. This design pattern almost forbids accessing data directly from a component (by means of passing in or injecting a reference to the store).

Data-loading components?

But there are non-obvious use cases which can benefit from abstracting responsibilities like loading data.

{{awesome-twitter-component tweets=tweets}}

Loading tweets does not feel like an appropriate concern for the router!

There are valid arguments for encapsulating data retrieval:

  • Component consumers should not be concerned with how to load tweets, just provide minimal information (a Twitter handle)
  • As the component encapsulates all UI and data logic, it can be highly reusable
{{awesome-twitter-component handle='emberjs'}}

A different case

Imagine we have a template rendering a blog post model:

export default DS.Model.extend({
  title: DS.attr('string'),
  body: DS.attr('string'),
  comments: DS.hasMany('comment', { async: true })

Its comments can be passed into a comments-component, abiding by standard practice.

{{comments-component comments=post.comments}}

But we also need to display ads (Ad is also a model in our application).

{{ad-component keywords=post.body }}

This component requires text input to feed its internal algorithm of ad display. It makes total sense for it to access ad data in the Ember Data store.

export default Ember.Component.extend({
  store: Ember.inject.service(),

  displayAds: function() {
    const adTags = algorithm({ text: this.get('keywords') });
    this.get('store').query('ads', { tags: adTags }).then(function() {


Whether a component requires non-store data like the Twitter component or store data like our ad component, there is sound sense to both. We must note that neither change the URL.

Isn't there a standard answer to our question? So far, it looks like “it depends”.

Asynchronous Components

Once we have asynchronous components, it may be tempting to handle all data loading through them, eliminating traditional Routes, and essentially moving the model hook onto Components. But we think there are still strong architectural reasons for having Routes as a separate concept. Routes orchestrate transitions, and often have important work to do before you even know what components need to be on the page.

Components today have a broader meaning. There is no requirement for a component to be linked to either a template or data service.

Some components will necessarily be application-specific. Others will be reusable outside of the application context.

Some will be passed in data. Others will load data by themselves. And some of those might be entirely data-centric, with no UI whatsoever.

To our question “Should components load data?", we can conclude:

  • If you are changing the URL, use a Route.
  • If you can't decide exactly where you're going until after looking at the (asynchronously-loaded) data, use a Route.
  • Otherwise it's probably fine to use an asynchronous Component.

Enjoyed this article? Join Snacks!

Snacks is the best of Ember Octane in a highly digestible monthly newsletter. (No spam. EVER.)