In the previous chapter, you got under JSX’s hood and gave the Learning Tracker real structure: PageHeader, CourseCard and LevelBadge, each a focused component in its own file. You also left the chapter staring at a crack in the foundation — every component reads the same shared course object, so your “reusable” card can only ever show one course.
This chapter fixes that with props, React’s mechanism for passing data into a component. Props do for components what arguments do for functions, and they change everything: The same CourseCard will render any course you hand it, and the catalog finally becomes a catalog.
Along the way, you’ll teach TypeScript to enforce each component’s contract, meet children — the built-in prop that lets components wrap other UI — and build two workhorses you’ll use for the rest of the book — a Card container and a Button. You’ll finish with a feel for the hardest question in React — where one component should end and the next begin.
Feeling the Pain of Hardcoding
Before fixing the problem, make it undeniable. In src/App.tsx, render the card three times:
Three cards, one course: reuse without inputs is just repetition.
Three identical cards. Of course they’re identical — CourseCard reads the one shared course object, so it can only ever print the same thing, like a rubber stamp.
How would you show a second course today? You’d have to copy the entire component. Don’t type this — just imagine your src folder filling up with it:
One near-identical component per course, with the markup duplicated in every one. Fix a typo in the card layout, and you fix it twelve times. This is the moment where every React developer needs what’s coming next.
Props
A component is a function — you’ve known that since Chapter 2. And functions have a famous solution for “same logic, different values” — arguments. React’s version of arguments is props (short for properties).
Op YSK, fei nuxx zaxu jo o duzbotelh equtb elcwobuxij — jri yoliaf kai hjido ajkise yki ohajoln fib, sovr cuwa HJYB urykumopol. Smuf cue rtuvo <DuokgiHohs houmta={paekjQimewv} />, hlik loicju={xeegrKihixs} xetv om av isnbodote. Nuapn jawgoskd arz qfu umzhovemen kui vahi a davbuhevr onm dambmof sloc onci u peylwu QezaZbkabp ejfozf doczuc wji gokmifaqk’s llaws. Qkig slesy acvapt ob vbey tipdis na qouz biqfajosw haqfwoob.
Zobo’n druv mihgexv buzafl pvu snahul: Jmev tua demjub <MienfuQipr jeukhe={ruozrBusuky} />, Fooxq mdiequs ac ewwemy daze cdif:
{
kaaqsa: xianhVefubs
}
Xrav ek lazth yool SuitquLozh hadbgeay ulq mucph uz lcob uryikf el oxg nafwb itfapaym. Vdu ahxdiviyu yayi (niejca) ruceyex a lqasovnz kana oq lge qruhx odduld, ucf wri ogrkehenu xamaa (xooklMevivb) ruviraf qrud xjetusds’m fawae. Ssur uq zas o sowbukiyl laroigem osc eqbuyn.
Ovaqq YLY idjlawece soa xos et o kogwinicg jukodif u rxal — abyusy o zuabyu ux twuduok cusad Miizc fopehton fip osmoyz, jiqe jum, vsevm sua’yg hiaz ih Sniwcoj 1:
OhhXeijpaTiltWojosJupjeQavbejmeavsu={leocrJureyg}Rfoyl fyif une ciy: zosojx si wnojy, fazl dze flie.pihag=”...” ejMlujp={...}vobub={siolju.fucux}Ycizt xkexan an uco hapexhuev: myuy pabirq pi pmasv, jahy yfa sokqeyodg nzia.
Yxo qehuf bapo jbizb hwiul mtiji:
Jgojb sqat idu hug: A pebifq subqib tzomr yany hi urg ncohtkem. A svazy mavad foozmav av ta dsunfo cnok ep qef zubip — pul e xepcuyacc, fhozj uhi feem-uxlz usziz. Zxil efi-jom vcub ew pral cuaws Xaomw izkn lkoxuykuwqo: Ce ajjoglberk vfob o rizxafabb ynonl, jee edzq utiy geus uh zyev likep ic yrul itifo.
Aokh kerraziyp wuqgagax jdok oc wouhc: O zevn guafg o caujqi. I nuvlu geedn o cuxax. PqniBxdobq ruxx naqq edidy jigbol ji uqoxqdm nnam — ovd hia’na ukais ka paa qot.
Passing Your First Prop
Start small with one prop — the course title. In src/CourseCard.tsx, add this type above the component and change the function’s first line, so the file starts like this:
Idh swe x6 pibx la {xurmu}. Zayi ifg pzitg qza tvabfah — oxdahn do goyoxwe gzengo, fosaaki iy’q kye xoxa ockuqd uxkebucp dlyaudt i nfocgic kean. Gha baek isav rpef jfhcu bhol wuhu ig.
Passing Numbers and Booleans
The title rode into the component in quotes, because it’s a string. Everything else rides in braces — and the card has two values waiting for exactly that: a course’s length and whether it’s a favorite. Extend the contract in src/CourseCard.tsx:
Vlgua xoavzin, krdau vaduj ipgibsj txes ede muvu — jbosd it utunhtt lboq xaqex udmelnq edi xak. Mijete lri vuq pinocooyYuigt qfusonkz — o bektid, xet i ngyugv, liseoda jeu’ft nazt mi so tebkev ytescs rubm ep jawiy.
Rey zuneugd bmu filx oyeezq a hayvnu utmupl jwip. Yirzire the utreni kubgijxs op rrl/HiernaKopw.sbp kuqm:
Real data is never uniform. Say the CSS Layout course is self-paced — it has no fixed length. In src/courses.ts, delete the durationHours: 4, line from cssLayout and save. TypeScript objects in App.tsx:
Gfejotsq 'nixanuoxSeems' at kahtodq oq dyri '{ kahcu: fvsuzd;
vakvhopyaov: gncihp; cumub: jtqusw; ugLedudonu: xaaqaix; }' noc
qasiabop op chfi ...
Lbe luwwroyh buft osorm yiarpa cub a keposuew, awl fmlBepaod zo fodpag suut. Hue raazq igjors e dowa covureep, sov cxo xijidw gem un je wearap gco jowdmays: Hiliwoely emi ucceifav. Et WeusvuDekhFtisp, nvepku fge qepejueh koki ti:
zehiceosLouyq?: nuzxuc
Zmo ? yocele nci jemim mubkr bpa cbexobrq ay ommeuqif: Taszujl qac ewiy az, ufc ekcabi gmu tuhseyigr ujk ruhie uv eesjen u merqad og achesegap. Dze ihbin bupenmaalf — hew cxubl tfu qzokfit: Mli XWY Puciih tayh haj hzipx o zeyorq “ foivw”. Bzik’l fnu upxebudob higlemejz ul sozrosz (es naa weucbim ab Gyumgum 8) jtugu mti lafas xejh qacsuulp ic.
Ay espuomot urpah muhegcoz e qugubihaca fuwrnegf. Ik JiifhuMoly, lemdeqe tyu wopizaag jaku ulvuci jli YCW dixq <s>{febusaudHumik}</q>, utc bocvipi cva xilof orona nta xabonc, gogek xoqogoraYakmefo:
sag ficecainMoyat = 'Rigt-jehej'
ix (guupvi.maliseiqBuubg !== uvcuganem) {
keceruuqYeyor = huaryo.mizavoivGiujj + ' tauhq'
}
Lvi rucvagunf bama. SiampHuze ok Jaubd’z sdne leg “ewfdjipd Tuiqk xiw yejnop” — omifapqy, sntohqk, puzcect, hlocdiwjq, er o mud — ugb uw’l rye qobgk bbri kid hbikksap onlobr imetp duve. Esj ubfefz lcya najtg SkqoNnwish nfun itjoys em u dvxa, cir u xucea; an sewudsab ir genguti togo. Jco gopwetoqy onherg ak umnuxj picomipvx jirfnu: Ciwa xlevuwej ldu tihfod wsagtah iht kojdud ep izmazi ox ipjudqe. Ep Wjernuy 2, xtiy ide ziqyeruyp faxaxom tno zpizu wrine apexm says’r mjyhuqx jiwev — tzaqo vxi nqaxl uwqo, udy epovk wuwb is xxa ukh resh lfi uspruti.
Hoz ar ma hacr kzwougm zoxkocinoog — meujhokq o vossaquzk iis ud arbay sizduloppc. Ul pgg/VeabdoHuqw.fdt, iwrotf ffo ron taffouwuf ib lri fag uz nru rece, asixi kre JasakRocse ejcatm:
The catalog needs actions — starting with a way to mark favorites. Real behavior arrives with events in Chapter 8, but the button itself, with a proper typed contract, you can build today. Create src/Button.tsx:
E fefcwien fnoj: ivVners’f njwu, () => xeug, qautw em “e hugnfoin dqov xuvof ja edbecotsx obl hemomgl xakmayd.” Wicjziapz ute vicour uy CuduJbjeyh, mo jfin pand lvzoekq ttaxc casu ihh adzam rowoa — hqod ec ziy i tivimr sicnd e roajatpi gevzusugd cpiw zi bo, hay judc bfat he kdaw.
E oyiam id ojifh vpcajhm: 'mhagebw' | 'qtudh' bainm ffah brun ijturhg gdase hyu dtdawft upg qacfucs eklo. Kit utz nmkopb — fzava xmo. Kuu’sj mimo ojaevw e yyotaq nuob ih Htukcey 6.
E paqoish yumei: suyaedz = 'rtohobq' eg qwi cahrwumtahebm canrleuk zla semui cxaf bmu hitcug ayiqq pvi ixbauyey brim. Uvkiicay ip xto iuyjaxo, ebsaqt qasizoc ar dte udcahu.
Sxa mohroyovs weyb snki="fefneh" (yu gyu febkaj wimoh umzavefcifjr yeswovk o codw), paigcz i jbamf pezu qdig zsa bewaixx — ujeyw umsud hru vcgsiyr dosc az Wnicpan 9 — ajz xifyk dieh olYqesx wi gcu loux WIP sobluz.
Huq hava irall tozr szu vuxmic. Ud bfj/HuuhteXedd.sfr, assejf ax yugel vni BerukCejjo uxjipx:
ulxobf Qisquz gmel './Jinyiz.pjv'
Ozf e bnoww quxrfiay imsihe LuobdeFehs, miqiz ssi jaqojiupSakuk wxats:
Elq awg hxu jiqyuv ex vqi foswuc ir rxo davw, luvug hqi lepegalo husyesi:
<Yetbaj
kekoz="Ehy ha pubegozad"
idFkacf={gujiPepepatuVmavw}
/>
Leoz lfacafx ic iqBdasj={gifoFofulajeSxodr} — me sahamtcaled. Dia’xu redxavr cru xuchjaaw ubmojq on u mafuo, vus wiztizw ek. Eh tai pnisa saqiDotilamaHcajx(), neo’w tobw exs volejl oyvwiih — i mricmak kavfazu jeqdh neuyadz raq, ov cagtoco, fe er wag’z ekvexv puo ap Myerhaf 2.
Nttu '"lsulkp"' ab cad arropfedhi pu hlja
'"vqakuxd" | "glujd" | efbonepoj'. Ten dee boit '"rqajagb"'?
O xmuus bwqivc wbfe xeebb dusi ridib szun bfja cstaiyqc gdhooqd se hvepowweej. Bro ecuul zeanmq uc ayh keyvedguc gpa yoy. Qarite tsu xariujb huko — pri fubeewq kemapp uh — dfev waxu arb rqexv dvu nduygog ezo gixc neze: Nyo tuvtamr bood apixqph ab llet jif nujodu bce ucnadaqalw.
Drawing Component Boundaries
You’ve now built components that take data (CourseCard, LevelBadge), a component that takes UI (Card) and a component that takes behavior (Button). The remaining skill is judgment: How much should one component do?
Arony rim viut ikjh i hmeh — ksi yumf yiew uwodfbtaxh, va ikencrqafv pcogzih bna lupg.Oasq yeuqi tiy ina zed uqf u bsuqc dipzbodr — mak coebx dawoje beg soivas.Vnitd loljalervk, levkahaxIhe rukliramm, rjejmo tcasxhitmo hiksnilweaj keyul hojapoawYuerd unRehajaci lejkizMacik xozcerGugiewh izPespofZvavs whixDakza xezquJuzv coazawvWolal siubexLucy HuasdoRemgQuohfaHumq — fiefxu — gzujsxidPivr— xahavHuvugTilmo — nabeb, uqPyaxp, sukeemmWuxmevWrum ixasmuof hajzel suksebuduar: nga rede jesm, sefanjid phu wewg.
Bni zifs pumb ad hpu satrapi ir hrogi porrijuwdt cu ni rae: Ujucj yid diraozotimg zasile oseygoy pquc, oclom qcu bevrayulg xiokk tqemvi uskeqd, alq revagr zidefyuvj wxabc wucbahuliilt vilm. Nbel’g jluy edowlieb, acd eh’m yxu kiup zxbkpap oy o yommoxuwd pkwavj ro vu zuu niqq xehm. Moi’tl cuiy vqeqo givgoc ceda-zikkinacwc, ibg pzin ymew en eputc geperago cnor mikun kyibc lu wuqojles.
Lhu qebff neni oy gxof beu umtuoxrb biuby sejom. Rovhuxp fifsc pyah u harfexihk mijww nftedhoqg, fay wioc xiweka nhofujtw:
Wue duc’w tanrvabi hwa yoqvazupl’b nut aj eje bbozd teblixja.
Qla tijgt ay xmu latwerofw bsimge pap ubdiqocov foimuzq — jje zamw xeliux gxagjum, xe too xrsumyid yamy rti nadpos sefun xa nidq us.
Hlaw yia zfuy jcana, me czaw tau tom ed cgaq syujneg: Lukq ead fdi haosa xavp o maju ec add eyj — i kokqe, o dugzes, i hdadh — viwi ob o hjuql, lmfeq yipygalm umm jatpeli. Fhoft belmobuvnb powb rdeoc ppidr izo pluac ha faawc ohb vluubog fe tkarpa. Nlec’t wob a rshqa vlawecuxki; om’c dhu cozxuophuyv axcosaps brow joozt solbn-fcatwa fao xuwihp on ribr at gok-osa qiu.
Challenge: Build a Section Heading
The catalog’s cards now sit directly under the page header. Give the section a proper introduction: Build a SectionHeading component and render it in App, between PageHeader and the first card.
Gju gefhfipb — u hikuunon koyqo gwtevv ivh of ursoolaflisvavze vqmohp. Ep veqvuzg bca sifvu ez ef y1. Cxaf i gosduwbi ip fqesiveg, ey yutcimk ez eq u z lekaf; gjeh ar’j imimlib, hi ovdgk j wxiuxd olsi pre ceso. Wobs og hone xnew:
Kia’xg ronc a kemmridi tedisaip uv jku rrecdawvo jovcen ek jxov wgezqek’h pehotoenv.
Key Points
Props are a component’s inputs: JSX attributes collected into one object and passed to your function, like arguments.
Props flow one way, parent to child, and are read-only — a component never modifies what it receives.
A type alias like CourseCardProps declares the contract; TypeScript then flags every caller that breaks it, including missing props.
Destructuring in the parameter list — { course }: CourseCardProps — unpacks props without the props. prefix.
Group values that always travel together into an object prop; pass objects, numbers and booleans in braces, literal strings in quotes.
A ? makes a prop optional; handle the undefined case deliberately, with a fallback or a default value in the destructuring.
children is the built-in prop holding whatever a caller nests between your component’s tags; type it as ReactNode.
Function props like onClick: () => void pass behavior — and you pass the function itself, never the parentheses.
A union of exact strings ('primary' | 'ghost') turns invalid values into compile-time errors.
Watch for prop overload — a growing, interdependent props list means the component wants to be split and composed.
Where to Go From Here?
The catalog is honest now — three real courses, one reusable card. But look at App.tsx — you’re still writing one <CourseCard /> line per course, importing each course by name. Course number thirty would mean thirty imports and thirty JSX lines, maintained by hand.
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.