Containers
Containers are a familiar pattern to those working in vishnu-frontend by now, but see the Code Cookbook if you need a refresher. The container pattern is common in applications built with the Redux architecture, and we strongly encourage the use of container components when developing applications with ember-redux. Containers are responsible for specifying their own data requirements, but they are not responsible for fetching that data. Data fetching still occurs in the routes. Using connect, container components decouples our view tree from our state tree at any point we desire, rather than passing data through component and/or route hierarchies. connect has the following signature:
connect(stateMap, actionMap)(Ember.Component.extend({ … }))1
Container components are a natural fit with ember-redux's connect function. With Redux, a container component is just an Ember component that uses store.subscribe() behind-the-scenes to watch a part of the Redux state tree. The container then supplies props and closure actions to the presentational components it renders. With Redux, our container components are largely the same as before, with the following differences:
- We move our closure actions to an actionMap object.
- We move our data dependencies to a stateMap object.
- We then wrap our component with our actionMap and stateMap using
connect.
connect transfers the members of the actionMap into the component's actions object, and transfers the members of the stateMap to the component's properties.
Simple example
const stateMap = state => {
units: state.entities.units
}
const actionMap = dispatch => {
onStartUnit(unit, properties) {
dispatch({
type: TYPES.START_UNIT,
payload: { unit, properties }
})
}
}
const myComponent = Ember.Component.extend({})
export connect(stateMap, actionMap)(myComponent);
More robust example
The above example creates the action inline with the dispatch mechanism. This ends up feeling boilerplatey over time, so we suggest using action creators. With action creators, the above actionMap would look like this:
import { units } from 'vishnu/actions';
const actionMap = dispatch => {
onStartUnit: units.onStartUnit({ unit, properties })
}
Please see the action creators documentation for more information.
1. This syntax might seem a little foreign. Its a common convention in the React and Redux ecosystems which are rooted more in functional programming concepts. In this case, `connect` is a curried function that we partially apply our arguments to. This means that connect(stateMap, actionMap) returns a function that takes our component as its sole argument. This makes connected components infinitely composable and more reusable. ↩