From 2c9e07b9285980d6985ca97b6ced9f4e7babf56d Mon Sep 17 00:00:00 2001 From: YEONGJAE LEE <71895560+lee0jae330@users.noreply.github.com> Date: Thu, 5 Dec 2024 12:27:25 +0900 Subject: [PATCH] =?UTF-8?q?[#238]=20=ED=99=88=ED=8E=98=EC=9D=B4=EC=A7=80?= =?UTF-8?q?=20=EC=B4=88=EA=B8=B0=20=EB=A1=9C=EB=94=A9=20=EC=8B=9C=20?= =?UTF-8?q?=EC=8A=A4=EC=BC=88=EB=A0=88=ED=86=A4=20UI=20=EC=A0=81=EC=9A=A9?= =?UTF-8?q?=20=EB=B0=8F=20code-highlighter=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EC=8A=A4=ED=86=A0=EB=A6=AC=EB=B6=81=20=EC=A0=9C?= =?UTF-8?q?=EC=9E=91=20(#239)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ๐Ÿ™€ chore: ๋กœ๋”ฉ ์‹œ ์Šค์ผˆ๋ ˆํ†ค UI ์ถ”๊ฐ€ ๋ฐ ๋ฌดํ•œ์Šคํฌ๋กค ์ปค์Šคํ…€ ํ›…์œผ๋กœ ๋ถ„๋ฆฌ * โœจ feat: ์ฝ”๋“œ high-lighter storybook ์ถ”๊ฐ€ * ๐Ÿ™€ chore: let -> const๋กœ ๋ณ€๊ฒฝ --- README.md | 12 +-- .../CodeContent/CodeContent.stories.tsx | 44 ++++++++++ .../{ => CodeContent}/CodeContent.tsx | 10 ++- .../CodeViewer/CodeViewer.stories.tsx | 82 +++++++++++++++++++ .../{ => CodeViewer}/CodeViewer.tsx | 15 ++-- .../LineNumbers/LineNumber.stories.tsx | 22 +++++ .../{ => LineNumbers}/LineNumbers.tsx | 7 +- .../src/shared/code-highlighter/index.ts | 2 +- apps/client/src/shared/hooks/index.ts | 1 + .../src/shared/hooks/useInfiniteScroll.ts | 29 +++++++ .../hooks/usePreventLeaveWorkspacePage.ts | 2 +- .../WorkspaceContainer/WorkspaceContainer.tsx | 44 ++++------ 12 files changed, 226 insertions(+), 44 deletions(-) create mode 100644 apps/client/src/shared/code-highlighter/components/CodeContent/CodeContent.stories.tsx rename apps/client/src/shared/code-highlighter/components/{ => CodeContent}/CodeContent.tsx (91%) create mode 100644 apps/client/src/shared/code-highlighter/components/CodeViewer/CodeViewer.stories.tsx rename apps/client/src/shared/code-highlighter/components/{ => CodeViewer}/CodeViewer.tsx (75%) create mode 100644 apps/client/src/shared/code-highlighter/components/LineNumbers/LineNumber.stories.tsx rename apps/client/src/shared/code-highlighter/components/{ => LineNumbers}/LineNumbers.tsx (86%) create mode 100644 apps/client/src/shared/hooks/useInfiniteScroll.ts diff --git a/README.md b/README.md index 04510bc7..8d7ef2a9 100644 --- a/README.md +++ b/README.md @@ -60,15 +60,14 @@

hello world!

``` -์›น ๊ฐœ๋ฐœ ์ดˆ๋ณด์ž๋“ค์—๊ฒŒ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์€ ์–ด๋ ต๊ณ  ๋ถ€๋‹ด์Šค๋Ÿฝ๊ฒŒ ๋Š๊ปด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
-ํ•˜์ง€๋งŒ BooLock์—์„œ๋Š” ๋ธ”๋ก์„ ์กฐ๋ฆฝํ•˜๋ฉฐ ์‰ฝ๊ณ  ์žฌ๋ฏธ์žˆ๊ฒŒ ์ž์‹ ๋งŒ์˜ ์›น์‚ฌ์ดํŠธ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+์›น ๊ฐœ๋ฐœ ์ดˆ๋ณด์ž๋“ค์—๊ฒŒ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์€ ์–ด๋ ต๊ณ  ๋ถ€๋‹ด์Šค๋Ÿฝ๊ฒŒ ๋Š๊ปด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+ํ•˜์ง€๋งŒ BooLock์—์„œ๋Š” ๋ธ”๋ก์„ ์กฐ๋ฆฝํ•˜๋ฉฐ ์‰ฝ๊ณ  ์žฌ๋ฏธ์žˆ๊ฒŒ ์ž์‹ ๋งŒ์˜ ์›น์‚ฌ์ดํŠธ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
-BooLock์€ HTML๊ณผ CSS๋ฅผ ๋ธ”๋ก์ฝ”๋”ฉ ๋ฐฉ์‹์œผ๋กœ ํ•™์Šตํ•  ์ˆ˜ ์žˆ๋Š” ํ”Œ๋žซํผ์ž…๋‹ˆ๋‹ค.
-์ฝ”๋“œ๋ฅผ ๋ชฐ๋ผ๋„ ๋ธ”๋ก์„ ์กฐ๋ฆฝํ•˜๋Š” ๊ฐ„๋‹จํ•œ ๋ฐฉ์‹์œผ๋กœ ์›ํ•˜๋Š” ์›น์‚ฌ์ดํŠธ๋ฅผ ์ œ์ž‘ํ•˜๊ณ , ์ด๋ฅผ ํ†ตํ•ด ์›น ๊ฐœ๋ฐœ์˜ ๊ธฐ์ดˆ๋ฅผ ์žฌ๋ฏธ์žˆ๊ฒŒ ๋ฐฐ์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+BooLock์€ HTML๊ณผ CSS๋ฅผ ๋ธ”๋ก์ฝ”๋”ฉ ๋ฐฉ์‹์œผ๋กœ ํ•™์Šตํ•  ์ˆ˜ ์žˆ๋Š” ํ”Œ๋žซํผ์ž…๋‹ˆ๋‹ค.
+์ฝ”๋“œ๋ฅผ ๋ชฐ๋ผ๋„ ๋ธ”๋ก์„ ์กฐ๋ฆฝํ•˜๋Š” ๊ฐ„๋‹จํ•œ ๋ฐฉ์‹์œผ๋กœ ์›ํ•˜๋Š” ์›น์‚ฌ์ดํŠธ๋ฅผ ์ œ์ž‘ํ•˜๊ณ , ์ด๋ฅผ ํ†ตํ•ด ์›น ๊ฐœ๋ฐœ์˜ ๊ธฐ์ดˆ๋ฅผ ์žฌ๋ฏธ์žˆ๊ฒŒ ๋ฐฐ์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋ธ”๋ก๋“ค์ด ๋ชจ์—ฌ ๋งŒ๋“ค์–ด์ง„ ๋‚˜๋งŒ์˜ ์›นํŽ˜์ด์ง€๋ฅผ ์ฃผ๋ณ€ ์‚ฌ๋žŒ๋“ค๊ณผ ๊ณต์œ ํ•ด๋ณด์„ธ์š”. โค๏ธ -
# ๐Ÿฅ ์ฃผ์š”๊ธฐ๋Šฅ @@ -184,7 +183,7 @@ BooLock์€ HTML๊ณผ CSS๋ฅผ ๋ธ”๋ก์ฝ”๋”ฉ ๋ฐฉ์‹์œผ๋กœ ํ•™์Šตํ•  ์ˆ˜ ์žˆ๋Š” ํ”Œ๋žซ storybook description - Blockly์˜ Flyout ๋‚ด๋ถ€์— DOM ์š”์†Œ(input, button)๋ฅผ ๋™์ ์œผ๋กœ ์ƒ์„ฑํ•˜์—ฌ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค. ์ž…๋ ฅ๊ฐ’์€ ์ค‘๋ณต ํ™•์ธ๊ณผ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ๊ฑฐ์ณ CSS_ ์ ‘๋‘์‚ฌ๋ฅผ ๋ถ™์—ฌ ๋ธ”๋ก์œผ๋กœ ๋“ฑ๋ก๋˜๋ฉฐ, ์ฆ‰์‹œ Flyout์— ๋ฐ˜์˜๋ฉ๋‹ˆ๋‹ค. ์ƒ์„ฑ๋œ ๋ธ”๋ก์€ ์šฐํด๋ฆญ ์‹œ "๋ธ”๋ก ์‚ญ์ œ" ์˜ต์…˜์œผ๋กœ ๊ด€๋ จ๋œ ๋ชจ๋“  ์ธ์Šคํ„ด์Šค๋ฅผ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Reset CSS ์ฒดํฌ๋ฐ•์Šค์™€ ํˆดํŒ์„ ์ถ”๊ฐ€ํ•ด ๊ธฐ๋ณธ ์Šคํƒ€์ผ ์ดˆ๊ธฐํ™”์™€ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ๊ฐœ์„ ํ–ˆ์Šต๋‹ˆ๋‹ค. + Blockly์˜ Flyout ๋‚ด๋ถ€์— DOM ์š”์†Œ(input, button)๋ฅผ ๋™์ ์œผ๋กœ ์ƒ์„ฑํ•˜์—ฌ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค. ์ž…๋ ฅ๊ฐ’์€ ์ค‘๋ณต ํ™•์ธ๊ณผ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ๊ฑฐ์ณ CSS\_ ์ ‘๋‘์‚ฌ๋ฅผ ๋ถ™์—ฌ ๋ธ”๋ก์œผ๋กœ ๋“ฑ๋ก๋˜๋ฉฐ, ์ฆ‰์‹œ Flyout์— ๋ฐ˜์˜๋ฉ๋‹ˆ๋‹ค. ์ƒ์„ฑ๋œ ๋ธ”๋ก์€ ์šฐํด๋ฆญ ์‹œ "๋ธ”๋ก ์‚ญ์ œ" ์˜ต์…˜์œผ๋กœ ๊ด€๋ จ๋œ ๋ชจ๋“  ์ธ์Šคํ„ด์Šค๋ฅผ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Reset CSS ์ฒดํฌ๋ฐ•์Šค์™€ ํˆดํŒ์„ ์ถ”๊ฐ€ํ•ด ๊ธฐ๋ณธ ์Šคํƒ€์ผ ์ดˆ๊ธฐํ™”์™€ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ๊ฐœ์„ ํ–ˆ์Šต๋‹ˆ๋‹ค. > **๐Ÿ‘‡ ๋” ์ž์„ธํ•œ ๊ธฐ๋ก ๋ฐ ๊ณผ์ • ํ™•์ธํ•˜๊ธฐ ๐Ÿ‘‡**
> [Blockly ์ปค์Šคํ…€](https://www.notion.so/Blockly-14077ba9a1b680ccafcbd5b3781bf390?pvs=21) @@ -268,6 +267,7 @@ React์˜ SPA ๊ตฌ์กฐ๋กœ ์ธํ•ด ๊ฒ€์ƒ‰ ์—”์ง„์ด ํŽ˜์ด์ง€ ์ •๋ณด๋ฅผ ์ธ์‹ํ•˜์ง€ > **๐Ÿ‘‡ ๋” ์ž์„ธํ•œ ๊ธฐ๋ก ๋ฐ ๊ณผ์ • ํ™•์ธํ•˜๊ธฐ ๐Ÿ‘‡**
> [์‚ฌ์šฉ์ž ๊ฐ€์ด๋“œ](https://www.notion.so/51679d3e288b485f9a0ea9068eb621f5?pvs=21)
### ์Šคํ† ๋ฆฌ๋ถ ํ…Œ์ŠคํŠธ + [**์Šคํ† ๋ฆฌ๋ถ ๋ฐฐํฌ ๋งํฌ**](https://boostcampwm-2024.github.io/web31-BooLock/)
diff --git a/apps/client/src/shared/code-highlighter/components/CodeContent/CodeContent.stories.tsx b/apps/client/src/shared/code-highlighter/components/CodeContent/CodeContent.stories.tsx new file mode 100644 index 00000000..54641cec --- /dev/null +++ b/apps/client/src/shared/code-highlighter/components/CodeContent/CodeContent.stories.tsx @@ -0,0 +1,44 @@ +import { Meta, StoryObj } from '@storybook/react'; + +import { CodeContent } from './CodeContent'; + +const meta: Meta = { + title: 'shared/code-highlighter/CodeContent', + component: CodeContent, + parameters: { + layout: 'centered', + }, + tags: ['autodocs'], +}; + +export default meta; + +type Story = StoryObj; + +export const Default: Story = { + args: { + code: ` + + +
+

title

+

content

+
+ + `, + codeLineList: [ + '', + ' ', + ' ', + '
', + '

title

', + '

content

', + '
', + ' ', + '', + ], + selectedBlockStartLine: 5, + selectedBlockLength: 7, + selectedBlockType: 'BOOLOCK_SYSTEM_html', + }, +}; diff --git a/apps/client/src/shared/code-highlighter/components/CodeContent.tsx b/apps/client/src/shared/code-highlighter/components/CodeContent/CodeContent.tsx similarity index 91% rename from apps/client/src/shared/code-highlighter/components/CodeContent.tsx rename to apps/client/src/shared/code-highlighter/components/CodeContent/CodeContent.tsx index ded836c6..c58cd515 100644 --- a/apps/client/src/shared/code-highlighter/components/CodeContent.tsx +++ b/apps/client/src/shared/code-highlighter/components/CodeContent/CodeContent.tsx @@ -1,5 +1,6 @@ -import styles from '../styles/CodeViewer.module.css'; -import { useState, useEffect } from 'react'; +import { useEffect, useState } from 'react'; + +import styles from '../../styles/CodeViewer.module.css'; type CodeViewerProps = { code: string; @@ -9,6 +10,11 @@ type CodeViewerProps = { selectedBlockType?: string | null; }; +/** + * + * @description + * ๋ณ€ํ™˜๋œ HTML, CSS ์ฝ”๋“œ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ์ปดํฌ๋„ŒํŠธ + */ export const CodeContent = ({ code, codeLineList, diff --git a/apps/client/src/shared/code-highlighter/components/CodeViewer/CodeViewer.stories.tsx b/apps/client/src/shared/code-highlighter/components/CodeViewer/CodeViewer.stories.tsx new file mode 100644 index 00000000..2a7c1d07 --- /dev/null +++ b/apps/client/src/shared/code-highlighter/components/CodeViewer/CodeViewer.stories.tsx @@ -0,0 +1,82 @@ +import { Meta, StoryObj } from '@storybook/react'; + +import { CodeViewer } from './CodeViewer'; + +const meta: Meta = { + title: 'shared/code-highlighter/CodeViewer', + component: CodeViewer, + parameters: { + layout: 'fullscreen', + }, + tags: ['autodocs'], +}; + +export default meta; + +type Story = StoryObj; + +export const Default: Story = { + args: { + code: ` + + +
+

title

+

content

+
+ + `, + type: 'html', + theme: 'light', + }, +}; + +export const DarkThemeHTML: Story = { + args: { + code: ` + + +
+

title

+

content

+
+ + `, + type: 'html', + theme: 'dark', + }, +}; + +export const LightThemeCss: Story = { + args: { + code: `.title { + background-color: red; + } + .content { + font-size: 16px; + font-weight: bold; + font-family: 'Arial'; + color: #000; + } + `, + type: 'css', + theme: 'light', + }, +}; + +export const DarkThemeCss: Story = { + args: { + code: `.title { + background-color: red; + } + .content { + font-size: 16px; + font-weight: bold; + font-family: 'Arial'; + color: #000; + } + `, + type: 'css', + theme: 'dark', + }, +}; diff --git a/apps/client/src/shared/code-highlighter/components/CodeViewer.tsx b/apps/client/src/shared/code-highlighter/components/CodeViewer/CodeViewer.tsx similarity index 75% rename from apps/client/src/shared/code-highlighter/components/CodeViewer.tsx rename to apps/client/src/shared/code-highlighter/components/CodeViewer/CodeViewer.tsx index e29d86b2..490635ad 100644 --- a/apps/client/src/shared/code-highlighter/components/CodeViewer.tsx +++ b/apps/client/src/shared/code-highlighter/components/CodeViewer/CodeViewer.tsx @@ -1,8 +1,8 @@ -import { CodeContent } from './CodeContent'; -import { LineNumbers } from './LineNumbers'; -import { parseHighlightCss } from '../utils/parseHighlightCss'; -import { parseHighlightHtml } from '../utils/parseHighlightHtml'; -import styles from '../styles/CodeViewer.module.css'; +import { CodeContent } from '../CodeContent/CodeContent'; +import { LineNumbers } from '../LineNumbers/LineNumbers'; +import { parseHighlightCss } from '../../utils/parseHighlightCss'; +import { parseHighlightHtml } from '../../utils/parseHighlightHtml'; +import styles from '../../styles/CodeViewer.module.css'; import { useCoachMarkStore } from '@/shared/store/useCoachMarkStore'; type CodeViewerProps = { @@ -14,6 +14,11 @@ type CodeViewerProps = { selectedBlockType?: string | null; }; +/** + * + * @description + * ๋ณ€ํ™˜๋œ HTML, CSS ์ฝ”๋“œ๋ฅผ ์ค„ ์ˆ˜์™€ ํ•จ๊ป˜ ๋ณด์—ฌ์ฃผ๋Š” ์ปดํฌ๋„ŒํŠธ + */ export const CodeViewer = ({ code, type, diff --git a/apps/client/src/shared/code-highlighter/components/LineNumbers/LineNumber.stories.tsx b/apps/client/src/shared/code-highlighter/components/LineNumbers/LineNumber.stories.tsx new file mode 100644 index 00000000..c996d2c3 --- /dev/null +++ b/apps/client/src/shared/code-highlighter/components/LineNumbers/LineNumber.stories.tsx @@ -0,0 +1,22 @@ +import { Meta, StoryObj } from '@storybook/react'; + +import { LineNumbers } from './LineNumbers'; + +const meta: Meta = { + title: 'shared/code-highlighter/LineNumbers', + component: LineNumbers, + parameters: { + layout: 'centered', + }, + tags: ['autodocs'], +}; + +export default meta; + +type Story = StoryObj; + +export const Default: Story = { + args: { + codeLineList: ['line1', 'line2', 'line3'], + }, +}; diff --git a/apps/client/src/shared/code-highlighter/components/LineNumbers.tsx b/apps/client/src/shared/code-highlighter/components/LineNumbers/LineNumbers.tsx similarity index 86% rename from apps/client/src/shared/code-highlighter/components/LineNumbers.tsx rename to apps/client/src/shared/code-highlighter/components/LineNumbers/LineNumbers.tsx index 19f0df11..69a77d28 100644 --- a/apps/client/src/shared/code-highlighter/components/LineNumbers.tsx +++ b/apps/client/src/shared/code-highlighter/components/LineNumbers/LineNumbers.tsx @@ -1,10 +1,15 @@ +import styles from '../../styles/CodeViewer.module.css'; import { useState } from 'react'; -import styles from '../styles/CodeViewer.module.css'; type LineNumbersProps = { codeLineList: string[]; }; +/** + * + * @description + * ์ฝ”๋“œ์˜ ์ค„ ์ˆ˜๋ฅผ ํ‘œ์‹œํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ + */ export const LineNumbers = ({ codeLineList }: LineNumbersProps) => { const [hoveredLineNumber, setHoveredLineNumber] = useState(null); diff --git a/apps/client/src/shared/code-highlighter/index.ts b/apps/client/src/shared/code-highlighter/index.ts index 96758797..45187a73 100644 --- a/apps/client/src/shared/code-highlighter/index.ts +++ b/apps/client/src/shared/code-highlighter/index.ts @@ -1 +1 @@ -export { CodeViewer } from './components/CodeViewer'; +export { CodeViewer } from './components/CodeViewer/CodeViewer'; diff --git a/apps/client/src/shared/hooks/index.ts b/apps/client/src/shared/hooks/index.ts index 1ce64c92..94bde057 100644 --- a/apps/client/src/shared/hooks/index.ts +++ b/apps/client/src/shared/hooks/index.ts @@ -15,3 +15,4 @@ export { useCssOptionItem } from './css/useCssOptionItem'; export { workspaceKeys } from './query-key/workspaceKeys'; export { usePreventLeaveWorkspacePage } from './usePreventLeaveWorkspacePage'; +export { useInfiniteScroll } from './useInfiniteScroll'; diff --git a/apps/client/src/shared/hooks/useInfiniteScroll.ts b/apps/client/src/shared/hooks/useInfiniteScroll.ts new file mode 100644 index 00000000..5f839454 --- /dev/null +++ b/apps/client/src/shared/hooks/useInfiniteScroll.ts @@ -0,0 +1,29 @@ +import { useEffect, useRef } from 'react'; + +type useInfiniteScrollProps = { + intersectionCallback: IntersectionObserverCallback; +}; + +export const useInfiniteScroll = ({ intersectionCallback }: useInfiniteScrollProps) => { + const targetRef = useRef(null); + + const option = { + root: null, + rootMargin: '0px', + threshold: 0.5, + }; + + useEffect(() => { + if (!targetRef.current) { + return; + } + const observer = new IntersectionObserver(intersectionCallback, option); + observer.observe(targetRef.current); + return () => { + if (targetRef.current) { + observer.unobserve(targetRef.current); + } + }; + }, [intersectionCallback]); + return targetRef; +}; diff --git a/apps/client/src/shared/hooks/usePreventLeaveWorkspacePage.ts b/apps/client/src/shared/hooks/usePreventLeaveWorkspacePage.ts index 34c4bb2c..de4c4adf 100644 --- a/apps/client/src/shared/hooks/usePreventLeaveWorkspacePage.ts +++ b/apps/client/src/shared/hooks/usePreventLeaveWorkspacePage.ts @@ -4,7 +4,7 @@ import { useWorkspaceChangeStatusStore } from '@/shared/store'; export const usePreventLeaveWorkspacePage = () => { const { isBlockChanged, isCssChanged } = useWorkspaceChangeStatusStore(); - let blocker = useBlocker( + const blocker = useBlocker( ({ currentLocation, nextLocation }) => currentLocation.pathname !== nextLocation.pathname && (isBlockChanged || isCssChanged) ); diff --git a/apps/client/src/widgets/home/WorkspaceContainer/WorkspaceContainer.tsx b/apps/client/src/widgets/home/WorkspaceContainer/WorkspaceContainer.tsx index 16e6cf67..491b760a 100644 --- a/apps/client/src/widgets/home/WorkspaceContainer/WorkspaceContainer.tsx +++ b/apps/client/src/widgets/home/WorkspaceContainer/WorkspaceContainer.tsx @@ -1,9 +1,8 @@ import { EmptyWorkspace, WorkspaceGrid, WorkspaceHeader, WorkspaceList } from '@/widgets'; -import { useEffect, useRef } from 'react'; +import { useGetWorkspaceList, useInfiniteScroll } from '@/shared/hooks'; import { SkeletonWorkspaceList } from '@/shared/ui'; import { WorkspaceLoadError } from '@/entities'; -import { useGetWorkspaceList } from '@/shared/hooks'; /** * @@ -14,36 +13,25 @@ export const WorkspaceContainer = () => { const { hasNextPage, fetchNextPage, isPending, isFetchingNextPage, isError, workspaceList } = useGetWorkspaceList(); - const nextFetchTargetRef = useRef(null); - - useEffect(() => { - const options = { - root: null, - rootMargin: '0px', - threshold: 0.5, - }; - const fetchCallback: IntersectionObserverCallback = (entries, observer) => { - entries.forEach((entry) => { - if (entry.isIntersecting && hasNextPage) { - fetchNextPage(); - observer.unobserve(entry.target); - } - }); - }; - const observer = new IntersectionObserver(fetchCallback, options); - if (nextFetchTargetRef.current) { - observer.observe(nextFetchTargetRef.current); - } - return () => { - if (nextFetchTargetRef.current) { - observer.unobserve(nextFetchTargetRef.current); + const fetchCallback: IntersectionObserverCallback = (entries, observer) => { + entries.forEach((entry) => { + if (entry.isIntersecting && hasNextPage) { + fetchNextPage(); + observer.unobserve(entry.target); } - }; - }, [workspaceList]); + }); + }; + + const nextFetchTargetRef = useInfiniteScroll({ intersectionCallback: fetchCallback }); return (
+ {isPending && ( + + + + )} {isError ? ( ) : ( @@ -53,7 +41,7 @@ export const WorkspaceContainer = () => { ) : ( - {(isPending || isFetchingNextPage) && } + {isFetchingNextPage && } )) )}