🔵 Class Components in React
Class components in React are ES6 JavaScript classes that allow you to build UI just like functional components, but with more built-in features.
✅ What they can do:
Receive props as input: Just like functions, class components can receive data (called props) and use it inside the component.
Return JSX (like HTML): They return JSX that describes what should be shown on the screen.
Maintain private state: This is what makes class components powerful. They can store and manage their own data, called state.
This state is private, meaning it's only available inside that component and not accessible directly from outside. The component uses this state to decide what to display and how to behave.
✅ How to Create a Class Component in React
To create class component we need 2 imports, we need react and the component class from react.
Use class to define your component.
Extend from React.Component.
Add a render() method to return JSX (the UI).
<div class="infographic-classcomponent" id="cc">
<style>
.infographic-classcomponent {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-deep: #1942a8;
--accent-soft: #e3ebfd;
--line: #ddd6c9;
--radius: 8px;
--display-font: 'Fraunces', Georgia, serif;
--body-font: 'Inter', system-ui, sans-serif;
--mono-font: 'IBM Plex Mono', monospace;
max-width: 880px;
margin: 0 auto;
box-sizing: border-box;
background: transparent;
color: var(--ink);
font-family: var(--body-font);
}
.infographic-classcomponent[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #13171f;
--paper-alt: #1c212b;
--accent: #5b8def;
--accent-deep: #8fb4ff;
--accent-soft: #20293f;
--line: #2c313d;
}
.infographic-classcomponent * { box-sizing: border-box; }
.cc-eyebrow {
font-family: var(--mono-font); font-size: 0.72rem; letter-spacing: 0.1em;
text-transform: uppercase; color: var(--accent); margin: 0 0 0.45rem;
display: flex; align-items: center; justify-content: center; gap: 0.4rem;
}
.cc-eyebrow::before { content: ""; width: 14px; height: 2px; background: var(--accent); display: inline-block; }
.cc-title {
font-family: var(--display-font); font-size: clamp(1.5rem, 4vw, 2.3rem); text-align: center;
margin: 0 0 0.5rem; line-height: 1.12; letter-spacing: -0.01em;
}
.cc-sub { color: var(--ink-soft); font-size: 0.95rem; text-align: center; margin: 0 0 1.9rem; }
/* ===== two-column code panels ===== */
.cc-code-compare { display: grid; grid-template-columns: 1fr 1fr; gap: 1.25rem; margin-bottom: 1.6rem; }
.cc-code-block { display: flex; flex-direction: column; min-width: 0; }
.cc-code-head { display: flex; align-items: center; justify-content: center; gap: 0.4rem; margin-bottom: 0.5rem; }
.cc-code-head svg { width: 15px; height: 15px; flex-shrink: 0; }
.cc-code-name { font-size: 0.8rem; font-weight: 600; color: var(--ink); }
.cc-code-block pre {
margin: 0; background: #0d0d10; border: 1px solid #24252d; border-radius: var(--radius);
padding: 1rem 1.2rem; overflow: auto; max-height: 260px; flex: 1;
scrollbar-width: thin; scrollbar-color: #4a4a52 #0d0d10;
}
.cc-code-block pre::-webkit-scrollbar { width: 9px; height: 9px; }
.cc-code-block pre::-webkit-scrollbar-track { background: #0d0d10; }
.cc-code-block pre::-webkit-scrollbar-thumb { background: #4a4a52; border-radius: 5px; }
.cc-code-block pre::-webkit-scrollbar-thumb:hover { background: #5c5c66; }
.cc-code-block code { font-family: var(--mono-font); font-size: 0.76rem; line-height: 1.75; color: #d4d4d8; white-space: pre; }
.tok-kw { color: #c678dd; }
.tok-tag { color: #e06c75; }
.tok-type { color: #61afef; }
.tok-str { color: #98c379; }
.tok-punc { color: #6b7280; }
.tok-comment { color: #7f848e; font-style: italic; }
/* ===== run button ===== */
.cc-run-wrap { display: flex; justify-content: center; margin-bottom: 1.9rem; }
.cc-run-btn {
display: flex; align-items: center; gap: 0.5rem; font: inherit; font-weight: 600; font-size: 0.88rem;
color: #fff; background: var(--accent); border: none; border-radius: 100px; padding: 0.65rem 1.5rem;
cursor: pointer; box-shadow: 0 6px 16px -4px rgba(37,99,235,0.45); transition: transform 0.15s, background 0.15s;
}
.cc-run-btn:hover { transform: translateY(-1px); }
.cc-run-btn:active { transform: scale(0.97); }
.cc-run-btn:focus-visible { outline: 2px solid var(--accent-deep); outline-offset: 2px; }
.cc-run-btn.is-reset { background: var(--ink-soft); box-shadow: none; }
.cc-run-btn svg { width: 13px; height: 13px; }
/* ===== output ===== */
.cc-output-label {
font-family: var(--mono-font); font-size: 0.7rem; letter-spacing: 0.1em; text-transform: uppercase;
color: var(--ink-soft); text-align: center; margin: 0 0 0.7rem;
}
.cc-output-placeholder {
border: 1.5px dashed var(--line); border-radius: var(--radius); padding: 2.2rem 1.5rem; text-align: center;
color: var(--ink-soft); font-size: 0.85rem; max-width: 480px; margin: 0 auto;
}
.cc-preview {
display: none; border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden;
max-width: 480px; margin: 0 auto; box-shadow: 0 10px 24px -12px rgba(26,26,26,0.18);
animation: cc-fade-up 0.35s ease;
}
@keyframes cc-fade-up { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
.cc-preview-bar { background: #e9e9e9; padding: 0.5rem 0.7rem; display: flex; gap: 0.35rem; }
.cc-preview-bar span { width: 9px; height: 9px; border-radius: 50%; display: block; }
.cc-preview-bar span:nth-child(1) { background: #ff5f56; }
.cc-preview-bar span:nth-child(2) { background: #ffbd2e; }
.cc-preview-bar span:nth-child(3) { background: #27c93f; }
.cc-preview-page { background: #ffffff; padding: 1.6rem 1.4rem; font-family: Times, "Times New Roman", serif; }
.cc-preview-page h1 { font-size: 1.5rem; margin: 0 0 0.5rem; color: #000; font-weight: bold; }
.cc-preview-page p { font-size: 1rem; margin: 0; color: #000; }
.cc-output.is-run .cc-output-placeholder { display: none; }
.cc-output.is-run .cc-preview { display: block; }
@media (max-width: 640px) {
.cc-code-compare { grid-template-columns: 1fr; }
}
.cc-takeaway {
margin-top: 1.9rem; padding: 0.95rem 1.2rem; background: var(--accent-soft);
border-left: 3px solid var(--accent); border-radius: 4px; font-size: 0.9rem; color: var(--ink); line-height: 1.5;
max-width: 620px; margin-left: auto; margin-right: auto;
}
.cc-takeaway b { color: var(--accent-deep); }
@media (prefers-reduced-motion: reduce) {
.infographic-classcomponent *, .infographic-classcomponent *::before, .infographic-classcomponent *::after {
transition-duration: 0.001ms !important; animation-duration: 0.001ms !important;
}
}
</style>
<div class="cc-eyebrow">Class Components</div>
<h1 class="cc-title">Creating a Class Component</h1>
<p class="cc-sub">Define it once, use it anywhere, see it render.</p>
<div class="cc-code-compare">
<div class="cc-code-block">
<div class="cc-code-head">
<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M6 3 L2 8 L6 13" fill="none" stroke="var(--accent)" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/><path d="M10 3 L14 8 L10 13" fill="none" stroke="var(--accent)" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/></svg>
<span class="cc-code-name">Welcome.tsx</span>
</div>
<pre><code><span class="tok-comment">// Welcome.tsx</span>
<span class="tok-kw">import</span> <span class="tok-type">React</span><span class="tok-punc">, {</span> <span class="tok-type">Component</span> <span class="tok-punc">}</span> <span class="tok-kw">from</span> <span class="tok-str">'react'</span><span class="tok-punc">;</span>
<span class="tok-kw">class</span> <span class="tok-type">Welcome</span> <span class="tok-kw">extends</span> <span class="tok-type">Component</span> <span class="tok-punc">{</span>
render<span class="tok-punc">() {</span>
<span class="tok-kw">return</span> <span class="tok-punc">(</span>
<span class="tok-punc"><</span><span class="tok-tag">div</span><span class="tok-punc">></span>
<span class="tok-punc"><</span><span class="tok-tag">h1</span><span class="tok-punc">></span>Welcome to React Class Components<span class="tok-punc"></</span><span class="tok-tag">h1</span><span class="tok-punc">></span>
<span class="tok-punc"><</span><span class="tok-tag">p</span><span class="tok-punc">></span>This component is created using ES6 class.<span class="tok-punc"></</span><span class="tok-tag">p</span><span class="tok-punc">></span>
<span class="tok-punc"></</span><span class="tok-tag">div</span><span class="tok-punc">></span>
<span class="tok-punc">);</span>
<span class="tok-punc">}</span>
<span class="tok-punc">}</span>
<span class="tok-kw">export</span> <span class="tok-kw">default</span> <span class="tok-type">Welcome</span><span class="tok-punc">;</span></code></pre>
</div>
<div class="cc-code-block">
<div class="cc-code-head">
<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M6 3 L2 8 L6 13" fill="none" stroke="var(--accent)" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/><path d="M10 3 L14 8 L10 13" fill="none" stroke="var(--accent)" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/></svg>
<span class="cc-code-name">App.jsx</span>
</div>
<pre><code><span class="tok-kw">import</span> <span class="tok-type">React</span> <span class="tok-kw">from</span> <span class="tok-str">'react'</span><span class="tok-punc">;</span>
<span class="tok-kw">import</span> <span class="tok-type">Welcome</span> <span class="tok-kw">from</span> <span class="tok-str">'./Welcome'</span><span class="tok-punc">;</span>
<span class="tok-kw">function</span> <span class="tok-type">App</span><span class="tok-punc">() {</span>
<span class="tok-kw">return</span> <span class="tok-punc">(</span>
<span class="tok-punc"><</span><span class="tok-tag">div</span><span class="tok-punc">></span>
<span class="tok-punc"><</span><span class="tok-type">Welcome</span><span class="tok-punc"> /></span>
<span class="tok-punc"></</span><span class="tok-tag">div</span><span class="tok-punc">></span>
<span class="tok-punc">);</span>
<span class="tok-punc">}</span>
<span class="tok-kw">export</span> <span class="tok-kw">default</span> <span class="tok-type">App</span><span class="tok-punc">;</span></code></pre>
</div>
</div>
<div class="cc-run-wrap">
<button class="cc-run-btn" id="ccRunBtn" type="button">
<svg viewBox="0 0 12 12" aria-hidden="true"><path d="M2.5 1.5v9l7-4.5z" fill="currentColor"/></svg>
<span id="ccRunLabel">Run</span>
</button>
</div>
<div class="cc-output-label">Output</div>
<div class="cc-output" id="ccOutput">
<div class="cc-output-placeholder">Click Run to see the output</div>
<div class="cc-preview">
<div class="cc-preview-bar"><span></span><span></span><span></span></div>
<div class="cc-preview-page">
<h1>Welcome to React Class Components</h1>
<p>This component is created using ES6 class.</p>
</div>
</div>
</div>
<div class="cc-takeaway"><b><Welcome /></b> in App.jsx is what actually calls <code style="font-family:var(--mono-font)">render()</code> and puts this on the page.</div>
</div>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Fraunces:wght@500;600&family=Inter:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500&display=swap" rel="stylesheet">
<script>
(function () {
var root = document.getElementById('cc');
if (!root) return;
/* --- dark mode detection: body attribute > cookie > postMessage > light --- */
function applyDark(dark) {
if (dark) root.setAttribute('data-theme', 'dark');
else root.removeAttribute('data-theme');
}
var bodyAttr = document.body.getAttribute('data-darkmode');
var dark;
if (bodyAttr === 'true') dark = true;
else if (bodyAttr === 'false') dark = false;
else {
var match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
applyDark(dark);
window.addEventListener('message', function (e) {
if (e.data && e.data.type === 'darkMode') applyDark(!!e.data.value);
});
/* --- run / reset --- */
var btn = root.querySelector('#ccRunBtn');
var label = root.querySelector('#ccRunLabel');
var output = root.querySelector('#ccOutput');
var hasRun = false;
btn.addEventListener('click', function () {
hasRun = !hasRun;
output.classList.toggle('is-run', hasRun);
btn.classList.toggle('is-reset', hasRun);
label.textContent = hasRun ? 'Reset' : 'Run';
});
})();
</script>