Skip to content

Instantly share code, notes, and snippets.

@garrytan
Created August 31, 2015 03:56
Show Gist options
  • Select an option

  • Save garrytan/bd89e582f54e5350387f to your computer and use it in GitHub Desktop.

Select an option

Save garrytan/bd89e582f54e5350387f to your computer and use it in GitHub Desktop.
/** 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();
}
},
};
@garrytan
Copy link
Author

This is a version of Leif Denby's HistoryJSMixin that allows history.js to interoperate cleanly with react's state changes, only with durable URLs that get changed and reflected in the user history. One thing I really wanted was to have durable URLs so that as the user modified state (e.g. for a faceted search interface using Algolia) you could easily copy and paste the URL and return to this page. It also works great for pagination.

All I did was be sure to pass a URL as well to the History API on line 57 and 61.

I hope this is helpful for someone else who wants to have simple state persisted from React state to the URL / pushState, but without all the bells and whistles of having to include something like React Router.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment