Skip to content

Instantly share code, notes, and snippets.

@willhoney7
Last active April 17, 2018 15:25
Show Gist options
  • Save willhoney7/d36cee94feba249b3c1526b91be9032d to your computer and use it in GitHub Desktop.
Save willhoney7/d36cee94feba249b3c1526b91be9032d to your computer and use it in GitHub Desktop.
A React localStorage render props component
// MIT License
// By Will Honey at Operational Results, Inc.
import React from 'react';
import PropTypes from 'prop-types';
const SUPPORTS_LOCAL_STORAGE = (function() {
try {
localStorage.setItem('a', 1);
localStorage.removeItem('a');
return true;
} catch (e) {
return false;
}
})();
export default class LocalStorage extends React.Component {
static propTypes = {
storageKey: PropTypes.string.isRequired,
render: PropTypes.func.isRequired,
defaultValue: PropTypes.any
};
getStorageValue = storageKey => {
if (SUPPORTS_LOCAL_STORAGE) {
try {
const value = localStorage.getItem(storageKey);
return value !== undefined && value !== null ? JSON.parse(value).value : undefined;
} catch (er) {
console.warn('Failed to use localStorage. Falling back to component state', er);
}
}
};
setStorageValue = (storageKey, value) => {
if (SUPPORTS_LOCAL_STORAGE) {
try {
localStorage.setItem(storageKey, JSON.stringify({ value }));
} catch (er) {
console.warn('Failed to use localStorage. Falling back to component state', er);
}
}
};
constructor(props) {
super(props);
const storageValue = this.getStorageValue(this.props.storageKey);
this.state = { value: storageValue !== undefined ? storageValue : this.props.defaultValue };
}
setValue = value => {
this.setState({ value });
this.setStorageValue(this.props.storageKey, value);
};
render() {
return this.props.render(this.state.value, this.setValue);
}
}
export const withLocalStorage = localStorageProps => Component => props => (
<LocalStorage
{...localStorageProps}
render={(value, setValue) => <Component value={value} setValue={setValue} {...props} />}
/>
);
@willhoney7
Copy link
Author

willhoney7 commented Apr 17, 2018

Usage

<LocalStorage key="localStorageKey" defaultValue="" render={
  (value, setValue) => <input value={value} onChange={e => setValue(e.target.value)} />
}/>   

or

const ComponentWithLocalStorage = withLocalStorage({ key: "localStorageKey" })(Component);
<ComponentWithLocalStorage> hi </ComponentWithLocalStorage>

Notes

This won't work well if you need to access the same localStorage value in different locations. They will get out of sync. If you need that, use React 16.3's new context API.

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