Wednesday, 14 October 2020

creating a persistant data hook that supports functions

Ok so I am creating this awesome hook to persist filter state, now some of my filters include not only simple strings that can be saved to local storage and then retrieved but also more complex objects such as dates which in many cases contain functions, the idea is to able to store and then retrieve these functions from local storage.

Here is the hook:

export default function usePersistedState(key, defaultValue) {
  let transformedFuncs = parseWithFunc(localStorage.getItem(key))
  const [state, setState] = React.useState(
    () =>  transformedFuncs || defaultValue
  );
  
  React.useEffect(() => {
      if (key){
        localStorage.setItem(key, stringifyWithFunc(state));
      }
  }, [key, state]);
  return [state, setState];
}

function stringifyWithFunc(obj) {
  return JSON.stringify(obj, function(key, value) {
      return typeof value === "function" ? value.toString() : value;
  });
} 

function parseWithFunc(json) {
  return JSON.parse(json, function(key, value) {
      if (isFunction(key)) {
          return transformFunc(value);
      } else {
          return value; 
      }
  });
}

function isFunction(key) {
  switch (key){
    case "toOption":
      return true
    case "transform":
      return true
    case "validate":
      return true
    default:
      return false
  }
}
function transformFunc(value) {
  return eval(value);
}

Now I was successful in stringfying all my properties including the functions thanks to the replacer option for JSON.stringify that was referenced here, I was also able to "revive" my functions with the reviveroption for JSON.parse (also referenced above), the issue is that some of the functions I get back in my app from local storage have imported functions (luxon date functions) from webpack, so I get the following error:

Unhandled Rejection (ReferenceError): _utils_common__WEBPACK_IMPORTED_MODULE_11__ is not defined
eval
src/Components/hooks/usePersistedState.js:46
  43 |   }
  44 | }
  45 | function transformFunc(value) {
> 46 |   return eval(value);
  47 | }
  48 | 

The issue: the eval is not able to convert or access the _utils_common__WEBPACK_IMPORTED_MODULE_11__ this is just a simple shared function in the app.
Things I tried: I tried just doing the function locally but still got the same error since I use date transformation functions from luxon which I cannot simply do myself.
Things I would rather not do: Pass my hooks callback functions.
What I am looking for is a way to hydrate/rehydrate my functions from local storage so that I can then go ahead and use them in the app.



from creating a persistant data hook that supports functions

No comments:

Post a Comment