React Quickstart (Coming Soon)
This tutorial assumes you’re already familiar with HTML, CSS, JS, and npm. It also assumes you know what a JS framework is for.
First, visit the React training ground repo. Press the green Code button and click Download ZIP. Unzip the file and then open it in your editor. Then, run this command in the terminal to install the packages listed in package.json
.
npm install
Then run this command to start the dev server.
npm run dev
You should see something like this in your terminal.
VITE v6.3.2 ready in 251 ms
➜ Local: http://localhost:5173/ ➜ Network: use --host to expose ➜ press h + enter to show help
Visit localhost:5173 in your browser. The web page should say Hello World.
In your editor, you’ll see several files. However, for now you’ll mainly be working in src/components/HelloWorld.jsx
.
Stackblitz
Section titled “Stackblitz”If you prefer to work online, you can also open the React training ground repo on Stackblitz and start coding right away in your browser. You don’t have to run any of the npm commands if you use Stackblitz.
Hello World
Section titled “Hello World”In our file, we have an <h1>
element already added.
function HelloWorld() { return <h1>Hello World</h1>;}
export default HelloWorld;
Task: To make it more personal, change World
to your name.
function HelloWorld() { return <h1>Hello John</h1>;}
export default HelloWorld;
After saving, you should see the browser show your name.
Multiple elements
Section titled “Multiple elements”In React, a component must return a single JSX element. However, you can have multiple elements within a parent element.
Task: Add a <p>
element after the <h1>
element with some placeholder text.
function HelloWorld() { return ( <> <h1>Hello John</h1> <p>Lorem ipsum dolor...</p> </> );}
export default HelloWorld;
Notice that we’ve wrapped our elements in <>
and </>
. This is a React Fragment, which allows us to return multiple elements without adding an extra node to the DOM.
After saving, you should see both elements appear on screen.
App.jsx
Section titled “App.jsx”Before we look at our next topic, open up App.jsx
so you can see how it’s importing HelloWorld.jsx
.
import './App.css';import HelloWorld from './components/HelloWorld';
function App() { return ( <HelloWorld /> );}
export default App;
style attribute
Section titled “style attribute”You can add a style
attribute to an element just like in normal HTML, but in React you pass an object instead of a string.
Task: Add style={{ color: 'red' }}
to the h1 element.
function HelloWorld() { return ( <> <h1 style={{ color: 'red' }}>Hello John</h1> <p>Lorem ipsum dolor...</p> </> );}
export default HelloWorld;
After saving, you should see the <h1>
element turn red in the browser.
You can also create a style object ahead of time instead of putting the object inline.
const myStyle = { color: 'red'}
function HelloWorld() { return ( <> <h1 style={myStyle}>Hello John</h1> <p>Lorem ipsum dolor...</p> </> );}
export default HelloWorld;
External CSS File
Section titled “External CSS File”You typically add styles using external CSS files. Create a CSS file inside src/components
called HelloWorld.css
.
h1 { color: red;}
Task: Delete the inline style
attribute. Create HelloWorld.css
and import it into HelloWorld.jsx
.
import './HelloWorld.css';
function HelloWorld() { return ( <> <h1>Hello John</h1> <p>Lorem ipsum dolor...</p> </> );}
export default HelloWorld;
After saving, you should see that the <h1>
element is still red. Styles imported this way are global by default.
className
Attribute
Section titled “className Attribute”To apply CSS classes, React uses the className
attribute instead of class
(because class
is a reserved keyword in JavaScript).
Task: In HelloWorld.css
, change the h1
selector to a class selector, e.g., .heading
. Then, add className="heading"
to the <h1>
element in HelloWorld.jsx
.
.heading { color: red;}
import './HelloWorld.css';
function HelloWorld() { return ( <> <h1 className="heading">Hello John</h1> <p>Lorem ipsum dolor...</p> </> );}
export default HelloWorld;
After saving, the <h1>
element should still be red.
Add a name prop to the HelloWorld
component.
function HelloWorld({name}) { return <h1>Hello {name}</h1>;}
export default HelloWorld;
Then pass in the name prop to the HelloWorld
component inside App.jsx
.
import './App.css';import HelloWorld from './components/HelloWorld';
function App() { return ( <HelloWorld name="John" /> );}
export default App;
The page should display whatever name you passed in.
Add a state variable
Section titled “Add a state variable”For this section, we’re going to create a new file called Counter.jsx
. Add the following code to it.
function Counter() { return ( <button>Count: 0</button> );}
export default Counter;
Next, make sure to import it into App.jsx
.
import Counter from './components/Counter';
function App() { return ( <Counter /> );}
export default App;
After saving you should see the button appear on screen. It doesn’t do anything yet if you click on it.
Back in Counter,jsx
, import useState
from React and create a state variable for count. Replace the number 0
with {count}
.
import { useState } from 'react';
function Counter() { const [count, setCount] = useState(0);
return ( <button>Count: {count}</button> );}
export default Counter;
After saving, the button should still look the same. It still doesn’t do anything yet.
Make it reactive
Section titled “Make it reactive”Next, add an onClick
handler to the button that increments the count.
import { useState } from 'react';
function Counter() { const [count, setCount] = useState(0);
return ( <button onClick={() => setCount(count + 1)}>Count: {count}</button> );}
export default Counter;
After saving, the number on the button will go up by 1 when you click on it.
Use a function
Section titled “Use a function”Create a function called increment()
. Then replace the inline function with a reference to increment
.
import { useState } from 'react';
function Counter() { const [count, setCount] = useState(0);
function increment() { setCount(count + 1); }
return ( <button onClick={increment}>Count: {count}</button> );}
export default Counter;
After saving, the number on the button should still go up by 1 when you click on it.
Conditional
Section titled “Conditional”Let’s learn how to display elements conditionally.
If you only need an if condition, you can use the &&
syntax in the return statement.
import { useState } from 'react';
function Counter() { const [count, setCount] = useState(0);
function increment() { setCount(count + 1); }
return ( <div> {count > 10 && <h1>Good job!</h1>} <button onClick={increment}>Count: {count}</button> </div> );}
export default Counter;
This will display a heading with the phrase “Good job!” in the browser if the count is larger than 10. Try clicking on the button more than 10 times to test it out.
If you need an if and an else statement you can use a ternary operator in the return statement.
import { useState } from 'react';
function Counter() { const [count, setCount] = useState(0);
function increment() { setCount(count + 1); }
return ( <div> {count > 10 ? <h1>Good job!</h1> : <h1>Let's get started</h1>} <button onClick={increment}>Count: {count}</button> </div> );}
export default Counter;
This will display a heading with the phrase “Good job!” in the browser if the count is larger than 10. If not, it will display the phrase “Let’s get started”. Try clicking on the button more than 10 times to test it out.
If you need a more complicated conditional structure, you can use an if/else if/else statement outside of the return statement.
import { useState } from 'react';
function Counter() { const [count, setCount] = useState(0);
function increment() { setCount(count + 1); }
let message; if (count > 10) { message = <h1>Good job!</h1>; } else if (count > 5) { message = <h1>Not bad</h1>; } else { message = <h1>Let's get started</h1>; }
return ( <div> {message} <button onClick={increment}>Count: {count}</button> </div> );}
export default Counter;
This will display a heading with the phrase “Good job!” in the browser if the count is larger than 10. If the count is between 5 and 10, it will say “Not bad”. If it’s less than 5, it will say “Let’s get started”. Try clicking on the button more than 10 times to test it out.
For this section, we’re going to create a new file called TodoList.jsx
. Add the following code to it.
import { useState } from 'react';
function TodoList() { const [items, setItems] = useState([ { id: crypto.randomUUID(), text: 'Buy groceries' }, { id: crypto.randomUUID(), text: 'Read a book' }, { id: crypto.randomUUID(), text: 'Go for a walk' }, ]);
return ( <> <ul> {items.map((item) => ( <li key={item.id}>{item.text}</li> ))} </ul> </> );}
export default TodoList;
Next, make sure to import it into App.jsx
.
import TodoList from './components/TodoList';
function App() { return ( <TodoList /> );}
export default App;
Add items
Section titled “Add items”Next, add a newItem state variable, the handleAdd()
function and the <input>
element.
8 collapsed lines
import { useState } from 'react';
function TodoList() { const [items, setItems] = useState([ { id: crypto.randomUUID(), text: 'Buy groceries' }, { id: crypto.randomUUID(), text: 'Read a book' }, { id: crypto.randomUUID(), text: 'Go for a walk' }, ]); const [newItem, setNewItem] = useState("");
const handleAdd = () => { setItems([ ...items, { id: crypto.randomUUID(), text: newItem } ]); setNewItem(""); };
return ( <> <input value={newItem} onChange={(e) => setNewItem(e.target.value)} /> <button onClick={handleAdd}>Add</button> <ul> {items.map((item) => ( <li key={item.id}>{item.text}</li> ))} </ul> </> );}
export default TodoList;
Remove items
Section titled “Remove items”Next, add the handleDelete()
function and the <button>
element.
18 collapsed lines
import { useState } from "react";
function TodoList() { const [items, setItems] = useState([ { id: crypto.randomUUID(), text: "Buy groceries" }, { id: crypto.randomUUID(), text: "Read a book" }, { id: crypto.randomUUID(), text: "Go for a walk" } ]); const [newItem, setNewItem] = useState("");
const handleAdd = () => { setItems([ ...items, { id: crypto.randomUUID(), text: newItem } ]); setNewItem(""); };
const handleDelete = (id) => { setItems(items.filter((item) => item.id !== id)); };
return ( <> <input value={newItem} onChange={(e) => setNewItem(e.target.value)} /> <button onClick={handleAdd}>Add</button> <ul> {items.map((item) => ( <li key={item.id}> {item.text}{" "} <button onClick={() => handleDelete(item.id)}> Delete </button> </li> ))} </ul> </> );}
export default TodoList;
Filter items
Section titled “Filter items”Next, add the toggleItem()
function and the <input>
element. Also, add a completed property to each item in the list of items.
import { useState } from "react";
function TodoList() { const [items, setItems] = useState([ { id: crypto.randomUUID(), text: "Buy groceries", completed: false }, { id: crypto.randomUUID(), text: "Read a book", completed: false }, { id: crypto.randomUUID(), text: "Go for a walk", completed: false } ]);14 collapsed lines
const [newItem, setNewItem] = useState("");
const handleAdd = () => { setItems([ ...items, { id: crypto.randomUUID(), text: newItem } ]); setNewItem(""); };
const handleDelete = (id) => { setItems(items.filter((item) => item.id !== id)); };
const toggleItem = (id) => { setItems( items.map((item) => item.id === id ? { ...item, completed: !item.completed } : item ) ); };
return ( <> <input value={newItem} onChange={(e) => setNewItem(e.target.value)} /> <button onClick={handleAdd}>Add</button> <ul> {items.map((item) => ( <li key={item.id}> <input type="checkbox" checked={item.completed} onChange={() => toggleItem(item.id)} /> {item.text}{" "} <button onClick={() => handleDelete(item.id)}> Delete </button> </li> ))} </ul> </> );}
export default TodoList;
Next, add a hideCompleted state variable and a filteredItems variable.
import { useState } from "react";
function TodoList() { const [items, setItems] = useState([ { id: crypto.randomUUID(), text: "Buy groceries", completed: false }, { id: crypto.randomUUID(), text: "Read a book", completed: false }, { id: crypto.randomUUID(), text: "Go for a walk", completed: false } ]); const [newItem, setNewItem] = useState(""); const [hideCompleted, setHideCompleted] = useState(false);
19 collapsed lines
const handleAdd = () => { setItems([ ...items, { id: crypto.randomUUID(), text: newItem } ]); setNewItem(""); };
const handleDelete = (id) => { setItems(items.filter((item) => item.id !== id)); };
const toggleItem = (id) => { setItems( items.map((item) => item.id === id ? { ...item, completed: !item.completed } : item ) ); };
const filteredItems = hideCompleted ? items.filter((item) => !item.completed) : items;
return ( <> <input value={newItem} onChange={(e) => setNewItem(e.target.value)} /> <button onClick={handleAdd}>Add</button> <input type="checkbox" checked={hideCompleted} onChange={() => setHideCompleted(!hideCompleted)} /> <label>Hide Completed</label> <ul> {filteredItems.map((item) => ( <li key={item.id}> <input type="checkbox" checked={item.completed} onChange={() => toggleItem(item.id)} /> {item.text}{" "} <button onClick={() => handleDelete(item.id)}> Delete </button> </li> ))} </ul> </> );}
export default TodoList;
CSS + JS
Section titled “CSS + JS”For this section, create a new file called HelloWorld.css
in the components folder.
.red { color: red;}
Next, import that file inside HelloWorld.jsx. Then, use a ternary operator with the className prop to toggle the class. Also, add an onClick prop with an inline function that toggles the isActive state variable.
import { useState } from 'react';import './HelloWorld.css';
function HelloWorld() { const [isActive, setIsActive] = useState(true);
return ( <> <h1 className={isActive ? 'red' : ''}>Hello World</h1> <button onClick={() => setIsActive(!isActive)}> Toggle </button> </> );}