diff --git a/demo/src/hooks/useContext.js b/demo/src/hooks/useContext.js index 61afe75..32ea82d 100644 --- a/demo/src/hooks/useContext.js +++ b/demo/src/hooks/useContext.js @@ -68,7 +68,7 @@ export default { }, []); return ( - +

{`While somehow weird, we have two notifications for "ComponentWithContextHook" since it is re-rendered regardless of context changes because "Main" is @@ -82,7 +82,7 @@ export default { MemoizedParent - + ); } diff --git a/jsx-dev-runtime.js b/jsx-dev-runtime.js index 20fc158..331fc05 100644 --- a/jsx-dev-runtime.js +++ b/jsx-dev-runtime.js @@ -6,22 +6,20 @@ var origJsxDev = jsxDevRuntime.jsxDEV var wdyrStore = WDYR.wdyrStore module.exports = jsxDevRuntime -module.exports.jsxDEV = function jsxDEV(){ - var args = Array.prototype.slice.call(arguments) - - if(wdyrStore.React && wdyrStore.React.__IS_WDYR__){ +module.exports.jsxDEV = function jsxDEV(...args){ + if (wdyrStore.React && wdyrStore.React.__IS_WDYR__) { var origType = args[0] var rest = args.slice(1) var WDYRType = WDYR.getWDYRType(origType) - if(WDYRType){ - try{ + if (WDYRType) { + try { var element = origJsxDev.apply(null, [WDYRType].concat(rest)) - if(wdyrStore.options.logOwnerReasons){ + if (wdyrStore.options.logOwnerReasons) { WDYR.storeOwnerData(element) } return element - }catch(e){ + } catch(e) { wdyrStore.options.consoleLog('whyDidYouRender JSX transform error. Please file a bug at https://github.com/welldone-software/why-did-you-render/issues.', { errorInfo: { error: e, @@ -33,6 +31,6 @@ module.exports.jsxDEV = function jsxDEV(){ } } } - + return origJsxDev.apply(null, args) } diff --git a/src/wdyrStore.js b/src/wdyrStore.js index 98e4123..a3c2c84 100644 --- a/src/wdyrStore.js +++ b/src/wdyrStore.js @@ -21,7 +21,7 @@ const wdyrStore = { ownerDataMap: new WeakMap(), /* An array of infos for hooks tracked during current render */ - hooksInfoForCurrentRender: [], + hooksInfoForCurrentRender: new WeakMap(), }; export default wdyrStore; diff --git a/src/whyDidYouRender.js b/src/whyDidYouRender.js index 2c82c42..961c2a0 100644 --- a/src/whyDidYouRender.js +++ b/src/whyDidYouRender.js @@ -32,29 +32,29 @@ function getCurrentOwner() { } function trackHookChanges(hookName, { path: pathToGetTrackedHookResult }, rawHookResult) { - const prevResultRef = wdyrStore.React.useRef(initialHookValue); - const prevResult = prevResultRef.current; - const nextResult = pathToGetTrackedHookResult ? get(rawHookResult, pathToGetTrackedHookResult) : rawHookResult; - wdyrStore.hooksInfoForCurrentRender.push({ hookName, result: nextResult }); + const prevResultRef = wdyrStore.React.useRef(initialHookValue); + const prevResult = prevResultRef.current; + prevResultRef.current = nextResult; const ownerInstance = getCurrentOwner(); if (!ownerInstance) { return rawHookResult; } + if (!wdyrStore.hooksInfoForCurrentRender.has(ownerInstance)) { + wdyrStore.hooksInfoForCurrentRender.set(ownerInstance, []); + } + const hooksInfoForCurrentRender = wdyrStore.hooksInfoForCurrentRender.get(ownerInstance); + + hooksInfoForCurrentRender.push({ hookName, result: nextResult }); + const Component = ownerInstance.type.ComponentForHooksTracking || ownerInstance.type; const displayName = getDisplayName(Component); const isShouldTrack = shouldTrack(Component, { isHookChange: true }); - if (!isShouldTrack) { - return rawHookResult; - } - - prevResultRef.current = nextResult; - - if (prevResult !== initialHookValue) { + if (isShouldTrack && prevResult !== initialHookValue) { const notification = getUpdateInfo({ Component: Component, displayName, @@ -142,11 +142,11 @@ export function storeOwnerData(element) { displayName, props: ownerInstance.pendingProps, state: ownerInstance.stateNode ? ownerInstance.stateNode.state : null, - hooksInfo: wdyrStore.hooksInfoForCurrentRender, + hooksInfo: wdyrStore.hooksInfoForCurrentRender.get(ownerInstance) || [], additionalOwnerData, }); - wdyrStore.hooksInfoForCurrentRender = []; + wdyrStore.hooksInfoForCurrentRender.delete(ownerInstance); } } diff --git a/tests/hooks/useContext.test.js b/tests/hooks/useContext.test.js index cef090e..99e68fe 100644 --- a/tests/hooks/useContext.test.js +++ b/tests/hooks/useContext.test.js @@ -33,7 +33,7 @@ describe('hooks - useContext', () => { const OuterComponent = () => { const [currentState, setCurrentState] = React.useState('c'); - React.useEffect(() => { + React.useLayoutEffect(() => { setCurrentState('c'); }, []); @@ -68,7 +68,7 @@ describe('hooks - useContext', () => { const OuterComponent = () => { const [currentState, setCurrentState] = React.useState({ c: 'c' }); - React.useEffect(() => { + React.useLayoutEffect(() => { setCurrentState({ c: 'c' }); }, []); @@ -114,16 +114,16 @@ describe('hooks - useContext', () => { const OuterComponent = () => { const [currentState, setCurrentState] = React.useState({ c: 'c' }); - React.useEffect(() => { + React.useLayoutEffect(() => { setCurrentState({ c: 'c' }); }, []); return ( - +
-
+ ); }; @@ -131,11 +131,7 @@ describe('hooks - useContext', () => { ); - rtl.render( - - ); - - expect(updateInfos).toHaveLength(4); + expect(updateInfos).toHaveLength(2); expect(updateInfos[0].reason).toEqual({ hookDifferences: false, propsDifferences: [], @@ -168,37 +164,5 @@ describe('hooks - useContext', () => { ownerDifferences: false, } })); - expect(updateInfos[2].reason).toEqual({ - hookDifferences: false, - propsDifferences: [], - stateDifferences: false, - ownerDifferences: { - hookDifferences: [{ - differences: [{ - diffType: diffTypes.deepEquals, - pathString: '', - nextValue: { c: 'c' }, - prevValue: { c: 'c' }, - }], - hookName: 'useState', - }], - propsDifferences: false, - stateDifferences: false, - }, - }); - expect(updateInfos[3]).toEqual(expect.objectContaining({ - hookName: 'useContext', - reason: { - hookDifferences: [{ - diffType: diffTypes.deepEquals, - pathString: '', - nextValue: { c: 'c' }, - prevValue: { c: 'c' }, - }], - propsDifferences: false, - stateDifferences: false, - ownerDifferences: false, - } - })); }); });