Skip to content

Instantly share code, notes, and snippets.

@emil-alexandrescu
Created February 26, 2019 16:04
Show Gist options
  • Save emil-alexandrescu/83141d5e7a3a985e8646090f6654b877 to your computer and use it in GitHub Desktop.
Save emil-alexandrescu/83141d5e7a3a985e8646090f6654b877 to your computer and use it in GitHub Desktop.
HOC to take control of search query on url
import React, { Component } from 'react';
import { updateQuery, getQuery, getPathname } from 'lib/history';
import capitalize from 'lodash/capitalize';
import mergeWith from 'lodash/mergeWith';
import merge from 'lodash/merge';
import isArray from 'lodash/isArray';
import isObject from 'lodash/isObject';
function withQuery(name, defaultValues, storeCache = false, cacheIgnoredValues = []) {
return function(WrappedComponent) {
return class extends Component {
constructor(...args) {
super(...args);
const query = getQuery() || {};
let queryData = isObject(query[name]) ?
mergeWith({ ...defaultValues }, query[name], (objValue, srcValue) => {
if (isArray(objValue) || isObject(objValue)) {
return srcValue;
}
}) :
merge({ [name]: defaultValues }, query)[name];
if (storeCache && !query[name]) {
const userId = localStorage.getItem('app-user');
const pathname = getPathname();
const storageData = JSON.parse(localStorage.getItem(`${userId}_${pathname}_${name}`) || '{}');
if (Object.keys(storageData).length) {
queryData = storageData;
// ignoring some keys like date
cacheIgnoredValues.forEach(key => {
delete queryData[key];
});
}
}
this.state = { queryData };
}
@bind
onChange(data) {
const nextQuery = {};
if (!data && data !== false && data !== 0) {
nextQuery[name] = null;
} else {
nextQuery[name] = data;
}
if (storeCache) {
const userId = localStorage.getItem('app-user');
const pathname = getPathname();
localStorage.setItem(`${userId}_${pathname}_${name}`, JSON.stringify(nextQuery[name]));
}
updateQuery(nextQuery);
}
render() {
const capName = capitalize(name);
const newProps = {
[`query${capName}Data`]: this.state.queryData,
[`on${capName}QueryChange`]: this.onChange
};
return <WrappedComponent {...newProps} {...this.props} />;
}
};
};
}
export default withQuery;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment