Skip to content

Instantly share code, notes, and snippets.

@mikeapr4
Created August 2, 2018 11:56
Show Gist options
  • Save mikeapr4/ed34e071d7ed563a3747cfbaf67ba4c6 to your computer and use it in GitHub Desktop.
Save mikeapr4/ed34e071d7ed563a3747cfbaf67ba4c6 to your computer and use it in GitHub Desktop.
Reactive-compatible Moment.js Instances
import moment from 'moment';
import 'moment-timezone';
// Make all fields on `object` hidden (not enumerable)
// except any in the whitelist.
const hideFields = (object, whitelist) => Object.keys(object)
.forEach((field) => {
if (!whitelist.includes(field)) {
const val = object[field];
Object.defineProperty(object, field, {
value: val,
configurable: true,
writable: true,
enumerable: false,
});
}
});
/**
* Modify Moment locales and timezones so that only the identifier field
* is enumerable, this way the other data will be hidden from reactivity.
*
* Individual Moment instances can be reactive and if they have Locale or TZ
* changed, it will trigger reactivity, but changes to the Locale or TZ
* shared objects won't cause problems.
*/
moment.locales().forEach((code) => {
const locale = moment.localeData(code);
hideFields(locale, ['_abbr']);
});
moment.tz.names().forEach((tz) => {
const zone = moment.tz.zone(tz);
hideFields(zone, ['name']);
});
import { Store } from 'vuex';
const store = new Store({
...
});
const rehydrateMoments = (obj) => {
const queue = [obj];
while (queue.length) {
const item = queue.shift();
if (typeof item === 'object' && item !== null) {
if (Array.isArray(item)) {
queue.push(...item);
} else if (item._isAMomentObject) { // Found a Moment instance
Object.setPrototypeOf(item, moment.prototype);
// Reassign the TZ and Locale shared objects (only the identifier fields are in the snapshot)
// This also ensures the moment instance has references to Objects which themselves have
// the correct prototype (rather than plain Object deserialized versions)
item.tz(item.tz());
item.locale(item.locale());
} else {
queue.push(...Object.values(item));
}
}
}
};
const oldReplace = store.replaceState;
store.replaceState = function replaceState(state) {
rehydrateMoments(state);
return oldReplace.call(this, state);
};
@mikeapr4
Copy link
Author

mikeapr4 commented Aug 2, 2018

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