Coding for All
Lesson 9: Mini App: Pizza Vote
Mini App: Pizza Vote Combine components, props and state into a tiny working app.
1import { useState } from 'react';
2
3function VoteButton({ name }) {
4 const [votes, setVotes] = useState(0);
5 return (
6 <button onClick={() => setVotes(votes + 1)}>
7 {name}: {votes} {votes === 1 ? 'vote' : 'votes'}
8 </button>
9 );
10}
11
12function App() {
13 return (
14 <div>
15 <h1>Vote for tonight's pizza!</h1>
16 <VoteButton name="Margherita" />
17 <VoteButton name="Pepperoni" />
18 </div>
19 );
20}
21export default App;
Terminal
$ npm run dev
VITE v5.4 ready in 312 ms
Local: http://localhost:5173/
(your app is live: look at the browser window above!)
Every line, explained
import { useState } from 'react';
useState comes from the React library itself. This locked import line brings it in; you'll use it a few lines down.
function VoteButton({ name }) {
The grand finale uses everything at once. VoteButton is a reusable component (lesson 4) that takes a name prop...
const [votes, setVotes] = useState(0);
...and has its OWN state (lesson 6). Here is the payoff of components: every copy of VoteButton gets a separate votes memory. React keeps them apart automatically.
return (
When JSX spans several lines, it goes inside round brackets after return. The brackets keep the JSX attached to the return: without them, JavaScript would think the return finished at the end of that line and hand back nothing.
<button onClick={() => setVotes(votes + 1)}>
Each click adds a vote to THIS button's own counter.
{name}: {votes} {votes === 1 ? 'vote' : 'votes'}
Props and state side by side in one label: the name arrives from outside, the votes live inside. And a bonus reuse of lesson 8's ternary, so one vote reads "vote", not "votes".
</button>
Close the button tag.
);
The ); closes the return's round bracket.
}
This } closes the component function.
function App() {
The App component: every lesson's page starts from this function.
return (
When JSX spans several lines, it goes inside round brackets after return. The brackets keep the JSX attached to the return: without them, JavaScript would think the return finished at the end of that line and hand back nothing.
<div>
A component must return ONE outer tag. Putting two siblings side by side at the top level is an error, so a wrapping <div> holds them together.
<h1>Vote for tonight's pizza!</h1>
A heading to set the scene.
<VoteButton name="Margherita" />
One VoteButton...
<VoteButton name="Pepperoni" />
...and another. Same component, separate names, separate vote counts. Click both in the preview and watch them count independently: you have built a real interactive app from reusable parts. That is React!
</div>
Closing tag for the wrapping div.
);
The ); closes the return's round bracket.
}
This } closes the component function.
export default App;
export default App hands your component to the rest of the app. A locked line in every lesson: the app's starter file (main.jsx) imports App and mounts it on the page.