Skip to content

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.

Terminal window
npm install

Then run this command to start the dev server.

Terminal window
npm run dev

You should see something like this in your terminal.

Terminal window
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.

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.

In our file, we have an <h1> element already added.

HelloWorld.jsx
function HelloWorld() {
return <h1>Hello World</h1>;
}
export default HelloWorld;

Task: To make it more personal, change World to your name.

HelloWorld.jsx
function HelloWorld() {
return <h1>Hello John</h1>;
}
export default HelloWorld;

After saving, you should see the browser show your name.

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.

HelloWorld.jsx
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.

Before we look at our next topic, open up App.jsx so you can see how it’s importing HelloWorld.jsx.

App.jsx
import './App.css';
import HelloWorld from './components/HelloWorld';
function App() {
return (
<HelloWorld />
);
}
export default App;

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.

HelloWorld.jsx
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.

HelloWorld.jsx
const myStyle = {
color: 'red'
}
function HelloWorld() {
return (
<>
<h1 style={myStyle}>Hello John</h1>
<p>Lorem ipsum dolor...</p>
</>
);
}
export default HelloWorld;

You typically add styles using external CSS files. Create a CSS file inside src/components called HelloWorld.css.

HelloWorld.css
h1 {
color: red;
}

Task: Delete the inline style attribute. Create HelloWorld.css and import it into HelloWorld.jsx.

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.

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.

HelloWorld.css
.heading {
color: red;
}
HelloWorld.jsx
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.

HelloWorld.jsx
function HelloWorld({name}) {
return <h1>Hello {name}</h1>;
}
export default HelloWorld;

Then pass in the name prop to the HelloWorld component inside App.jsx.

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.

For this section, we’re going to create a new file called Counter.jsx. Add the following code to it.

Counter.jsx
function Counter() {
return (
<button>Count: 0</button>
);
}
export default Counter;

Next, make sure to import it into App.jsx.

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}.

Counter.jsx
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.

Next, add an onClick handler to the button that increments the count.

Counter.jsx
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.

Create a function called increment(). Then replace the inline function with a reference to increment.

Counter.jsx
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.

Let’s learn how to display elements conditionally.

If you only need an if condition, you can use the && syntax in the return statement.

Counter.jsx
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.

Counter.jsx
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.

Counter.jsx
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.

TodoList.jsx
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.

App.jsx
import TodoList from './components/TodoList';
function App() {
return (
<TodoList />
);
}
export default App;

Next, add a newItem state variable, the handleAdd() function and the <input> element.

TodoList.jsx
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;

Next, add the handleDelete() function and the <button> element.

TodoList.jsx
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;

Next, add the toggleItem() function and the <input> element. Also, add a completed property to each item in the list of items.

TodoList.jsx
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.

TodoList.jsx
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;

For this section, create a new file called HelloWorld.css in the components folder.

HelloWorld.css
.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.

HelloWorld.jsx
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>
</>
);
}