Tutorial - Intro To React - React
Tutorial - Intro To React - React
React Prerequisites
Setup for the Tutorial
Option 1: Write Code in the
Browser
Option 2: Local Development
Environment
These docs are old and won’t be updated. Go to react.dev for the Help, I'm Stuck!
Tip
This tutorial is designed for people who prefer to learn by doing. If you
prefer learning concepts from the ground up, check out our step-by- Before We Start the Tutorial
step guide. You might find this tutorial and the guide complementary to What Are We Building?
each other. Prerequisites
Setup for the Tutorial
Option 1: Write Code in the
Browser
The tutorial is divided into several sections:
Option 2: Local Development
Environment
Setup for the Tutorial will give you a starting point to follow the tutorial. Help, I'm Stuck!
Overview will teach you the fundamentals of React: components, props, Overview
and state. What Is React?
Inspecting the Starter Code
Completing the Game will teach you the most common techniques in
Passing Data Through Props
React development.
Making an Interactive
Adding Time Travel will give you a deeper insight into the unique strengths Component
of React. Developer Tools
Completing the Game
You don’t have to complete all of the sections at once to get the value out Lifting State Up
Why Immutability Is
of this tutorial. Try to get as far as you can — even if it’s one or two Important
sections. Function Components
Taking Turns
g
Declaring a Winner
Adding Time Travel
In this tutorial, we’ll show how to build an interactive tic-tac-toe game with
React.
You can see what we’ll be building here: Final Result. If the code doesn’t Before We Start the Tutorial
What Are We Building?
make sense to you, or if you are unfamiliar with the code’s syntax, don’t
Prerequisites
worry! The goal of this tutorial is to help you understand React and its
Setup for the Tutorial
syntax.
Option 1: Write Code in the
Browser
We recommend that you check out the tic-tac-toe game before continuing Option 2: Local Development
Environment
with the tutorial. One of the features that you’ll notice is that there is a Help, I'm Stuck!
numbered list to the right of the game’s board. This list gives you a history Overview
of all of the moves that have occurred in the game, and it is updated as the What Is React?
game progresses. Inspecting the Starter Code
Passing Data Through Props
Making an Interactive
You can close the tic-tac-toe game once you’re familiar with it. We’ll be Component
starting from a simpler template in this tutorial. Our next step is to set you Developer Tools
up so that you can start building the game. Completing the Game
Lifting State Up
Why Immutability Is
Prerequisites Important
Function Components
Taking Turns
g
We’ll assume that you have some familiarity with HTML and JavaScript, but Declaring a Winner
you should be able to follow along even if you’re coming from a different Adding Time Travel
programming language. We’ll also assume that you’re familiar with
programming concepts like functions, objects, arrays, and to a lesser
extent, classes.
You can now skip the second setup option, and go to the Overview section
to get an overview of React.
What Is React?
JSX comes with the full power of JavaScript. You can put any JavaScript
expressions within braces inside JSX. Each React element is a JavaScript
object that you can store in a variable or pass around in your program.
Board
Game
The Square component renders a single <button> and the Board renders
9 squares. The Game component renders a board with placeholder values
Before We Start the Tutorial
which we’ll modify later. There are currently no interactive components. What Are We Building?
Prerequisites
Setup for the Tutorial
Passing Data Through Props
Option 1: Write Code in the
Browser
To get our feet wet, let’s try passing some data from our Board component
Option 2: Local Development
to our Square component. Environment
Help, I'm Stuck!
Let’s fill the Square component with an “X” when we click it. First, change
the button tag that is returned from the Square component’s render()
Before We Start the Tutorial
function to this: What Are We Building?
Prerequisites
Put the className and onClick props on separate lines for better
readability.
After these changes, the <button> tag that is returned by the Square’s Before We Start the Tutorial
render method looks like this: What Are We Building?
Prerequisites
We now have the basic building blocks for our tic-tac-toe game. To have a
complete game, we now need to alternate placing “X”s and “O”s on the
Before We Start the Tutorial
board, and we need a way to determine a winner.
What Are We Building?
Prerequisites
component can tell each Square what to display by passing a prop, just like Completing the Game
we did when we passed a number to each Square. Lifting State Up
Why Immutability Is
Important
Function Components
Taking Turns
g
To collect data from multiple children, or to have two child Declaring a Winner
components communicate with each other, you need to declare the Adding Time Travel
shared state in their parent component instead. The parent
component can pass the state back down to the children by using
props; this keeps the child components in sync with each other and
with the parent component.
Each Square will now receive a value prop that will either be 'X' , 'O' , or
null for empty squares. Before We Start the Tutorial
What Are We Building?
Next, we need to change what happens when a Square is clicked. The Prerequisites
Board component now maintains which squares are filled. We need to Setup for the Tutorial
create a way for the Square to update the Board’s state. Since state is Option 1: Write Code in the
Browser
considered to be private to a component that defines it, we cannot update Option 2: Local Development
the Board’s state directly from Square. Environment
Help, I'm Stuck!
Overview
Instead, we’ll pass down a function from the Board to the Square, and we’ll
What Is React?
have Square call that function when a square is clicked. We’ll change the
Inspecting the Starter Code
renderSquare method in Board to: Passing Data Through Props
Making an Interactive
Component
renderSquare(i) {
Developer Tools
return (
<Square Completing the Game
value={this.state.squares[i]} Lifting State Up
onClick={() => this.handleClick(i)}
Why Immutability Is
/> Important
);
Function Components
}
Taking Turns
g
Declaring a Winner
Note
Adding Time Travel
We split the returned element into multiple lines for readability, and
added parentheses so that JavaScript doesn’t insert a semicolon after
return and break our code.
Now we’re passing down two props from Board to Square: value and
onClick . The onClick prop is a function that Square can call when Before We Start the Tutorial
clicked. We’ll make the following changes to Square: What Are We Building?
Prerequisites
Replace this.state.value with this.props.value in Square’s render Setup for the Tutorial
method Option 1: Write Code in the
Browser
Replace this.setState() with this.props.onClick() in Square’s render
Option 2: Local Development
method Environment
Help, I'm Stuck!
Delete the constructor from Square because Square no longer keeps track
of the game’s state Overview
What Is React?
Inspecting the Starter Code
After these changes, the Square component looks like this: Passing Data Through Props
Making an Interactive
Component
class Square extends React.Component {
Developer Tools
render() {
return ( Completing the Game
<button Lifting State Up
className="square"
Why Immutability Is
onClick={() => this.props.onClick()} Important
>
Function Components
{this.props.value}
Taking Turns
g
</button>
Declaring a Winner
);
} Adding Time Travel
}
1. The onClick prop on the built-in DOM <button> component tells React to
Before We Start the Tutorial
set up a click event listener.
What Are We Building?
2. When the button is clicked, React will call the onClick event handler that is Prerequisites
defined in Square’s render() method. Setup for the Tutorial
Option 1: Write Code in the
3. This event handler calls this.props.onClick() . The Square’s onClick
Browser
prop was specified by the Board. Option 2: Local Development
Environment
4. Since the Board passed onClick={() => this.handleClick(i)} to Square,
Help, I'm Stuck!
the Square calls the Board’s handleClick(i) when clicked.
Overview
5. We have not defined the handleClick() method yet, so our code crashes. If What Is React?
you click a square now, you should see a red error screen saying something Inspecting the Starter Code
like “this.handleClick is not a function”. Passing Data Through Props
Making an Interactive
Component
Note Developer Tools
The DOM <button> element’s onClick attribute has a special meaning Completing the Game
to React because it is a built-in component. For custom components like Lifting State Up
Square, the naming is up to you. We could give any name to the Why Immutability Is
Important
Square’s onClick prop or Board’s handleClick method, and the code Function Components
Taking Turns
g
would work the same. In React, it’s conventional to use on[Event] Declaring a Winner
names for props which represent events and handle[Event] for the Adding Time Travel
methods which handle the events.
In the previous code example, we suggested that you create a copy of the Overview
What Is React?
squares array using the slice() method instead of modifying the
Inspecting the Starter Code
existing array. We’ll now discuss immutability and why immutability is
Passing Data Through Props
important to learn. Making an Interactive
Component
Developer Tools
There are generally two approaches to changing data. The first approach is
Completing the Game
to mutate the data by directly changing the data’s values. The second
Lifting State Up
approach is to replace the data with a new copy which has the desired
Why Immutability Is
changes. Important
Function Components
Taking Turns
g
Declaring a Winner
Adding Time Travel
Detecting changes in mutable objects is difficult because they are modified Setup for the Tutorial
Option 1: Write Code in the
directly. This detection requires the mutable object to be compared to
Browser
previous copies of itself and the entire object tree to be traversed. Option 2: Local Development
Environment
Help, I'm Stuck!
Detecting changes in immutable objects is considerably easier. If the
Overview
immutable object that is being referenced is different than the previous
What Is React?
one, then the object has changed.
Inspecting the Starter Code
Passing Data Through Props
Making an Interactive
Determining When to Re-Render in React Component
Developer Tools
The main benefit of immutability is that it helps you build pure components Completing the Game
in React. Immutable data can easily determine if changes have been made, Lifting State Up
which helps to determine when a component requires re-rendering. Why Immutability Is
Important
Function Components
Taking Turns
g
You can learn more about shouldComponentUpdate() and how you can Declaring a Winner
build pure components by reading Optimizing Performance. Adding Time Travel
Function Components
Note
When we modified the Square to be a function component, we also
changed onClick={() => this.props.onClick()} to a shorter
onClick={props.onClick} (note the lack of parentheses on both
sides).
Before We Start the Tutorial
What Are We Building?
Prerequisites
Setup for the Tutorial
Taking Turns
Option 1: Write Code in the
Browser
We now need to fix an obvious defect in our tic-tac-toe game: the “O”s Option 2: Local Development
cannot be marked on the board. Environment
Help, I'm Stuck!
We’ll set the first move to be “X” by default. We can set this default by Overview
What Is React?
modifying the initial state in our Board constructor:
Inspecting the Starter Code
Passing Data Through Props
class Board extends React.Component { Making an Interactive
constructor(props) { Component
super(props); Developer Tools
this.state = {
Completing the Game
squares: Array(9).fill(null),
xIsNext: true, Lifting State Up
}; Why Immutability Is
} Important
Function Components
Taking Turns
g
Each time a player moves, xIsNext (a boolean) will be flipped to Declaring a Winner
determine which player goes next and the game’s state will be saved. We’ll Adding Time Travel
update the Board’s handleClick function to flip the value of xIsNext :
handleClick(i) {
const squares = this.state.squares.slice();
squares[i] = this.state.xIsNext ? 'X' : 'O';
this.setState({
squares: squares,
xIsNext: !this.state.xIsNext, Before We Start the Tutorial
}); What Are We Building?
} Prerequisites
Setup for the Tutorial
Option 1: Write Code in the
With this change, “X”s and “O”s can take turns. Try it! Browser
Option 2: Local Development
Environment
Let’s also change the “status” text in Board’s render so that it displays
Help, I'm Stuck!
which player has the next turn:
Overview
What Is React?
render() { Inspecting the Starter Code
const status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O'); Passing Data Through Props
Making an Interactive
return ( Component
// the rest has not changed
Developer Tools
Completing the Game
Lifting State Up
After applying these changes, you should have this Board component:
Why Immutability Is
Important
Function Components
Taking Turns
g
class Board extends React.Component { Declaring a Winner
constructor(props) { Adding Time Travel
super(props);
this.state = {
squares: Array(9).fill(null),
xIsNext: true,
};
}
handleClick(i) {
const squares = this.state.squares.slice();
Before We Start the Tutorial
squares[i] = this.state.xIsNext ? 'X' : 'O';
What Are We Building?
this.setState({
Prerequisites
squares: squares,
xIsNext: !this.state.xIsNext, Setup for the Tutorial
}); Option 1: Write Code in the
} Browser
Option 2: Local Development
renderSquare(i) { Environment
return ( Help, I'm Stuck!
<Square
value={this.state.squares[i]} Overview
onClick={() => this.handleClick(i)} What Is React?
/> Inspecting the Starter Code
);
Passing Data Through Props
}
Making an Interactive
Component
render() {
const status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O'); Developer Tools
Completing the Game
return (
Lifting State Up
<div>
<div className="status">{status}</div> Why Immutability Is
Important
<div className="board-row">
{this.renderSquare(0)} Function Components
Taking Turns
g
{this.renderSquare(1)}
Declaring a Winner
{this.renderSquare(2)}
</div> Adding Time Travel
<div className="board-row">
{this.renderSquare(3)}
{this.renderSquare(4)}
{this.renderSquare(5)}
</div>
<div className="board-row">
{this.renderSquare(6)}
{this.renderSquare(7)}
{this.renderSquare(8)} Before We Start the Tutorial
</div>
What Are We Building?
</div>
);
Prerequisites
} Setup for the Tutorial
} Option 1: Write Code in the
Browser
Option 2: Local Development
View the full code at this point Environment
Help, I'm Stuck!
Overview
Declaring a Winner What Is React?
Inspecting the Starter Code
Now that we show which player’s turn is next, we should also show when Passing Data Through Props
the game is won and there are no more turns to make. Copy this helper Making an Interactive
Component
function and paste it at the end of the file:
Developer Tools
Completing the Game
function calculateWinner(squares) { Lifting State Up
const lines = [ Why Immutability Is
[0, 1, 2], Important
[3, 4, 5],
Function Components
[6, 7, 8],
Taking Turns
g
[0, 3, 6],
Declaring a Winner
[1, 4, 7],
[2, 5, 8], Adding Time Travel
[0, 4, 8],
[2, 4, 6],
];
for (let i = 0; i < lines.length; i++) {
const [a, b, c] = lines[i];
if (squares[a] && squares[a] === squares[b] && squares[a] ===
squares[c]) {
return squares[a];
} Before We Start the Tutorial
}
What Are We Building?
return null;
}
Prerequisites
Setup for the Tutorial
Option 1: Write Code in the
Browser
Given an array of 9 squares, this function will check for a winner and return
Option 2: Local Development
'X' , 'O' , or null as appropriate. Environment
Help, I'm Stuck!
We will call calculateWinner(squares) in the Board’s render function to Overview
check if a player has won. If a player has won, we can display text such as What Is React?
Inspecting the Starter Code
“Winner: X” or “Winner: O”. We’ll replace the status declaration in Board’s
Passing Data Through Props
render function with this code:
Making an Interactive
Component
Developer Tools
render() {
const winner = calculateWinner(this.state.squares); Completing the Game
let status; Lifting State Up
if (winner) { Why Immutability Is
status = 'Winner: ' + winner; Important
} else { Function Components
Taking Turns
g
status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
Declaring a Winner
}
Adding Time Travel
return (
// the rest has not changed
handleClick(i) {
Prerequisites
const squares = this.state.squares.slice(); Setup for the Tutorial
if (calculateWinner(squares) || squares[i]) { Option 1: Write Code in the
return; Browser
} Option 2: Local Development
squares[i] = this.state.xIsNext ? 'X' : 'O'; Environment
this.setState({
Help, I'm Stuck!
squares: squares,
xIsNext: !this.state.xIsNext, Overview
}); What Is React?
} Inspecting the Starter Code
Passing Data Through Props
Making an Interactive
View the full code at this point Component
Developer Tools
Congratulations! You now have a working tic-tac-toe game. And you’ve Completing the Game
Lifting State Up
just learned the basics of React too. So you’re probably the real winner
Why Immutability Is
here. Important
Function Components
Taking Turns
g
Adding Time Travel Declaring a Winner
Adding Time Travel
As a final exercise, let’s make it possible to “go back in time” to the
previous moves in the game.
We’ll store the past squares arrays in another array called history . The Overview
What Is React?
history array represents all board states, from the first to the last move,
Inspecting the Starter Code
and has a shape like this: Passing Data Through Props
Making an Interactive
Component
history = [
// Before first move
Developer Tools
{ Completing the Game
squares: [ Lifting State Up
null, null, null,
Why Immutability Is
null, null, null,
Important
null, null, null,
] Function Components
Taking Turns
g
},
Declaring a Winner
// After first move
{ Adding Time Travel
squares: [
null, null, null,
null, 'X', null,
null, null, null,
]
},
// After second move
{
squares: [ Before We Start the Tutorial
null, null, null,
What Are We Building?
null, 'X', null,
null, null, 'O',
Prerequisites
] Setup for the Tutorial
}, Option 1: Write Code in the
// ... Browser
]
Option 2: Local Development
Environment
Help, I'm Stuck!
Now we need to decide which component should own the history state. Overview
What Is React?
Inspecting the Starter Code
Lifting State Up, Again Passing Data Through Props
Making an Interactive
We’ll want the top-level Game component to display a list of past moves. It Component
will need access to the history to do that, so we will place the history Developer Tools
state in the top-level Game component. Completing the Game
Lifting State Up
Why Immutability Is
Placing the history state into the Game component lets us remove the Important
squares state from its child Board component. Just like we “lifted state Function Components
Taking Turns
g
up” from the Square component into the Board component, we are now Declaring a Winner
lifting it up from the Board into the top-level Game component. This gives Adding Time Travel
the Game component full control over the Board’s data, and lets it instruct
the Board to render previous turns from the history .
First, we’ll set up the initial state for the Game component within its
constructor:
Next, we’ll have the Board component receive squares and onClick
props from the Game component. Since we now have a single click handler
in Board for many Squares, we’ll need to pass the location of each Square
into the onClick handler to indicate which Square was clicked. Here are
the required steps to transform the Board component:
Before We Start the Tutorial
What Are We Building?
Delete the constructor in Board.
Prerequisites
Replace this.state.squares[i] with this.props.squares[i] in Board’s
Setup for the Tutorial
renderSquare . Option 1: Write Code in the
Browser
Replace this.handleClick(i) with this.props.onClick(i) in Board’s
Option 2: Local Development
renderSquare . Environment
Help, I'm Stuck!
The Board component now looks like this: Overview
What Is React?
Inspecting the Starter Code
class Board extends React.Component {
Passing Data Through Props
handleClick(i) {
const squares = this.state.squares.slice();
Making an Interactive
Component
if (calculateWinner(squares) || squares[i]) {
return; Developer Tools
} Completing the Game
squares[i] = this.state.xIsNext ? 'X' : 'O';
Lifting State Up
this.setState({
squares: squares, Why Immutability Is
Important
xIsNext: !this.state.xIsNext,
}); Function Components
Taking Turns
g
}
Declaring a Winner
renderSquare(i) { Adding Time Travel
return (
<Square
value={this.props.squares[i]}
onClick={() => this.props.onClick(i)}
/>
);
}
We’ll update the Game component’s render function to use the most
recent history entry to determine and display the game’s status:
Before We Start the Tutorial
What Are We Building?
render() {
Prerequisites
const history = this.state.history;
const current = history[history.length - 1]; Setup for the Tutorial
const winner = calculateWinner(current.squares); Option 1: Write Code in the
Browser
let status;
if (winner) { Option 2: Local Development
Environment
status = 'Winner: ' + winner;
} else {
Help, I'm Stuck!
status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O'); Overview
} What Is React?
Inspecting the Starter Code
return (
Passing Data Through Props
<div className="game">
<div className="game-board"> Making an Interactive
<Board Component
squares={current.squares} Developer Tools
onClick={(i) => this.handleClick(i)} Completing the Game
/>
Lifting State Up
</div>
<div className="game-info">
Why Immutability Is
Important
<div>{status}</div>
<ol>{/* TODO */}</ol> Function Components
Taking Turns
g
</div>
Declaring a Winner
</div>
); Adding Time Travel
}
Since the Game component is now rendering the game’s status, we can
remove the corresponding code from the Board’s render method. After
refactoring, the Board’s render function looks like this:
Before We Start the Tutorial
render() { What Are We Building?
return ( Prerequisites
<div> Setup for the Tutorial
<div className="board-row"> Option 1: Write Code in the
{this.renderSquare(0)} Browser
{this.renderSquare(1)}
Option 2: Local Development
{this.renderSquare(2)}
Environment
</div>
Help, I'm Stuck!
<div className="board-row">
{this.renderSquare(3)} Overview
{this.renderSquare(4)} What Is React?
{this.renderSquare(5)}
Inspecting the Starter Code
</div>
<div className="board-row"> Passing Data Through Props
{this.renderSquare(6)} Making an Interactive
{this.renderSquare(7)} Component
{this.renderSquare(8)} Developer Tools
</div>
Completing the Game
</div>
); Lifting State Up
} Why Immutability Is
Important
Function Components
Taking Turns
g
Finally, we need to move the handleClick method from the Board Declaring a Winner
component to the Game component. We also need to modify Adding Time Travel
handleClick because the Game component’s state is structured
differently. Within the Game’s handleClick method, we concatenate new
history entries onto history .
handleClick(i) {
const history = this.state.history;
const current = history[history.length - 1]; Before We Start the Tutorial
const squares = current.squares.slice(); What Are We Building?
if (calculateWinner(squares) || squares[i]) { Prerequisites
return;
Setup for the Tutorial
}
squares[i] = this.state.xIsNext ? 'X' : 'O'; Option 1: Write Code in the
this.setState({ Browser
history: history.concat([{ Option 2: Local Development
squares: squares, Environment
}]), Help, I'm Stuck!
xIsNext: !this.state.xIsNext, Overview
});
What Is React?
}
Inspecting the Starter Code
Passing Data Through Props
Making an Interactive
Component
Note Developer Tools
Unlike the array push() method you might be more familiar with, the Completing the Game
concat() method doesn’t mutate the original array, so we prefer it. Lifting State Up
Why Immutability Is
Important
Function Components
Taking Turns
g
At this point, the Board component only needs the renderSquare and Declaring a Winner
render methods. The game’s state and the handleClick method should Adding Time Travel
be in the Game component.
In JavaScript, arrays have a map() method that is commonly used for Overview
What Is React?
mapping data to other data, for example:
Inspecting the Starter Code
Passing Data Through Props
const numbers = [1, 2, 3]; Making an Interactive
const doubled = numbers.map(x => x * 2); // [2, 4, 6] Component
Developer Tools
Completing the Game
Using the map method, we can map our history of moves to React Lifting State Up
elements representing buttons on the screen, and display a list of buttons Why Immutability Is
Important
to “jump” to past moves.
Function Components
Taking Turns
g
Let’s map over the history in the Game’s render method: Declaring a Winner
Adding Time Travel
render() {
const history = this.state.history;
const current = history[history.length - 1];
const winner = calculateWinner(current.squares);
Picking a Key
When we render a list, React stores some information about each rendered
list item. When we update a list, React needs to determine what has
changed. We could have added, removed, re-arranged, or updated the
list’s items. Before We Start the Tutorial
What Are We Building?
Prerequisites
Imagine transitioning from
Setup for the Tutorial
Option 1: Write Code in the
<li>Alexa: 7 tasks left</li> Browser
<li>Ben: 5 tasks left</li> Option 2: Local Development
Environment
Help, I'm Stuck!
to Overview
What Is React?
Inspecting the Starter Code
<li>Ben: 9 tasks left</li>
Passing Data Through Props
<li>Claudia: 8 tasks left</li>
<li>Alexa: 5 tasks left</li>
Making an Interactive
Component
Developer Tools
Completing the Game
In addition to the updated counts, a human reading this would probably
Lifting State Up
say that we swapped Alexa and Ben’s ordering and inserted Claudia
Why Immutability Is
between Alexa and Ben. However, React is a computer program and does Important
not know what we intended. Because React cannot know our intentions, Function Components
Taking Turns
g
we need to specify a key property for each list item to differentiate each Declaring a Winner
list item from its siblings. One option would be to use the strings alexa , Adding Time Travel
ben , claudia . If we were displaying data from a database, Alexa, Ben, and
Claudia’s database IDs could be used as keys.
When a list is re-rendered, React takes each list item’s key and searches the Before We Start the Tutorial
What Are We Building?
previous list’s items for a matching key. If the current list has a key that
Prerequisites
didn’t exist before, React creates a component. If the current list is missing
Setup for the Tutorial
a key that existed in the previous list, React destroys the previous
Option 1: Write Code in the
component. If two keys match, the corresponding component is moved. Browser
Keys tell React about the identity of each component which allows React to Option 2: Local Development
Environment
maintain state between re-renders. If a component’s key changes, the Help, I'm Stuck!
component will be destroyed and re-created with a new state.
Overview
What Is React?
key is a special and reserved property in React (along with ref , a more Inspecting the Starter Code
advanced feature). When an element is created, React extracts the key Passing Data Through Props
Making an Interactive
property and stores the key directly on the returned element. Even though Component
key may look like it belongs in props , key cannot be referenced using Developer Tools
this.props.key . React automatically uses key to decide which Completing the Game
components to update. A component cannot inquire about its key . Lifting State Up
Why Immutability Is
Important
Function Components
Taking Turns
g
It’s strongly recommended that you assign proper keys whenever you Declaring a Winner
build dynamic lists. If you don’t have an appropriate key, you may want Adding Time Travel
to consider restructuring your data so that you do.
If no key is specified, React will present a warning and use the array index
as a key by default. Using the array index as a key is problematic when
trying to re-order a list’s items or inserting/removing list items. Explicitly
passing key={i} silences the warning but has the same problems as array
Before We Start the Tutorial
indices and is not recommended in most cases. What Are We Building?
Prerequisites
Keys do not need to be globally unique; they only need to be unique Setup for the Tutorial
between components and their siblings. Option 1: Write Code in the
Browser
Option 2: Local Development
Environment
Implementing Time Travel
Help, I'm Stuck!
In the tic-tac-toe game’s history, each past move has a unique ID Overview
What Is React?
associated with it: it’s the sequential number of the move. The moves are
Inspecting the Starter Code
never re-ordered, deleted, or inserted in the middle, so it’s safe to use the
Passing Data Through Props
move index as a key. Making an Interactive
Component
Developer Tools
In the Game component’s render method, we can add the key as <li
Completing the Game
key={move}> and React’s warning about keys should disappear:
Lifting State Up
Why Immutability Is
const moves = history.map((step, move) => { Important
const desc = move ? Function Components
Taking Turns
g
'Go to move #' + move :
Declaring a Winner
'Go to game start';
return ( Adding Time Travel
<li key={move}>
<button onClick={() => this.jumpTo(move)}>{desc}</button>
</li>
);
});
handleClick(i) {
// this method has not changed
}
jumpTo(step) {
this.setState({
Before We Start the Tutorial
stepNumber: step, What Are We Building?
xIsNext: (step % 2) === 0, Prerequisites
}); Setup for the Tutorial
}
Option 1: Write Code in the
Browser
render() {
Option 2: Local Development
// this method has not changed
Environment
}
Help, I'm Stuck!
Overview
Notice in jumpTo method, we haven’t updated history property of the What Is React?
Inspecting the Starter Code
state. That is because state updates are merged or in more simple words
Passing Data Through Props
React will update only the properties mentioned in setState method Making an Interactive
leaving the remaining state as is. For more info see the documentation. Component
Developer Tools
We will now make a few changes to the Game’s handleClick method Completing the Game
Lifting State Up
which fires when you click on a square.
Why Immutability Is
Important
Function Components
Taking Turns
g
The stepNumber state we’ve added reflects the move displayed to the user Declaring a Winner
now. After we make a new move, we need to update stepNumber by Adding Time Travel
adding stepNumber: history.length as part of the this.setState
argument. This ensures we don’t get stuck showing the same move after a
new one has been made.
render() {
const history = this.state.history;
const current = history[this.state.stepNumber];
const winner = calculateWinner(current.squares);
If you have extra time or want to practice your new React skills, here are
some ideas for improvements that you could make to the tic-tac-toe game
which are listed in order of increasing difficulty:
Before We Start the Tutorial
What Are We Building?
1. Display the location for each move in the format (col, row) in the move
Prerequisites
history list.
Setup for the Tutorial
2. Bold the currently selected item in the move list.
Option 1: Write Code in the
Browser
3. Rewrite Board to use two loops to make the squares instead of hardcoding
Option 2: Local Development
them.
Environment
4. Add a toggle button that lets you sort the moves in either ascending or Help, I'm Stuck!
descending order. Overview
5. When someone wins, highlight the three squares that caused the win. What Is React?
Inspecting the Starter Code
6. When no one wins, display a message about the result being a draw. Passing Data Through Props
Making an Interactive
Component
Throughout this tutorial, we touched on React concepts including
Developer Tools
elements, components, props, and state. For a more detailed explanation
Completing the Game
of each of these topics, check out the rest of the documentation. To learn
Lifting State Up
more about defining components, check out the React.Component API Why Immutability Is
reference. Important
Function Components
Taking Turns
g
Is this page useful? Edit this page Declaring a Winner
Adding Time Travel