Skip to content

Commit 0b0504e

Browse files
committed
Revert "Fix: 코드블럭 깜빡임 현상 수정"
This reverts commit 3900df1.
1 parent 595a727 commit 0b0504e

File tree

1 file changed

+69
-65
lines changed

1 file changed

+69
-65
lines changed

components/code-block.tsx

Lines changed: 69 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"use client";
22

3-
import React, { useState, memo } from "react";
3+
import React, { useState, useEffect } from "react";
44
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
55
import {
66
oneDark,
@@ -17,65 +17,23 @@ interface CodeBlockProps {
1717
filename?: string;
1818
}
1919

20-
// SyntaxHighlighter를 별도 컴포넌트로 분리
21-
const CodeHighlighter = memo(({
22-
language,
23-
code,
24-
isDark
25-
}: {
26-
language: string;
27-
code: string;
28-
isDark: boolean;
29-
}) => {
30-
return (
31-
<SyntaxHighlighter
32-
language={language}
33-
style={isDark ? oneDark : oneLight}
34-
customStyle={{
35-
margin: 0,
36-
padding: "1rem",
37-
borderRadius: 0,
38-
fontSize: "13px",
39-
whiteSpace: "pre-wrap",
40-
wordBreak: "break-all",
41-
overflowWrap: "anywhere",
42-
maxWidth: "100%",
43-
overflowX: "visible",
44-
background: isDark
45-
? "rgba(30, 30, 30, 0.95)"
46-
: "rgba(250, 250, 250, 0.95)",
47-
transition: "background 0.3s ease",
48-
}}
49-
wrapLines={true}
50-
wrapLongLines={true}
51-
lineProps={{
52-
style: { wordBreak: "break-all", whiteSpace: "pre-wrap" },
53-
}}
54-
className="whitespace-pre-wrap break-all"
55-
PreTag={({ children, ...props }) => (
56-
<pre {...props} className="transition-colors duration-300">
57-
{children}
58-
</pre>
59-
)}
60-
>
61-
{code}
62-
</SyntaxHighlighter>
63-
);
64-
});
65-
66-
CodeHighlighter.displayName = "CodeHighlighter";
67-
68-
function CodeBlock({
20+
export default function CodeBlock({
6921
language,
7022
code,
7123
filename,
7224
}: CodeBlockProps) {
7325
const [isCopied, setIsCopied] = useState(false);
7426
const [isCollapsed, setIsCollapsed] = useState(false);
27+
const [mounted, setMounted] = useState(false);
7528
const { resolvedTheme } = useTheme();
76-
77-
// 테마를 직접 체크 (서버와 클라이언트 모두에서 작동)
78-
const isDark = resolvedTheme === "dark";
29+
30+
// 서버/클라이언트 하이드레이션 불일치 방지
31+
useEffect(() => {
32+
setMounted(true);
33+
}, []);
34+
35+
// 실제 사용할 테마 (마운트 전에는 기본값 사용)
36+
const isDark = mounted ? resolvedTheme === "dark" : false;
7937

8038
const handleCopy = async () => {
8139
await navigator.clipboard.writeText(code);
@@ -112,7 +70,12 @@ function CodeBlock({
11270
};
11371

11472
return (
115-
<div className="relative spacing-section rounded-lg overflow-hidden border border-primary/20 shadow-md">
73+
<motion.div
74+
className="relative spacing-section rounded-lg overflow-hidden border border-primary/20 shadow-md"
75+
initial={{ opacity: 0, y: 10 }}
76+
animate={{ opacity: 1, y: 0 }}
77+
transition={{ duration: 0.4 }}
78+
>
11679
<div
11780
className="flex items-center justify-between bg-gradient-to-r from-primary/20 to-primary/5 text-primary
11881
px-3 sm:px-4 py-2 sm:py-2.5 text-xs sm:text-sm font-mono border-b border-primary/15"
@@ -186,18 +149,59 @@ function CodeBlock({
186149
<div className="absolute top-0 right-0 bottom-0 w-4 bg-gradient-to-l from-black/5 to-transparent pointer-events-none"></div>
187150
<div className="absolute top-0 left-0 bottom-0 w-4 bg-gradient-to-r from-black/5 to-transparent pointer-events-none"></div>
188151

189-
{/* 항상 CodeHighlighter 렌더링 */}
190-
<CodeHighlighter language={language} code={code} isDark={isDark} />
152+
{/* 마운트 전까지는 로딩 상태 표시 */}
153+
{!mounted ? (
154+
<div
155+
className="p-4 bg-muted/30 text-muted-foreground font-mono text-xs space-y-2 animate-pulse"
156+
style={{ minHeight: "8rem" }}
157+
>
158+
{code
159+
.split("\n")
160+
.slice(0, 8)
161+
.map((_, idx) => (
162+
<div
163+
key={idx}
164+
className="h-4 bg-muted-foreground/20 rounded"
165+
style={{ width: `${Math.floor(Math.random() * 50) + 50}%` }}
166+
></div>
167+
))}
168+
</div>
169+
) : (
170+
<SyntaxHighlighter
171+
language={language}
172+
style={isDark ? oneDark : oneLight}
173+
customStyle={{
174+
margin: 0,
175+
padding: "1rem",
176+
borderRadius: 0,
177+
fontSize: "13px",
178+
whiteSpace: "pre-wrap", // 자동 줄바꿈
179+
wordBreak: "break-all", // 단어 중간에서도 줄바꿈
180+
overflowWrap: "anywhere", // 어디서든 줄바꿈 허용
181+
maxWidth: "100%",
182+
overflowX: "visible", // 좌우 스크롤 제거
183+
background: isDark
184+
? "rgba(30, 30, 30, 0.95)"
185+
: "rgba(250, 250, 250, 0.95)",
186+
transition: "background 0.3s ease",
187+
}}
188+
wrapLines={true}
189+
wrapLongLines={true}
190+
lineProps={{
191+
style: { wordBreak: "break-all", whiteSpace: "pre-wrap" },
192+
}}
193+
className="whitespace-pre-wrap break-all"
194+
PreTag={({ children, ...props }) => (
195+
<pre {...props} className="transition-colors duration-300">
196+
{children}
197+
</pre>
198+
)}
199+
>
200+
{code}
201+
</SyntaxHighlighter>
202+
)}
191203
</div>
192204
</motion.div>
193-
</div>
205+
</motion.div>
194206
);
195207
}
196-
197-
export default memo(CodeBlock, (prevProps, nextProps) => {
198-
return (
199-
prevProps.code === nextProps.code &&
200-
prevProps.language === nextProps.language &&
201-
prevProps.filename === nextProps.filename
202-
);
203-
});

0 commit comments

Comments
 (0)