Skip to content

Commit 9b857a1

Browse files
authored
[URH-26] useHover ์‹ ๊ทœ (#29)
* โœจ feat: useHover ์‹ ๊ทœ * ๐Ÿ”จ refactor: ์ œ๋„ˆ๋ฆญ ํƒ€์ž… ์ ์šฉ * ๐Ÿ› fix: ์กฐ๊ฑด๋ถ€ ๋ Œ๋”๋ง ์‹œ useHover ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ๋ฒ„๊ทธ
1 parent 62a451e commit 9b857a1

File tree

2 files changed

+69
-0
lines changed

2 files changed

+69
-0
lines changed

โ€Žsrc/hooks/useHover.test.tsx

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import '@testing-library/jest-dom';
2+
import { render, screen, fireEvent } from '@testing-library/react';
3+
4+
import useHover from './useHover';
5+
6+
const TestComponent = () => {
7+
const [hovered, ref] = useHover<HTMLDivElement>();
8+
9+
return (
10+
<div data-testid="test-component" ref={ref}>
11+
{`${hovered}`}
12+
</div>
13+
);
14+
};
15+
16+
describe('useHover', () => {
17+
let testComponent: HTMLElement;
18+
19+
beforeEach(() => {
20+
render(<TestComponent />);
21+
testComponent = screen.getByTestId('test-component');
22+
});
23+
24+
test('hovered์˜ ์ดˆ๊นƒ๊ฐ’์€ false์ด๋‹ค.', () => {
25+
expect(testComponent).toHaveTextContent('false');
26+
});
27+
28+
test('ref ์ปดํฌ๋„ŒํŠธ์— mouseenter ์‹œ hovered์˜ ๊ฐ’์€ true์ด๋‹ค.', () => {
29+
fireEvent.mouseEnter(testComponent);
30+
expect(testComponent).toHaveTextContent('true');
31+
});
32+
33+
test('ref ์ปดํฌ๋„ŒํŠธ์— mouseenter ํ›„ mouseleave ์‹œ hovered์˜ ๊ฐ’์€ false์ด๋‹ค.', () => {
34+
fireEvent.mouseEnter(testComponent);
35+
expect(testComponent).toHaveTextContent('true');
36+
fireEvent.mouseLeave(testComponent);
37+
expect(testComponent).toHaveTextContent('false');
38+
});
39+
});

โ€Žsrc/hooks/useHover.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { useCallback, useRef, useState } from 'react';
2+
3+
const useHover = <T extends HTMLElement>(): [boolean, (node: T) => void] => {
4+
const ref = useRef<T | null>(null);
5+
const [isHovered, setIsHovered] = useState(false);
6+
7+
const handleMouseEnter = useCallback(() => setIsHovered(true), []);
8+
const handleMouseLeave = useCallback(() => setIsHovered(false), []);
9+
10+
const callbackRef = useCallback(
11+
(node: T) => {
12+
if (ref.current) {
13+
ref.current.removeEventListener('mouseenter', handleMouseEnter);
14+
ref.current.removeEventListener('mouseleave', handleMouseLeave);
15+
}
16+
17+
ref.current = node;
18+
19+
if (ref.current) {
20+
ref.current.addEventListener('mouseenter', handleMouseEnter);
21+
ref.current.addEventListener('mouseleave', handleMouseLeave);
22+
}
23+
},
24+
[handleMouseEnter, handleMouseLeave]
25+
);
26+
27+
return [isHovered, callbackRef];
28+
};
29+
30+
export default useHover;

0 commit comments

Comments
ย (0)