From 79339711f9da1c9f22e0dc021a98fa7cdb499302 Mon Sep 17 00:00:00 2001 From: Mohamed Khelif Date: Tue, 6 Jun 2023 16:16:45 -0400 Subject: [PATCH] EVG-20089 Add useEffectDebugger hook (#1878) --- src/test_utils/hooks.ts | 68 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 src/test_utils/hooks.ts diff --git a/src/test_utils/hooks.ts b/src/test_utils/hooks.ts new file mode 100644 index 0000000000..26baf7d417 --- /dev/null +++ b/src/test_utils/hooks.ts @@ -0,0 +1,68 @@ +import { DependencyList, EffectCallback, useEffect, useRef } from "react"; + +/** + * `usePrevious` is a custom hook that returns the previous value of a given value + * @param value + * @param initialValue + * @returns - the previous value + */ +const usePrevious = (value: T, initialValue: T) => { + const ref = useRef(initialValue); + useEffect(() => { + ref.current = value; + }); + return ref.current; +}; + +/** + * `useEffectDebugger` is a custom hook that logs the changed dependencies of a useEffect hook + * + * @param effectHook - the effect hook + * @param dependencies - an array of dependencies + * @param dependencyNames - an array of strings that correspond to the dependencies + */ +const useEffectDebugger = ( + effectHook: EffectCallback, + dependencies: DependencyList, + dependencyNames: string[] = [] +) => { + if (process.env.NODE_ENV !== "development") { + console.warn( + "[use-effect-debugger] This hook should only be used in development!" + ); + } + if (dependencies.length !== dependencyNames.length) { + console.warn( + "[use-effect-debugger] The number of dependencies and dependency names should be the same!" + ); + } + const previousDeps = usePrevious(dependencies, []); + + const changedDeps = dependencies.reduce( + (accum: Record, dependency, index) => { + if (dependency !== previousDeps[index]) { + const keyName = dependencyNames[index] || index; + return { + ...accum, + [keyName]: { + before: previousDeps[index], + after: dependency, + }, + }; + } + + return accum; + }, + {} as Record + ); + + if (Object.keys(changedDeps).length) { + console.log("[use-effect-debugger] "); + console.table(changedDeps); + } + + // eslint-disable-next-line react-hooks/exhaustive-deps + useEffect(effectHook, dependencies); +}; + +export { useEffectDebugger };