React
a gentle introduction
$ npm create vite@latest
Hands up
- Who has written HTML?
- Who has written JavaScript?
- Who has changed a page with
document.querySelector?
- Who has used React before?
What is React?
- JavaScript library
- Created by Facebook (now Meta)
- Used for building user interfaces
- Components, all the way down
- Much easier than wiring up the DOM by hand
- A library, not a framework
— no router, no data layer. Bring your own.
React prerequisites
- JavaScript fundamentals
- Destructuring
const { name } = props
- Arrow functions
x => x * 2
- Array methods
map, filter
- Spread
[...todos, item]
- Modules
import / export
- Fetch API & Promises
No longer on the list: JavaScript classes.
The old way, the React way
On the left you tell the page what to change.
On the right you say what it should be.
UI = f(state)
Your component is a function. Give it the data, it gives back the screen.
Data changes → React calls it again.
Oh Wait…
npm
create-react-app
vite
Getting started
- Needs Node.js (the LTS version)
- Opens on
http://localhost:5173, reloads as you save
- Old tutorials say
create-react-app.
Skip those.
What you get
$ tree my-app
index.html ← one empty div
package.json
src/
main.jsx ← start here
App.jsx ← your code
App.css
One empty div. React fills it, and owns everything inside.
Every React component ever…
No class. No render(). No constructor. No super().
A component is a function
Name it with a Capital.
<greeting> is an HTML tag, <Greeting> is yours.
JSX
Looks like HTML. Is JavaScript.
{ } drops back into JavaScript
- One root element — or a fragment
<></>
- Close every tag:
<br />
className, not class
- camelCase:
onClick, tabIndex
Props
Arguments for components.
Props are read-only.
A component never changes its own props.
children
Lists
key tells React which item is which
— use an id from your data, not the array index.
Conditions
Careful: {count && <Badge />}
prints a 0 when count is 0.
Styling (CSS)
- Import the stylesheet where you use it
- Inline styles are an object; property names are camelCased
React so far
createRoot(…).render(<App />)
- JSX — HTML in JavaScript,
{ } for expressions
- Components are functions that return JSX (Capital names)
- Props go in, read-only
- Lists with
map and a key
- Conditions with
? : and &&
Things that change
This never changes. Why?
- Changing a variable doesn't tell React to draw again
- And if it did draw again,
let count = 0 would run again
useState
A value React remembers, and the only way to change it.
What happens on a click
- render #1 · count = 0 · first render
Events
Pass the function. Don't call it.
Inputs
State is the source of truth. The input just shows it.
Replace, don't mutate
on screen
Lifting state up
Data flows down as props. Events flow up as callbacks.
useEffect
For talking to things outside React: timers, the network, the browser.
| no array | after every render |
[] | once, when the component appears |
[userId] | again whenever userId changes |
Fetching data
Good to understand once. In a real app, a library does this for you.
You might not need an effect
✗ an effect to keep two states in sync
If you can work it out from props or state, it is not state.
Rules of hooks
- Call them at the top level of the component
— not inside
if, loops or callbacks
- Only in components, or in your own hooks
- Your own hooks start with
use:
useLocalStorage, useWindowSize
The linter that comes with Vite catches all three.
If a tutorial shows you a class
| class X extends React.Component | function X() |
| this.props.name | function X({ name }) |
| this.state, this.setState | useState |
| componentDidMount | useEffect(…, []) |
| componentDidUpdate | useEffect(…, [deps]) |
| componentWillUnmount | the effect's cleanup function |
| shouldComponentUpdate | memo — or let the compiler do it |
Classes still work. New code doesn't use them.
Thinking in React
- Draw boxes around the UI — each box is a component
- Build it static first, with props only
- Find the least state you need
— everything else is calculated
- Decide where each piece of state lives
- Pass callbacks down so events flow up
Exercise: a todo list
- A
TodoItem that shows a text prop
- Render a hard-coded array with
map and a key
- Move the array into
useState
- An input and a button to add a todo
- A checkbox to mark one done — replace, don't mutate
- Stretch: delete, a "hide done" filter, keep the list in
localStorage with useEffect
What’s next?
| Pages and URLs | React Router |
| A full framework | Next.js, React Router in framework mode |
| Server data | TanStack Query |
| Types | TypeScript — --template react-ts |
| Phones | React Native — same components, native screens |
Next time…
React Native
Same components, same props, same state.
<View> and <Text> instead of
<div> and <p>, on a real phone.
Who is your best friend?
(besides Google, StackOverflow and ChatGPT)
react.dev
Hungry for more React?
And in the browser: the React Developer Tools extension.