본문 바로가기
  • 코딩, 허쌤이 떠먹여 줄게
FrontEnd/React

props - 테마바꾸기

by 허쌤 2026. 3. 28.

App.jsx

import { useState } from 'react';
import Toolbar from './components/Toolbar';
import ContentPanel from './components/ContentPanel';

/**
 * Props 방식: theme, count, setters 를 자식에게 props 로 전달합니다.
 * 중첩이 깊어지면 "props drilling" 이 됩니다.
 */
function App() {
  const [theme, setTheme] = useState('light');
  const [count, setCount] = useState(0);

  const toggleTheme = () => {
    setTheme((t) => (t === 'light' ? 'dark' : 'light'));
  };

  return (
    <div className={`app ${theme}`}>
      <header>
        <h1>Props 예제</h1>
        <span className="badge">상태는 App · props로 전달</span>
      </header>

      <Toolbar
        theme={theme}
        onToggleTheme={toggleTheme}
        count={count}
        onIncrement={() => setCount((c) => c + 1)}
      />

      <ContentPanel theme={theme} count={count} />
    </div>
  );
}

export default App;

 

components/ContentPanel.jsx

/**
 * ContentPanel — theme, count를 props로만 표시합니다.
 */
function ContentPanel({ theme, count }) {
  return (
    <section className="panel">
      <p className="note">
        <strong>ContentPanel</strong>은 부모가 넘긴 props로 화면을 그립니다.
      </p>
      <p>현재 테마 문자열: <code>{theme}</code></p>
      <p className="counter">{count}</p>
    </section>
  );
}

export default ContentPanel;

 

components/Toolbar.jsx

/**
 * ContentPanel — theme, count를 props로만 표시합니다.
 */
function ContentPanel({ theme, count }) {
  return (
    <section className="panel">
      <p className="note">
        <strong>ContentPanel</strong>은 부모가 넘긴 props로 화면을 그립니다.
      </p>
      <p>현재 테마 문자열: <code>{theme}</code></p>
      <p className="counter">{count}</p>
    </section>
  );
}

export default ContentPanel;

 

 

index.css

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family: system-ui, sans-serif;
}

.app {
  min-height: 100vh;
  padding: 1.5rem;
  transition: background 0.2s, color 0.2s;
}

.app.light {
  background: #f8fafc;
  color: #0f172a;
}

.app.dark {
  background: #0f172a;
  color: #f1f5f9;
}

header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 1rem;
  margin-bottom: 1.5rem;
}

header h1 {
  margin: 0;
  font-size: 1.25rem;
}

.badge {
  font-size: 0.75rem;
  padding: 0.25rem 0.5rem;
  border-radius: 6px;
  background: rgba(59, 130, 246, 0.2);
  color: #3b82f6;
}

.app.dark .badge {
  background: rgba(96, 165, 250, 0.15);
  color: #93c5fd;
}

.panel {
  border-radius: 12px;
  padding: 1.25rem;
  margin-bottom: 1rem;
  border: 1px solid rgba(148, 163, 184, 0.4);
}

.app.dark .panel {
  border-color: rgba(148, 163, 184, 0.25);
}

button {
  cursor: pointer;
  padding: 0.5rem 1rem;
  border-radius: 8px;
  border: none;
  font-weight: 600;
}

.btn-toggle {
  background: #3b82f6;
  color: white;
}

.btn-toggle:hover {
  filter: brightness(1.05);
}

.counter {
  font-size: 2rem;
  font-weight: 700;
  margin: 0.5rem 0;
}

.note {
  font-size: 0.85rem;
  opacity: 0.85;
  line-height: 1.5;
}

 

 

'FrontEnd > React' 카테고리의 다른 글

props · useContex 비교 테마 바꾸기  (0) 2026.03.28
useContext 테마바꾸기  (0) 2026.03.28
24차시. 프로젝트 정리  (0) 2026.03.24
23차시. 빌드 & 배포  (0) 2026.03.23
22차시. 컴포넌트 최적화  (0) 2026.03.22