Topic
Explore the playground gallery
Definition
A learning playground is an isolated, runnable example that lets a learner change one variable and observe a focused behavior without unrelated application complexity.
In simpler words
Use the gallery to experiment safely, then carry the idea back to a real feature.
The gallery is not a replacement for product work: it is a fast feedback loop for concepts that are easier to see than memorize.
After this you can
- Choose a relevant demo
- Turn an observation into a product decision
How the gallery works
Definition
Each playground focuses on one executable concept and presents a small prompt, editable interaction, and observable result.
In simpler words
Change one thing at a time and say what changed before moving on.
Open a card that matches the lesson topic.
Read its hint before changing state or input.
Reset after an experiment, then identify the product situation where the pattern belongs.
Use observations well
Definition
An observation is useful only when it is connected to a defined rule or constraint in the production code.
In simpler words
A fun demo becomes learning when you can explain its boundary.
Record the input, visible result, and rule you inferred.
Do not copy a demo implementation into a feature before checking data ownership, error states, and accessibility.
Live playground
Playground gallery
Open a demo, change one input, and explain the visible result.
Scroll the gallery below for every live demo.
Describing the UI
Live playground
Writing JSX
JSX describes UI. Toggle pieces and watch one tree update — that is declarative markup, not manual DOM edits.
Ticket
Open
return (
<>
<h2 className="card">Ticket</h2>
<p>Open</p>
</>
);Live playground
JS in JSX
Inside JSX, { expression } runs JavaScript. Quotes make a literal string.
Hello, Ada — double is 6
Wrong would be: src="name" (literal text), not src={name}
return <p>Hello, {name} — double is {count * 2}</p>;Live playground
First component
Hello, Ada
function Hello({ name }) {
return <h1>Hello, {name}</h1>;
}Live playground
Import / export
Parent imports TicketRow and composes it — same idea as import { TicketRow } from "./TicketRow".
• Fix cookie auth
import { TicketRow } from "./TicketRow";
function TicketList() {
return (
<ul>
<TicketRow title="Fix cookie auth" />
</ul>
);
}Live playground
Props
Live playground
Conditional rendering
Please sign in
{loggedIn ? <Welcome /> : <Login />}Live playground
Lists
- Auth cookie (open)
- Query keys (done)
- Layouts (open)
Live playground
Purity
Pure render: same props/state → same UI. Derive values; do not fetch or setState while rendering.
3
// Right — derive during render
const label = n > 10 ? "big" : n;
return <p>{label}</p>;
// Wrong — setState during render (loop risk)
// if (n > 10) setFlag(true);Adding Interactivity
Live playground
Events
Try tab away (blur), type, Escape, submit, and click.
Live playground
SPA navigation
Simulated react-router-dom: public /login vs private /course/* (ProtectedRoute).
Requested: /login → rendering /login
<Route element={<ProtectedRoute />}>
<Route path="/course/frontend" element={<FrontendRoadmap />} />
</Route>
// Product app here: Next App Router, not react-router-domLive playground
useState
const [count, setCount] = useState(0); setCount(c => c + 1);
Live playground
Render and commit
setState schedules a render, then React commits DOM updates. The preview updates after the click handler finishes.
Panel is closed
setOpen(true); // 1) render calculates new tree // 2) commit applies DOM changes
Live playground
Queueing updates
Three setN(n + 1) with the same snapshot add 1. Functional updaters add 3.
setN(n + 1); setN(n + 1); setN(n + 1); // +1 setN(n => n + 1); // ×3 → +3
Live playground
State as snapshot
State is a snapshot. Logging right after setState still sees the old value.
Rendered count: 0
—
setCount(count + 1); console.log(count); // previous snapshot
Live playground
Objects in state
setPerson({ ...person, name }); // new objectLive playground
Arrays in state
- Auth
- Query
Managing State
Live playground
Sharing state
Lifted state — both panels read the same index.
Active panel: A
Live playground
State structure
Prefer deriving openCount — mirrored state can drift.
Derived open count: 2
Live playground
Reset with key
Changing key remounts the editor — local draft resets without manual clear.
<TicketEditor key={ticket.id} ticketId={ticket.id} />Live playground
useReducer
count = 0
dispatch({ type: "inc" })Live playground
Context
Deep child reads theme = light (no prop drilling)
Escape Hatches
Live playground
Refs
ref.current = 0 · renders = 0
const clicks = useRef(0);
Live playground
DOM refs
inputRef.current?.focus()
Live playground
Effects
Seconds: 0
Cleanup clears the interval when stopped/unmounted.
Live playground
Effect lifecycle
tick = 0
Live playground
Derived state
Derived during render — no Effect mirroring props into state.
fullName = Ada Lovelace
- Auth cookie
- Layouts
- Query keys
- Pulse draft
const fullName = first + " " + last; const filtered = tickets.filter(...)
Live playground
Custom hooks
Imagine useOnline() wraps this state + event subscription.
Connected
function useOnline() { /* subscribe once */ }Live playground
useMemo
Plain filter runs every render. useMemo recalculates only when tickets or query change — toggle theme (unrelated) and compare the counters.
theme=light · plain path renders=1 · useMemo calc runs=1 · matches=40/40
const visible = useMemo( () => tickets.filter(t => t.title.includes(query)), [tickets, query], );
Live playground
useCallback
Effects depend on the handler. A new function each render re-fires the Effect; useCallback keeps identity until deps change.
status=open · renders=1 · Effect with plain fn runs=0 · Effect with useCallback runs=0
const onChange = useCallback(() => { ... }, [status]);
useEffect(() => { /* subscribe */ }, [onChange]);RTK / Query
Live playground
RTK drafts
Mini createSlice feel: dispatch named actions → state updates → UI re-renders.
value=0 · title="(empty)"
createSlice → configureStore → Provider → dispatch(action)
Live playground
Query keys
- Auth cookie
- Layouts
Different keys → different cache entries.
Live playground
RTK vs Query
TanStack Query — server-owned cache + invalidate after mutations.
Live playground
Cookies
axios.create({ withCredentials: true })Next.js
Live playground
Server vs Client
Can fetch on server; cannot use useState/onClick.
Live playground
Layouts & pages
page.tsx: Ticket list
Live playground
Link & navigate
Prefetch + client transition for internal routes.
Live playground
Fetching data
Interactive tickets/Pulse lists: Axios + Query with credentials.
Live playground
Mutations
Idle
Live playground
Errors & loading
Show skeleton while the segment streams.
Live playground
Cache / revalidate
Query cache: stale
Next revalidatePath/tag is for Next server caches — not Nest auth.
Live playground
Route handlers
Nest: TypeORM, cookie JWT, domain rules.
Keep in mind
- Prefer a five-minute deliberate experiment over randomly changing several controls.
Test
Check your understanding
At least 10 questions — mix of concept, syntax, practical, and logic. Score ≥ 80% (enforced by the API) to save progress.
Checking your session…
10 questions · concept 3 · syntax 2 · practical 3 · logic 2