Skip to content

Commit

Permalink
Merge pull request #43 from mbti-nf-team/feat/DelayRenderComponent
Browse files Browse the repository at this point in the history
  • Loading branch information
saseungmin authored Sep 1, 2023
2 parents 1da4f63 + 87919f2 commit 37ea880
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 28 deletions.
5 changes: 5 additions & 0 deletions .changeset/tasty-starfishes-care.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@nf-team/react": minor
---

feat(DelayRenderComponent): 컴포넌트가 랜더링하는 경우에도 delay를 걸 수 있도록 props 추가 및 delay props명 변경
78 changes: 62 additions & 16 deletions packages/react/src/components/DelayRenderComponent.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,37 +24,83 @@ describe('DelayRenderComponent', () => {
<DelayRenderComponent
initialRenderState={given.initialState}
isVisible={given.isVisible}
delay={delay}
unRenderDelay={given.unRenderDelay}
renderDelay={given.renderDelay}
>
<MockComponent />
</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();
});
});
});
});
31 changes: 19 additions & 12 deletions packages/react/src/components/DelayRenderComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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<Props>) {
const [isRender, onRender, unRender] = useBoolean(initialRenderState);
const timer = useRef<ReturnType<typeof setTimeout> | null>(null);
const unRenderTimer = useRef<ReturnType<typeof setTimeout>>();
const renderTimer = useRef<ReturnType<typeof setTimeout>>();

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;
Expand Down

0 comments on commit 37ea880

Please sign in to comment.