Skip to content

Commit d7b6f87

Browse files
author
Brian Vaughn
committed
Add failing test for passive effects cleanup functio not being called for memoized components
1 parent 2cfd73c commit d7b6f87

File tree

1 file changed

+69
-0
lines changed

1 file changed

+69
-0
lines changed

packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2734,6 +2734,75 @@ describe('ReactHooksWithNoopRenderer', () => {
27342734
expect(ReactNoop.getChildren()).toEqual([]);
27352735
});
27362736
});
2737+
2738+
it('calls passive effect destroy functions for memoized components', () => {
2739+
const Wrapper = ({children}) => children;
2740+
function Child({prop}) {
2741+
React.useEffect(() => {
2742+
Scheduler.unstable_yieldValue('passive create');
2743+
return () => {
2744+
Scheduler.unstable_yieldValue('passive destroy');
2745+
};
2746+
}, [prop]);
2747+
React.useLayoutEffect(() => {
2748+
Scheduler.unstable_yieldValue('layout create');
2749+
return () => {
2750+
Scheduler.unstable_yieldValue('layout destroy');
2751+
};
2752+
}, [prop]);
2753+
Scheduler.unstable_yieldValue('render');
2754+
return null;
2755+
}
2756+
2757+
const isEqual = (prevProps, nextProps) =>
2758+
prevProps.prop === nextProps.prop;
2759+
const MemoizedChild = React.memo(Child, isEqual);
2760+
2761+
act(() => {
2762+
ReactNoop.render(
2763+
<Wrapper>
2764+
<MemoizedChild key={1} />
2765+
</Wrapper>,
2766+
);
2767+
});
2768+
expect(Scheduler).toHaveYielded([
2769+
'render',
2770+
'layout create',
2771+
'passive create',
2772+
]);
2773+
2774+
act(() => {
2775+
ReactNoop.render(
2776+
<Wrapper>
2777+
<MemoizedChild key={1} />
2778+
</Wrapper>,
2779+
);
2780+
});
2781+
expect(Scheduler).toHaveYielded([]);
2782+
2783+
// This update is exists to test an internal implementation detail:
2784+
// Effects without updating dependencies lose their layout/passive tag during an update.
2785+
act(() => {
2786+
ReactNoop.render(
2787+
<Wrapper>
2788+
<MemoizedChild key={2} />
2789+
</Wrapper>,
2790+
);
2791+
});
2792+
expect(Scheduler).toHaveYielded([
2793+
'render',
2794+
'layout destroy',
2795+
'layout create',
2796+
'passive destroy',
2797+
'passive create',
2798+
]);
2799+
2800+
// Unmount the component and verify that passive destroy functions are deferred until post-commit.
2801+
act(() => {
2802+
ReactNoop.render(null);
2803+
});
2804+
expect(Scheduler).toHaveYielded(['layout destroy', 'passive destroy']);
2805+
});
27372806
});
27382807

27392808
describe('useLayoutEffect', () => {

0 commit comments

Comments
 (0)