HistoryJSMixin updated: React History / PushState now with URL updates (great for pagination / search)

I wanted a simple way for React component state to update pushState/history, and I found it in Leif Denby's simple HistoryJSMixin. One thing it was missing: being able to update the URL too (e.g. change "/foo" to "/foo?bar=baf") with that state. 

I've added it with a simple two line change here (line 57 and 61): 

/** Adapted from http://leifdenby.svbtle.com/reactjs-and-browser-history-a-historyjs-mixin */
var HistoryJSMixin = {
_historyjs_recoverState: function(state) {
received_state_serialized = state.data;
if (!$.isEmptyObject(received_state_serialized)) {
if (this.deserializeState !== undefined) {
received_state = this.deserializeState(received_state_serialized);
}
else {
received_state = received_state_serialized;
}
if (this.serializeState !== undefined) {
current_state_serialized = this.serializeState();
}
else {
current_state_serialized = JSON.stringify(this.state);
}
// look through the received state to see if there are any changes
// relative to the state we are currently in
combined_state = $.extend({}, this.state, received_state);
update_state = !(JSON.stringify(current_state_serialized) === JSON.stringify(received_state_serialized));
var callback_f = function() {};
if (this.hasRecoveredState !== undefined) {
callback_f = this.hasRecoveredState;
}
if (update_state) {
if (this.recoverState !== undefined) {
this.recoverState(combined_state, callback_f);
}
else {
this.setState(combined_state, callback_f);
}
}
}
},
saveState: function(options) {
var serialized_state = null;
if (this.serializeState !== undefined) {
serialized_state = this.serializeState();
}
else {
serialized_state = {};
$.each(this.state, function(k,v) {
if (k != '_historyjs_has_saved') {
serialized_state[k] = String(v);
}
});
}
if (!this.state._historyjs_has_saved) {
this.setState({ _historyjs_has_saved: true }, function() {
History.replaceState(serialized_state, options.title, options.url);
});
}
else {
History.pushState(serialized_state, options.title, options.url);
}
},
bindToBrowserHistory: function() {
History.Adapter.bind(window,'statechange',function(){
this._historyjs_recoverState(History.getState());
}.bind(this));
this._historyjs_recoverState(History.getState());
},
getInitialState: function() {
return { _historyjs_has_saved: false };
},
patchSavedState: function(data, callback) {
var old_state = History.getState();
$.extend(old_state.data, data);
History.replaceState(old_state.data);
if (callback !== undefined) {
callback();
}
},
};

Here's an example snippet of how to use it:

@ExampleComponent = React.createClass
mixins: [HistoryJSMixin]
# so, in your search field, you can save the state to history and set the URL as well below...
#
search: (toSearch)->
handleResults = (err, content)=>
if content.query == @state.search
@setState(searchResults: content.hits)
@saveState(url: '/foo?bar=foo') # BINGO
# hypothetical search function async call../
@index.search toSearch, {}, handleResults

So, as you can see on line 10, you can pass a url key to the call now and have it propagate to the URL bar. I've been using it in places where React Router would be too heavy duty, and all you really want is to propagate search terms, or page number.

views