Open Michael-Gibbons opened 1 year ago
import { useEffect } from "react" const DEFAULT_OPTIONS = { maxDepth: 10 } export const useNonPrimitiveEffect = (callback, inputDeps, options = DEFAULT_OPTIONS) => { const depthOf = function(object) { var level = 1; for(var key in object) { if (!object.hasOwnProperty(key)) continue; if(typeof object[key] == 'object'){ var depth = depthOf(object[key]) + 1; level = Math.max(depth, level); } } return level; } if(depthOf(inputDeps) > options.maxDepth){ throw new Error("Error in useNonPrimitiveEffect, max depth exceeded. This is either an infinite loop or you may need to increase the max depth in useNonPrimitiveEffect.") } if(!Array.isArray(inputDeps)){ throw new Error("Error in useNonPrimitiveEffect, dependencies must be an array. Exactly the same as React's useEffect.") } const reducer = (values, propValue) => { if (Array.isArray(propValue)) { values = unwrapArray(propValue).reduce(reducer, values); } else if (typeof propValue === 'object' && propValue !== null) { values = Object.values(propValue).reduce(reducer, values); } else { values.push(propValue); } return values; }; const unwrapArray = (values) => { let unwrapped = []; values.forEach((value) => { if (Array.isArray(value)) { unwrapped = unwrapped.concat(unwrapArray(value)); } else { reducer(unwrapped, value); } }); return unwrapped; }; let watchDeps; if (Array.isArray(inputDeps)) { watchDeps = unwrapArray(inputDeps).reduce(reducer, []); } else { watchDeps = Object.values(inputDeps).reduce(reducer, []); } useEffect(() => { callback(); }, [watchDeps]); }