The page navigation is complete. You may now navigate the page content as you wish.
Skip to main content

Why Ember?

Ember for React Developers

Note: The original document has been re-published with permission, and modified slightly for this site.

Conceptually, both React and Ember can provide the solutions to the same problems. React has historically only been the component layer of applications, but that is changing as React evolves, and gradually adds more features that aim to make developing applications with React more pleasant. Ember offers a more out of the box, and aims to have a solution or pattern for most situations – with additional tooling, conventions, architectural patterns. The goal is to abstract away the menial differences between apps and reduce friction when switching projects.

React is only Components

React is *mostly* components. Interactions with external services such as Redux, GraphQL or Orbit.js happen through components backed by a Context which we'll dive into in a bit.

Ember connects to data via Services

Ember has architectural patterns for dealing with specific interactions. Third party services are always interfaced with an Ember Service. Services are used for a lot more than just 3rd party library integrations. A Service is a singleton that lives for the duration of the application. Ember has object types other than services.

Components

Both Ember and React use components as the foundational building block for web apps, and Ember and React components have a lot in common. There are a couple important differences between components in the two frameworks you should know about, though!

If you're not already familiar with Ember's concept of components, please take a bit and check out the official guides: https://guides.emberjs.com/release/components/defining-a-component/

The first major difference is that React Components can be defined using either JavaScript *classes* or *functions*, whereas the equivalents in Ember are *class-backed components* (which use a JavaScript class) and *template-only components* (which do not use JavaScript at all). This separation is a reflection of the second major difference between React and Ember components: how the rendered HTML is defined. React components use JSX and Ember uses Templates – both template-only components, and class-backed components.

Some of the reasons for using a templating language over "just JavaScript"™ are discussed here in this video from ReactiveConf. There are other reasons as well, but they are beyond the scope of this guide.

Like React, Ember makes heavy use of ideas from both functional programming and object-oriented programming, though you'll find they show up in different ways!

Component Patterns

Next, let's look at four types of component patterns: presentational/stateless components, container components, higher-order components, and contextual components.

Presentational or "Stateless" Components

Presentational components only display or format data. They do not have state, do not make requests, and do not cause side-effects within the app without being passed a function to do so.

Presentational components are one half of a common design pattern in component-driven interfaces, where behavior is separated from what displays the result of the behavior. These are most commonly referred to as container and presentational components. However, a container component with state does not need to exist in order to use a presentational component. A presentational component could be thought of as a Pure Function in that the output is always the same for any given set of inputs. The presentational component may have logic for controlling what is displayed when, but it does not maintain the state that backs the logic. Icon component libraries are an example of presentational components.

The example below shows a logic-less, presentational component that will be rendered with some static data:

// presentation.jsx
import React from 'react';

export function Presentation({ message, response }) {
  return (
    <>
      Obi Wan Kenobi: {message}
      General Grievous: {response}
    </> 
  );
}
// invocation.jsx
<Presentation
  message={‘Hello There!’}
  response={‘General Kenobi!!’}
/>

In presentation.jsx the component receives two arguments which are then rendered. We see that in invocation.jsx those arguments are assigned to static values, so the rendered result will be:

Obi Wan Kenobi: Hello There! General Grievous: General Kenobi!!

The same pattern would be written this way in Ember:

<!-- presentation/template.hbs -->
<p>Obi Wan Kenobi: {{@message}}</p>
<p>General Grievous: {{@response}}</p>
<!-- invocation/template.hbs -->
<Presentation 
  @message=‘Hello There!’ 
  @response=‘General Kenobi!!’
/>

Container Components

Container components provide functionality to the wrapping content without adding any markup to the DOM. These are also known as "Renderless Components". They may also be higher-order components, but in React, a Higher-Order Component is a little more specific than the Container component concept.

The following example may be something used to manage the open or closed state of a modal.

// modal-state.jsx

import React, { useState, useCallback } from ‘react’;

export function ModalState({ children }) {
  const [isActive, setIsActive] = useState(false);
  const toggle = useCallback(() => setIsActive(!isActive), [isActive]);
  const close = () => setIsActive(false);
  const open = () => setIsActive(true);
  
  return children({
    isActive,
    actions: {
      toggle, close, open
    }
  });
} 

Using React's hooks, we just set up some state and callbacks to provide to any child components that may want to use an open/close state.

// usage.jsx

<ModalState>
  {({ isActive, actions }) => {
    return (
      <AskAQuestion isActive={isActive} close={actions.close} />
    );
  }}
</ModalState>

Higher-Order Components

Higher-Order components are functions that take a component as an argument and return a new component wrapping the passed component with some additional functionality.

In Ember, a higher-order component is something different. Read Higher-Order Components in Ember.js by Chris Krycho, or watch (the very funny) talk by Miguel Camba, Higher Order Components.

Ember doesn't have the same concept as React's higher-order components. There are tradeoffs here, so let's examine those.

The inconvenience (in Ember) is that you have to be slightly more verbose with your reuse as you need to specify the argument keys in addition to the value, where as with higher-order components in React, they are implicitly given to your wrapped component.

However, this use of higher-order components makes it hard to track down where props are coming from, an inconvenience for React. It's also why (in-part) React has been encouraging hooks. Ember has not adopted this pattern, because Ember is striving for code to be discoverable, especially to those who may be unfamiliar with Ember in general. Ember's goal is to make it clear and easy to "go to definition", and higher-order functions would detract from that.

Contextual Components

Contextual components are useful when you have a set of components that need to be used together, and you want consistent invocation / style / interaction between that set of components. Contextual components are an Ember concept; the closest translation to the idea is Compound Components. Because the components are nothing more than module exports, the static properties of related components can be tacked on to the main export of a component.

Templates and JSX

Templates in Ember are not "Just JavaScript" like JSX. Ember templates build on HTML (a template that is only HTML is completely valid), or rather, a superset of HTML.

One of the benefits of JSX is that by leveraging JavaScript, it's very clear where variables and event handlers come from. In larger components being able to "Go-to definition" by either hotkey or click combination to find the definition of the property or function is essential to learning the flow of data. An IDE or editor's support of this kind of discovery comes natural with *just* JavaScript support.

Of course, Ember has a entire framework of features right out of the box, so the developer's IDE needs a few addditional plugins to achieve a similar experience- two important ones are Ember Language Server, and Handlebars. ‌

Aside from editor-feature differences, there are a number of technical reasons that Ember uses templates over JavaScript. First, templates are statically analyzable and can be transformed and/or modified at build time. Second, templates are compiled down to a binary format that makes the compiled size that is much smaller than gzipped and minified JavaScript. The binary format also allows for the user's browser to read and evaluate the template much faster than JavaScript as JavaScript needs to be parsed and compiled by the browser before it can be evaluated. Finally, templates allow you to use all the features of the web. HTML attributes can be separated from component arguments through use of ...attributes, and all the attributes you find in HTML (or SVG) documentation just work. There's no need to try to translate anything in your head before you write it.

For more information on the benefits of the templating language that ember uses, there is this talk that Tom Dale gave at ReactiveConf 2017: Secrets of the Glimmer VM.


Have more information to add to this page? Issues and PRs to this project's repository are welcome!