diff --git a/.changeset/tasty-starfishes-care.md b/.changeset/tasty-starfishes-care.md new file mode 100644 index 00000000..cb5459fd --- /dev/null +++ b/.changeset/tasty-starfishes-care.md @@ -0,0 +1,5 @@ +--- +"@nf-team/react": minor +--- + +feat(DelayRenderComponent): 컴포넌트가 랜더링하는 경우에도 delay를 걸 수 있도록 props 추가 및 delay props명 변경 diff --git a/packages/react/src/components/DelayRenderComponent.test.tsx b/packages/react/src/components/DelayRenderComponent.test.tsx index b6773dd3..c200dcea 100644 --- a/packages/react/src/components/DelayRenderComponent.test.tsx +++ b/packages/react/src/components/DelayRenderComponent.test.tsx @@ -24,37 +24,83 @@ describe('DelayRenderComponent', () => { )); - context('isVisible이 true인 경우', () => { - given('initialState', () => false); - given('isVisible', () => true); + describe('컴포넌트의 unRendering을 지연시킨다', () => { + given('unRenderDelay', () => delay); - it('자식 컴포넌트가 나타나야만 한다', () => { - const { container } = renderDelayRenderComponent(); + context('isVisible이 true인 경우', () => { + given('initialState', () => false); + given('isVisible', () => true); - expect(container).toHaveTextContent(childComponentText); + it('자식 컴포넌트가 나타나야만 한다', () => { + const { container } = renderDelayRenderComponent(); + + act(() => { + jest.advanceTimersByTime(0); + }); + + expect(container).toHaveTextContent(childComponentText); + }); + }); + + context('isVisible이 false인 경우', () => { + given('initialState', () => true); + given('isVisible', () => false); + + it(`${delay}ms 뒤에 아무것도 나타나지 않아야만 한다`, () => { + const { container } = renderDelayRenderComponent(); + + expect(container).toHaveTextContent(childComponentText); + + act(() => { + jest.advanceTimersByTime(200); + }); + + expect(container).toBeEmptyDOMElement(); + }); }); }); - context('isVisible이 false인 경우', () => { - given('initialState', () => true); - given('isVisible', () => false); + describe('컴포넌트의 rendering을 지연시킨다', () => { + given('renderDelay', () => delay); + given('unRenderDelay', () => 0); + + context('isVisible이 true인 경우', () => { + given('initialState', () => false); + given('isVisible', () => true); - it(`${delay}ms 뒤에 아무것도 나타나지 않아야만 한다`, () => { - const { container } = renderDelayRenderComponent(); + it('자식 컴포넌트가 나타나야만 한다', () => { + const { container } = renderDelayRenderComponent(); - expect(container).toHaveTextContent(childComponentText); + act(() => { + jest.advanceTimersByTime(200); + }); - act(() => { - jest.advanceTimersByTime(200); + expect(container).toHaveTextContent(childComponentText); }); + }); + + context('isVisible이 false인 경우', () => { + given('initialState', () => true); + given('isVisible', () => false); - expect(container).toBeEmptyDOMElement(); + it(`${delay}ms 뒤에 아무것도 나타나지 않아야만 한다`, () => { + const { container } = renderDelayRenderComponent(); + + expect(container).toHaveTextContent(childComponentText); + + act(() => { + jest.advanceTimersByTime(0); + }); + + expect(container).toBeEmptyDOMElement(); + }); }); }); }); diff --git a/packages/react/src/components/DelayRenderComponent.tsx b/packages/react/src/components/DelayRenderComponent.tsx index d1e0ce35..3b919426 100644 --- a/packages/react/src/components/DelayRenderComponent.tsx +++ b/packages/react/src/components/DelayRenderComponent.tsx @@ -5,35 +5,42 @@ import useBoolean from '../hooks/useBoolean'; interface Props { isVisible: boolean; initialRenderState?: boolean; - delay?: number; + unRenderDelay?: number; + renderDelay?: number; } function DelayRenderComponent({ - isVisible, delay = 400, initialRenderState = false, children, + isVisible, unRenderDelay = 400, renderDelay = 0, initialRenderState = false, children, }: PropsWithChildren) { const [isRender, onRender, unRender] = useBoolean(initialRenderState); - const timer = useRef | null>(null); + const unRenderTimer = useRef>(); + const renderTimer = useRef>(); useEffect(() => { if (isVisible) { - onRender(); + renderTimer.current = setTimeout(() => { + onRender(); + renderTimer.current = undefined; + }, renderDelay); } - }, [onRender, isVisible]); + + return () => { + clearTimeout(renderTimer.current); + }; + }, [onRender, renderDelay, isVisible]); useEffect(() => { if (!isVisible) { - timer.current = setTimeout(() => { + unRenderTimer.current = setTimeout(() => { unRender(); - timer.current = null; - }, delay); + unRenderTimer.current = undefined; + }, unRenderDelay); } return () => { - if (timer.current) { - clearTimeout(timer.current); - } + clearTimeout(unRenderTimer.current); }; - }, [unRender, delay, isVisible]); + }, [unRender, unRenderDelay, isVisible]); if (!isRender) { return null;