connect-to-backbone v0.0.4
connectToBackbone
A decorator for integrating Backbone with React components. You'll notice similarities to the @connect
decorator provided by redux. This project is still in a proof-of-concept stage and is not thoroughly tested.
Models
@connectToBackbone()
class Header {
static propTypes = {
label: PropTypes.string
};
render() {
return <h1>{this.props.label}</h1>;
}
}
<Header model={model} />
The Header
component will observe changes to model
and keep its state up-to-date as attributes change. Change handling is debounced, so if multiple change events are triggered in quick succession, only one render occurs. Model attributes are provided to the decorated component directly as props (this.props.label
). This allows for a better contract and minimizes Backbone-specific code in components.
selectModelState
@connectToBackbone({ selectModelState: model => model.pick('label') })
By default, selectModelState
returns model.toJSON()
, but this can be overridden to allow specific attributes to be passed to the decorated component. In the example above, the component will only be listening to change:label
and all other changes to the model are ignored.
Collections
@connectToBackbone()
class List {
static propTypes = {
items: PropTypes.array
};
render() {
return (
<ul>
{this.props.items.map(item => <li>{item.title}</li>)}
</ul>
);
}
}
<List collection={collection} />
The List
component will observe changes to collection
(reset update change
by default) and keep its state up-to-date as the collection changes. Once again, change handling is debounced to minimize re-renders.
selectCollectionState
@connectToBackbone({ selectCollectionState: collection => collection.sortByLabel() })
By default, selectCollectionState
returns collection.toJSON()
, but this can be overridden to allow custom behavior. In the example above, a function can be used to display a sorted list. Keep performance in mind since this function can be called many times if the collection and its models are changing frequently. ignoreCollectionChangeEvents
can be used to minimize work in such cases.
ignoreCollectionChangeEvents
@connectToBackbone({ ignoreCollectionChangeEvents: true })
class List {
render() {
return (
<ul>
{this.props.collection.map(model => <ListItem model={model} />)}
</ul>
);
}
}
@connectToBackbone()
class ListItem {
static propTypes = {
title: PropTypes.string
};
render() {
return (
<li>{this.props.title}</li>
);
}
}
The ignoreCollectionChangeEvents
option can be used to only listen to the reset
and update
events, so the list will not re-render on every model change. This can be useful if the list items are also smart components that listen to model change events on their own. In the example above, the ListItem
component is a smart component that is receiving the model instance as a prop. The ListItem
will be listening to model changes, so the List
does not need to.
Composite
<Composite model={model} collection={collection} />
Both a model and collection can be provided to a component, as you'd expect.
Avoid Nested Smart Components
While a smart component with a collection can create smart children components that are each passed a model, it's best to avoid other forms of nested smart components. Otherwise, multiple levels of components could be listening and trying to re-render on the same change events. This pattern works best if you avoid multiple levels of smart components listening to the same model.