Skip to content

Instantly share code, notes, and snippets.

@Problematic
Last active February 20, 2019 00:12
Show Gist options
  • Save Problematic/b6e617409856c8aaff9a7349561df7e3 to your computer and use it in GitHub Desktop.
Save Problematic/b6e617409856c8aaff9a7349561df7e3 to your computer and use it in GitHub Desktop.
import React, { useState, useMemo, useContext } from 'react';
interface ToggleState {
items: any[];
toggleItem: (item: any, toggled?: boolean) => boolean;
}
const ToggleContext = React.createContext<ToggleState>({
items: [],
toggleItem: () => false,
});
const ToggleManager: React.FC<{ comparator: (a: any, b: any) => boolean }> = ({ children, comparator = (a, b) => a === b }) => {
const [items, setItems] = useState<any[]>([]);
const context = useMemo<ToggleState>(() => ({
items,
toggleItem: (item: any, toggled?: boolean) => {
const remove = toggled === false || (toggled === undefined && items.some(el => comparator(el, item)));
if (remove) {
setItems(items.filter(el => !comparator(el, item)));
return false;
} else {
setItems([...items, item]);
return true;
}
}
}), [items]);
return (
<ToggleContext.Provider value={context}>
{children}
</ToggleContext.Provider>
)
}
const useToggle = (item: any): [boolean, (toggled?: boolean) => boolean] => {
const { items, toggleItem: toggle } = useContext(ToggleContext);
return [
items.includes(item),
(toggled?: boolean) => toggle(item, toggled)
];
}
export default ToggleManager;
export {
useToggle,
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment