Project

General

Profile

Download (2.14 KB) Statistics
| Branch: | Tag: | Revision:
import PropTypes from 'prop-types';
import React, { useEffect, useReducer, useCallback } from 'react';

export const CardExpansionContext = React.createContext({});

const cardExpansionReducer = (state, action) => {
// A React reducer, not a Redux one!
switch (action.type) {
case 'expand':
return {
...state,
[action.key]: true,
};
case 'collapse':
return {
...state,
[action.key]: false,
};
case 'add':
if (state[action.key] === undefined) {
return {
...state,
[action.key]: true,
};
}
return state;
case 'expandAll': {
const expandedState = {};
Object.keys(state).forEach(key => {
expandedState[key] = true;
});
return expandedState;
}
case 'collapseAll': {
const collapsedState = {};
Object.keys(state).forEach(key => {
collapsedState[key] = false;
});
return collapsedState;
}
default:
throw new Error(`invalid card expansion type: ${action.type}`);
}
};

export const CardExpansionContextWrapper = ({ children }) => {
const [cardExpandStates, dispatch] = useReducer(cardExpansionReducer, {});
// On mount, get values from localStorage and set them in state
const initializeCardFromLocalStorage = useCallback(key => {
const value = localStorage.getItem(`${key} card expanded`);
if (value !== null && value !== undefined) {
dispatch({ type: value === 'true' ? 'expand' : 'collapse', key });
} else {
dispatch({ type: 'add', key });
}
}, []);
// On unmount, save the values to local storage
// eslint-disable-next-line arrow-body-style
useEffect(() => {
return () =>
Object.entries(cardExpandStates).forEach(([key, value]) =>
localStorage.setItem(`${key} card expanded`, value)
);
});
return (
<CardExpansionContext.Provider
value={{
cardExpandStates,
dispatch,
registerCard: initializeCardFromLocalStorage,
}}
>
{children}
</CardExpansionContext.Provider>
);
};

CardExpansionContextWrapper.propTypes = {
children: PropTypes.node.isRequired,
};
(1-1/4)