marionette-redux
v1.0.2
Published
Marionette and Backbone bindings for Redux
Downloads
326
Maintainers
Readme
Marionette Redux
Marionette and Backbone bindings for Redux.
It's like React Redux, but for Marionette and Backbone.
Marionette Redux allows you to connect
any Marionette or Backbone "component" to a Redux store.
Why Use This Library?
Predictability
Marionette Redux introduces to a Marionette application a lifecycle that allows for deterministic DOM updates – consistent at first render and for any subsequent store updates (or component state changes) after the first render.
Migrating to React
If you've decided to migrate, Marionette Redux allows you to leverage Redux as a central data store to share app state between your React and Marionette components.
Examples:
How Does It Work?
componentWillUpdate
will execute when a display component (Marionette.View
or Marionette.Behavior
) first renders. This is where you put your DOM manipuation code.
A connected component's mapStateToProps
will execute whenever the Redux store state changes. If the return object of display component's mapStateToProps
differs from the last result, componentWillUpdate
will execute.
Thus, you can set up components to always rely on the same set of values to determine their DOM state. This means that your view's can execute the same callstack on first render and for any Redux store changes.
Installation
npm install --save marionette-redux
Usage
connect
Below is an example of a Marionette.View
that has been "connected" to a Redux store
. The following code could also be applied to a Marionette.Behavior
.
var ConnectedView = MarionetteRedux.connect()(Marionette.View.extend({
store: store,
mapStateToProps: function(state) {
return {
isActive: state.isActive
}
},
componentWillUpdate: function() {
this.$el.toggleClass('active', this.props.isActive);
}
}));
In this example, store
is a property on the component, but connect
will also look to window.store
as a last resort. window.store
can thus act similarly to React Redux's "Provider
".
mixin
While connect
is the recommended approach, Marionette Redux can also be used as a mixin.
Marionette.View.extend(MarionetteRedux.mixin);
Mappings
Mappings work the same as in React Redux. A change to the Redux store will result in this callback being executed on any "connected" components.
mapStateToProps
mapStateToProps
can be a property on the component itself.
var ConnectedView = MarionetteRedux.connect()(Marionette.View.extend({
mapStateToProps: function(state) {
return {
isActive: state.isActive
}
}
}));
Or it can be provided to connect
as the first argument.
function mapStateToProps(state) {
return {
isActive: state.isActive
}
}
var ConnectedView = MarionetteRedux.connect(mapStateToProps)(Marionette.View.extend({…}));
mapDispatchToProps
mapDispatchToProps
can also be a property on the component.
var ConnectedView = MarionetteRedux.connect()(Marionette.View.extend({
mapDispatchToProps: function(dispatch) {
return {
dispatchMyEvent: function() {
dispatch({
type: 'MY_EVENT'
});
}
}
},
events: {
click: 'handleClick'
},
handleClick: function() {
this.props.dispatchMyEvent();
}
}));
Or it can provided to connect
as the second argument.
var ConnectedView = MarionetteRedux.connect(null, mapDispatchToProps)(Marionette.View.extend({…}));
Lifecycle
componentWillReceiveProps
This function is similar to React's componentWillReceiveProps
. It provides an opportunity to execute any side effect functions before execution of componentWillUpdate
.
Note: If the component is not a display component, meaining it is a Backbone.Model
or Backbone.Collection
, componentWillReceiveProps
will still execute, however componentWillUpdate
WILL NOT.
componentWillUpdate
This library ecourages the use of componentWillUpdate
to ensure predictability of DOM state – one of the great things about React.
As demonstrated below, componentWillUpdate
can be used to execute code that you want to run when a component is first rendered and after any subsequent changes to a component's props
or state
.
var ConnectedView = MarionetteRedux.connect()(Marionette.View.extend({
store: store,
mapStateToProps: function(state) {
return {
isActive: state.isActive
}
},
componentWillUpdate: function() {
this.$el.toggleClass('active', this.props.isActive);
}
}));
State
If you prefer more granular control over store updates, we've provided state to components as well.
setState
, getState
, state
, and getInitialState
are all available for getting and setting state.
State works exactly the same as Marionette's modelEvents
listeners, using the stateEvents
object to define listeners:
var ConnectedView = MarionetteRedux.connect()(Marionette.View.extend({
store: store,
getInitialState: function() {
return: {
isActive: false
}
},
stateEvents: {
'change:isActive': 'onIsActiveChange'
},
onIsActiveChange: function(view, isActive) {
this.$el.toggleClass('active', isActive);
},
mapStateToProps: function(state) {
return {
isActive: state.active === this.model.id
}
},
componentWillReceiveProps: function(update) {
this.setState({
isActive: update.isActive
});
},
}));
As with changes to props
, changes to a display component's state
will execute componentWillUpdate
.
Backbone
You also have the option to connect
a Backbone.Model
or Backbone.Collection
.
Model
function mapStateToProps(state) {
return {
currency: state.currency
}
}
var Model = Backbone.Model.extend({
store: store,
initialize: function() {
// update the store on changes
this.on('update', function() {
store.dispatch({
type: 'MODEL_UPDATE',
data: this.toJSON()
});
})
},
componentWillReceiveProps: function(update) {
this.set({
currency: update.currency
})
}
});
var ConnectedModel = MarionetteRedux.connect(mapStateToProps)(Model);
Collection
var Collection = Backbone.Collection.extend({
store: store,
initialize: function() {
// update the store on changes
this.on('update', function() {
store.dispatch({
type: 'COLLECTION_UPDATE',
data: this.toJSON()
});
})
}
});
var ConnectedCollection = MarionetteRedux.connect()(Collection);
License
MIT