I’m trying to separate my UI components completely from any Meteor package / data loading dependency. Using containers, it’s pretty easy to do this for one level of UI-container, like:
./containers/ItemContainer.jsx
/*
* The container for the UI for one item
* It takes care of loading the data
*/
import React, { Component } from 'react';
import { composeWithTracker } from 'react-komposer';
import ItemUI from '../components/ItemUI.jsx';
import { Items } from '../lib/collections.js';
function composer(props, onData) {
const { itemId } = props;
if (Meteor.subscribe('items', itemId).ready()) {
const item = Items.findOne({ _id: itemId });
onData(null, {...props, item });
}
};
export default composeWithTracker(composer)(ItemUI);
./components/ItemUI.jsx
/*
* The UI for one item
* It only does UI stuff
*/
import React, { Component, PropTypes } from 'react';
export default class ItemUI extends Component {
render() {
const { item } = this.props;
return <div> { item.name } </div>;
}
}
ItemUI.propTypes = {
item: PropTypes.object.isRequired,
};
Now what happens if ItemUI
renders an nested container-component? It sounds like ItemUI
would import the container that itself depends on some data loading logic, so ItemUI
that is supposed to be pure UI loads data stuff. That’s annoying for testing where I’d like to test UI components independently of any data loading thing.
My guess is that things would now look like:
./containers/ItemContainer.jsx
-> same as before
./components/Item.jsx
/*
* The UI for one item
* It should only do UI stuff, BUT has data dependency through its children,
* and therefore import data dependent things
*/
import React, { Component, PropTypes } from 'react';
import SubItemContainer from '../containers/SubItemContainer.jsx'; <- this is NOT COOL
export default class ItemUI extends Component {
render() {
const { item } = this.props;
return <div>
{ item.name }
<SubItemContainer subItemId={ item.subItemId } />
</div>;
}
}
ItemUI.propTypes = {
item: PropTypes.object.isRequired,
};
./containers/SubItemContainer.jsx
/*
* The container for the UI for one sub item
* It takes care of loading the data
*/
import React, { Component } from 'react';
import { composeWithTracker } from 'react-komposer';
import SubItemUI from '../components/SubItemUI.jsx';
import { SubItems } from '../lib/collections.js';
function composer(props, onData) {
const { subItemId } = props;
if (Meteor.subscribe('subItems', subItemId).ready()) {
const subItem = SubItems.findOne({ _id: subItemId });
onData(null, {...props, subItem });
}
};
export default composeWithTracker(composer)(SubItemUI);