-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(@yourssu/react): create useSecTimer, useMediaQuery (#22)
* docs: modify useInterval md & add english md * feat(react): create useSecTimer * feat(react): create useMediaQuery
- Loading branch information
Showing
12 changed files
with
438 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# useInterval | ||
|
||
`useInterval` custom hook is used to execute a given callback function at a specified interval. | ||
This hook utilizes `useEffect` and `useRef` to manage the callback function and interval timer. | ||
|
||
## API | ||
|
||
```ts | ||
useInterval(callback: () => void, interval: number) | ||
``` | ||
|
||
#### Parameters | ||
|
||
- `callback` (function): The callback function to be executed. | ||
- `interval` (number): The interval (in milliseconds) at which the callback function will be executed. | ||
|
||
## Example | ||
|
||
```jsx | ||
const MyComponent = () => { | ||
useInterval(() => { | ||
console.log('This will run every second'); | ||
}, 1000); | ||
|
||
return <div>Check the console</div>; | ||
}; | ||
``` | ||
|
||
## Notes | ||
|
||
This hook internally uses two `useEffect` hooks: | ||
|
||
1. The first `useEffect` keeps the callback function up to date. | ||
2. The second `useEffect` sets up a timer to execute the callback function at the given interval. | ||
|
||
If the `interval` changes or is set to `null`, the timer will be updated or cleared accordingly. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# useMediaQuery | ||
|
||
`useMediaQuery` is a custom React hook that allows you to easily use media queries in your React components. | ||
It leverages the `window.matchMedia` API to listen for changes in the viewport and determine if a specified media query matches the current state of the viewport. | ||
|
||
## API | ||
|
||
```ts | ||
useMediaQuery(query: string); | ||
``` | ||
|
||
### Parameters | ||
|
||
- `query` (string): A media query string that you want to match against the current viewport. | ||
|
||
### Return value | ||
|
||
- `isMatch` (boolean): A boolean value indicating whether the media query matches the current viewport. | ||
|
||
## Examples | ||
|
||
```jsx | ||
import { useMediaQuery } from './useMediaQuery'; | ||
|
||
const MyComponent = () => { | ||
const isLargeScreen = useMediaQuery('(min-width: 1024px)'); | ||
|
||
return ( | ||
<div> | ||
{isLargeScreen ? ( | ||
<p>The viewport is at least 1024 pixels wide</p> | ||
) : ( | ||
<p>The viewport is less than 1024 pixels wide</p> | ||
)} | ||
</div> | ||
); | ||
}; | ||
``` | ||
|
||
## Notes | ||
|
||
- This hook relies on the `window.matchMedia` API, which is widely supported in modern browsers. However, for older browsers, you might need to include a polyfill. | ||
- Ensure that the `query` parameter is correctly formatted as a valid media query string. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# useMediaQuery | ||
|
||
`useMediaQuery`는 React 컴포넌트에서 미디어 뭐리를 쉽게 사용할 수 있게 해주는 커스텀 React 훅입니다. | ||
이 훅은 `window.matchMedia` API를 활용하여 뷰포트의 상태 변화를 감지하고 지정된 미디어 쿼리가 현재 뷰포트와 일치하는지 확인합니다. | ||
|
||
## API | ||
|
||
```ts | ||
useMediaQuery(query: string); | ||
``` | ||
|
||
### Parameters | ||
|
||
- `query` (string): 현재 뷰포트와 일치시키고자 하는 미디어 쿼리 문자열입니다. | ||
|
||
### Return value | ||
|
||
- `isMatch` (boolean): 미디어 쿼리가 현재 뷰포트와 일치하는지 boolean 값으로 나타냅니다. | ||
|
||
## Examples | ||
|
||
```jsx | ||
import { useMediaQuery } from './useMediaQuery'; | ||
|
||
const MyComponent = () => { | ||
const isLargeScreen = useMediaQuery('(min-width: 1024px)'); | ||
|
||
return ( | ||
<div> | ||
{isLargeScreen ? ( | ||
<p>The viewport is at least 1024 pixels wide</p> | ||
) : ( | ||
<p>The viewport is less than 1024 pixels wide</p> | ||
)} | ||
</div> | ||
); | ||
}; | ||
``` | ||
|
||
## Notes | ||
|
||
- 이 훅은 최신 브라우저에서 널리 지원되는 `window.matchMedia` API에 의존합니다. 그러나 오래된 브라우저의 경우 폴리필을 포함해야 할 수도 있습니다. | ||
- `query` 매개변수가 유효한 미디어 쿼리 문자열로 올바르게 포맷되어 있는지 확인해야 합니다. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import { renderHook } from '@testing-library/react'; | ||
import { describe, it, expect, vi } from 'vitest'; | ||
|
||
import { useMediaQuery } from './useMediaQuery'; | ||
|
||
// Browser environment | ||
describe('useMediaQuery - Browser', () => { | ||
it('should return true when the query matches', () => { | ||
const query = '(min-width: 600px)'; | ||
|
||
// setting jsdom environment | ||
Object.defineProperty(window, 'matchMedia', { | ||
writable: true, | ||
value: (query: string) => ({ | ||
matches: query === '(min-width: 600px)', | ||
media: query, | ||
onchange: null, | ||
addEventListener: vi.fn(), | ||
removeEventListener: vi.fn(), | ||
}), | ||
}); | ||
|
||
const { result } = renderHook(() => useMediaQuery(query)); | ||
expect(result.current).toBe(true); | ||
}); | ||
|
||
it('should return false when the query does not match', () => { | ||
const query = '(max-width: 599px)'; | ||
|
||
// setting jsdom environment | ||
Object.defineProperty(window, 'matchMedia', { | ||
writable: true, | ||
value: (query: string) => ({ | ||
matches: query === '(max-width: 599px)', | ||
media: query, | ||
onchange: null, | ||
addEventListener: vi.fn(), | ||
removeEventListener: vi.fn(), | ||
}), | ||
}); | ||
|
||
const { result } = renderHook(() => useMediaQuery(query)); | ||
expect(result.current).toBe(true); | ||
}); | ||
}); | ||
|
||
// Node.js environment | ||
describe('useMediaQuery - Node.js', () => { | ||
it('should return false when running on server side', () => { | ||
const query = '(min-width: 600px)'; | ||
|
||
const { result } = renderHook(() => useMediaQuery(query)); | ||
expect(result.current).toBe(false); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { useEffect, useState } from 'react'; | ||
|
||
/** | ||
* `useMediaQuery` 커스텀 훅은 뷰포트의 크기를 감지하고, 주어진 쿼리와 일치하는지 확인합니다. | ||
* | ||
* @param {string} query - 미디어 쿼리 문자열입니다. | ||
* @returns {boolean} 미디어 쿼리가 현재 뷰포트와 일치하는지 여부를 반환합니다. | ||
*/ | ||
export const useMediaQuery = (query: string) => { | ||
const [isMatch, setIsMatch] = useState(false); | ||
|
||
useEffect(() => { | ||
// If window is not defined, it means that the code is running on the server side. | ||
if (typeof window === 'undefined') { | ||
return; | ||
} | ||
|
||
const mediaQuery = window.matchMedia(query); | ||
setIsMatch(mediaQuery.matches); | ||
|
||
const listener = () => setIsMatch(mediaQuery.matches); | ||
|
||
mediaQuery.addEventListener('change', listener); | ||
|
||
return () => mediaQuery.removeEventListener('change', listener); | ||
}, [query]); | ||
|
||
return isMatch; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
# useSecTimer | ||
|
||
`useSecTimer` is a custom React hook that provides a countdown timer functionality. | ||
It allows you to set a timer that counts down from a specified number of seconds and provides functions to reset the timer and check if the timer has ended. | ||
|
||
## Features | ||
|
||
- Countdown Timer: Start a timer from a specified number of seconds and countdown to 0. | ||
- Reset Functionality: Reset the timer to the initial value. | ||
- Timer End Check: Easily check if the timer has reached 0. | ||
|
||
## API | ||
|
||
```ts | ||
useSecTimer(seconds: number) | ||
``` | ||
|
||
### Parameters | ||
|
||
- `seconds` (number): The initial number of seconds for the countdown timer. | ||
|
||
### Return value | ||
|
||
- `leftTime` (number): The current time left on the timer in seconds. | ||
- `isTimerEnd` (boolean): A boolean value that indicates whether the timer has reached 0. | ||
- `resetTimer` (function): A function to reset the timer to the initial value. | ||
|
||
## Examples | ||
|
||
```jsx | ||
const TimerComponent = () => { | ||
const { leftTime, isTimerEnd, resetTimer } = useSecTimer(10); | ||
|
||
return ( | ||
<div> | ||
<div>Left time: {leftTime} seconds</div> | ||
<div>Timer end: {isTimerEnd ? 'Yes' : 'No'}</div> | ||
<button onClick={resetTimer}>Reset</button> | ||
</div> | ||
); | ||
}; | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
# useSecTimer | ||
|
||
`useSecTimer` 훅은 주어진 시간(초)에서 시작하여 0까지 카운트다운하는 타이머 기능을 제공합니다. | ||
타이머를 초기화하고, 타이머 종료 여부를 확인할 수 있습니다. | ||
|
||
## Features | ||
|
||
- 카운트다운 타이머: 주어진 시간(초)에서 시작하여 0까지 카운트다운합니다. | ||
- 리셋 기능: 타이머를 처음 값으로 초기화할 수 있습니다. | ||
- 타이머 종료 확인: 타이머 종료 여부를 확인할 수 있습니다. | ||
|
||
## API | ||
|
||
```ts | ||
useSecTimer(seconds: number) | ||
``` | ||
|
||
### Parameters | ||
|
||
- `seconds` (number): 카운트다운 타이머의 시간(초)입니다. | ||
|
||
### Return value | ||
|
||
- `leftTime` (number): 타이머에 남은 시간(초)입니다. | ||
- `isTimerEnd` (boolean): 타이머가 0에 도달했는지 여부를 나타냅니다. | ||
- `resetTimer` (function): 타이머를 처음 값으로 초기화하는 함수입니다. | ||
|
||
## Examples | ||
|
||
```jsx | ||
const TimerComponent = () => { | ||
const { leftTime, isTimerEnd, resetTimer } = useSecTimer(10); | ||
|
||
return ( | ||
<div> | ||
<div>Left time: {leftTime} seconds</div> | ||
<div>Timer end: {isTimerEnd ? 'Yes' : 'No'}</div> | ||
<button onClick={resetTimer}>Reset</button> | ||
</div> | ||
); | ||
}; | ||
``` |
Oops, something went wrong.