OSB
OSB copied to clipboard
add useNonPrimitiveEffect hook
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]);
}