React from zero
The six words you need before any of it makes sense
Component, JSX, props, state, render, hook – once these six words sit, the rest of React is detail work.
You know JavaScript. What you are missing is the language React uses to talk about itself. Here are the six words that turn up in every explanation – each in two sentences.
Words with a dashed underline can be clicked – the explanation appears right there. And anything folded away under “In more depth” can safely be skipped on a first pass.
1. Component = a function describing an interface
A ComponentA function that describes what a piece of the interface should look like – a button, or a whole page.It always starts with a capital letter and returns JSX. You then use it like your own HTML element: <MyButton />.→ is a perfectly ordinary JavaScript function. The special part: it does not return a number or a string, but a description of what should appear on screen.
function Welcome() {
return <h1>Hello!</h1>;
}
// You use it like your own HTML element:
<Welcome /> <Welcome /> is your component; <welcome /> would be an unknown HTML element to React. The first letter decides.
2. JSX = HTML living inside JavaScript
The line <h1>Hello!</h1> in the middle of your code is called JSXThe HTML-looking syntax sitting inside your JavaScript, lines like <p>Hello</p>.It is not real HTML. A build tool turns it into ordinary function calls before anything runs.→. It looks like HTML but it is JavaScript: a build tool turns it into ordinary function calls before anything runs.
const name = "Ada";
const isAdmin = true;
<div className="card"> {/* class is called className here */}
<h1>Hello, {name}!</h1> {/* curly braces = JavaScript */}
<p>{2 + 3} messages</p> {/* any expression works */}
{isAdmin && <button>Delete</button>} {/* condition */}
{isAdmin ? <p>Boss</p> : <p>Guest</p>} {/* if / else */}
</div> Since there is no for in JSX, you build lists with map: {names.map(n => <li key={n}>{n}</li>)}. We will get to that key in a moment.
3. Props = the arguments of a component
PropsThe values a component receives from the outside – like the arguments of a function.Short for “properties”. They come in from above and must not be changed by the component.→ are the values a component receives from outside. You write them like HTML attributes, and the function receives them as one object.
function Greeting(props) {
return <h1>Hello, {props.name}!</h1>;
}
// It is more common to unpack the object straight away:
function Greeting({ name, loud }) {
return <h1>Hello, {name}{loud ? "!!!" : "."}</h1>;
}
<Greeting name="Ada" loud />
<Greeting name="Grace" /> A component must never change its own props. They belong to whoever passed them in. Anything that should change is state – which is next.
4. State = a component's memory
A normal variable inside a component is gone after the next pass. StateA value a component remembers and is allowed to change – the text in an input field, for example.When state changes, React redraws the component. That is exactly what separates it from a normal variable.→ is the value React keeps for you – and when you change it, React redraws the component.
function Counter() {
let count = 0;
return (
<button onClick={() => count++}>
{count}
</button>
);
} function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
{count}
</button>
);
} On the left count does briefly go up – but nobody tells React, and on the next pass everything starts at 0 again. On the right React knows about the change and redraws.
Picture React as an illustrator. A normal variable is a thought they immediately forget. useState is their notebook: whatever is written there survives – and the moment you write in it, they redraw the picture.
5. Render = React calls your function
A RenderReact calls your component function and looks at what it returns. Nothing more happens yet.The result is a description (“this is how it should look”). Only afterwards does React decide what actually changes on the page.→ is nothing mysterious: React calls your component function and looks at what comes back. Then it compares that result with the previous one and changes only the differences in the browser.
You click the button
↓
setCount(1) – React notes: "something changed here"
↓
React calls Counter() again ← this is the render
↓
Compare results: "the 0 has to become a 1"
↓
Change just that one number in the browser A Re-renderReact calls the component function again because something changed.That does not mean the page is rebuilt. If the result is the same as before, nothing changes in the browser at all.→ simply means the function runs again. If the result is the same as before, nothing on the page changes at all.
6. Hook = a borrowed ability
A function on its own cannot remember anything. A HookA built-in function whose name starts with “use” and that lends your component an ability – such as remembering something.Hooks may only appear at the top level of a component, never inside an if or a loop.→ lends it exactly such an ability: useState the remembering, useEffect reacting to the outside world, useRef a silent note. Every hook starts with use.
Two rules – these always apply:
1. Hooks go at the very top of the component.
Not inside an if, not in a loop, not after a return.
2. Hooks only live in components (capital letter)
or in your own hooks (name starts with use). React keeps track of your hooks by their order, not their name. If one is skipped on the second pass, the whole list shifts – and your counter suddenly holds the value of the text field.
All of it together
import { useState } from "react";
// A component that receives a prop
function Greeting({ name }: { name: string }) {
return <p>Hello, {name}!</p>;
}
export default function App() {
// State: the text somebody types
const [name, setName] = useState("World");
return (
<div>
<input
value={name} // driven by state
onChange={(e) => setName(e.target.value)} // typing changes state
/>
<Greeting name={name} /> {/* pass the prop on */}
</div>
);
} ▸ In more depth: what is a “controlled input”? optional
In the example above the <input> carries both value and onChange. That is called a controlled field: not the browser decides what is in it, but your state.
// controlled: state is the source of truth
<input value={name} onChange={(e) => setName(e.target.value)} />
// uncontrolled: the browser keeps the value itself
<input defaultValue="World" /> The sequence is a small circle: you type → onChange fires → setName changes the StateA value a component remembers and is allowed to change – the text in an input field, for example.When state changes, React redraws the component. That is exactly what separates it from a normal variable.→ → React redraws → the field shows the new value. It feels like typing straight into the field; in reality React takes the detour through state.
If you write value={name} and forget onChange, nothing can be typed into the field – the state never changes. React warns about this in the console.
Does it stick?
6 questions on this lesson. Wrong answers show up in your stats.
Now write it yourself
Build a greeting: whatever someone types into the field should appear right below it. You need exactly what was covered above – a prop, a state and a controlled input.
- □
GreetingshowsHello, <name>!– the name arrives as a prop - □Typing in the field updates the greeting immediately
- □The field starts out containing
World
import { useState } from "react"; // TODO: accept the "name" prop and output "Hello, <name>!" function Greeting(props: { name: string }) { return <p data-testid="greeting">Hello, ???</p>; } export default function App() { // TODO: add state, starting value "World" return ( <div style={{ fontFamily: "system-ui", padding: 16 }}> <input aria-label="name" /> <Greeting name="???" /> </div> ); }