--- id: tutorial title: "Tutorial: Intro to React" layout: tutorial sectionid: tutorial permalink: tutorial/tutorial.html redirect_from: - "docs/tutorial.html" - "docs/why-react.html" - "docs/tutorial-ja-JP.html" - "docs/tutorial-ko-KR.html" - "docs/tutorial-zh-CN.html" --- This tutorial doesn't assume any existing React knowledge. ## Before We Start the Tutorial {#before-we-start-the-tutorial} We will build a small game during this tutorial. **You might be tempted to skip it because you're not building games -- but give it a chance.** The techniques you'll learn in the tutorial are fundamental to building any React app, and mastering it will give you a deep understanding of React. >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-step guide](/docs/hello-world.html). You might find this tutorial and the guide complementary to each other. The tutorial is divided into several sections: * [Setup for the Tutorial](#setup-for-the-tutorial) will give you **a starting point** to follow the tutorial. * [Overview](#overview) will teach you **the fundamentals** of React: components, props, and state. * [Completing the Game](#completing-the-game) will teach you **the most common techniques** in React development. * [Adding Time Travel](#adding-time-travel) will give you **a deeper insight** into the unique strengths of React. You don't have to complete all of the sections at once to get the value out of this tutorial. Try to get as far as you can -- even if it's one or two sections. ### What Are We Building? {#what-are-we-building} 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](https://codepen.io/gaearon/pen/gWWZgR?editors=0010)**. If the code doesn't make sense to you, or if you are unfamiliar with the code's syntax, don't worry! The goal of this tutorial is to help you understand React and its syntax. We recommend that you check out the tic-tac-toe game before continuing with the tutorial. One of the features that you'll notice is that there is a numbered list to the right of the game's board. This list gives you a history of all of the moves that have occurred in the game, and it is updated as the game progresses. You can close the tic-tac-toe game once you're familiar with it. We'll be starting from a simpler template in this tutorial. Our next step is to set you up so that you can start building the game. ### Prerequisites {#prerequisites} We'll assume that you have some familiarity with HTML and JavaScript, but you should be able to follow along even if you're coming from a different programming language. We'll also assume that you're familiar with programming concepts like functions, objects, arrays, and to a lesser extent, classes. If you need to review JavaScript, we recommend reading [this guide](https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript). Note that we're also using some features from ES6 -- a recent version of JavaScript. In this tutorial, we're using [arrow functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions), [classes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes), [`let`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let), and [`const`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const) statements. You can use the [Babel REPL](babel://es5-syntax-example) to check what ES6 code compiles to. ## Setup for the Tutorial {#setup-for-the-tutorial} There are two ways to complete this tutorial: you can either write the code in your browser, or you can set up a local development environment on your computer. ### Setup Option 1: Write Code in the Browser {#setup-option-1-write-code-in-the-browser} This is the quickest way to get started! First, open this **[Starter Code](https://codepen.io/gaearon/pen/oWWQNa?editors=0010)** in a new tab. The new tab should display an empty tic-tac-toe game board and React code. We will be editing the React code in this tutorial. You can now skip the second setup option, and go to the [Overview](#overview) section to get an overview of React. ### Setup Option 2: Local Development Environment {#setup-option-2-local-development-environment} This is completely optional and not required for this tutorial!
Optional: Instructions for following along locally using your preferred text editor This setup requires more work but allows you to complete the tutorial using an editor of your choice. Here are the steps to follow: 1. Make sure you have a recent version of [Node.js](https://nodejs.org/en/) installed. 2. Follow the [installation instructions for Create React App](/docs/create-a-new-react-app.html#create-react-app) to make a new project. ```bash npx create-react-app my-app ``` 3. Delete all files in the `src/` folder of the new project > Note: > >**Don't delete the entire `src` folder, just the original source files inside it.** We'll replace the default source files with examples for this project in the next step. ```bash cd my-app cd src # If you're using a Mac or Linux: rm -f * # Or, if you're on Windows: del * # Then, switch back to the project folder cd .. ``` 4. Add a file named `index.css` in the `src/` folder with [this CSS code](https://codepen.io/gaearon/pen/oWWQNa?editors=0100). 5. Add a file named `index.js` in the `src/` folder with [this JS code](https://codepen.io/gaearon/pen/oWWQNa?editors=0010). 6. Add these three lines to the top of `index.js` in the `src/` folder: ```js import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css'; ``` Now if you run `npm start` in the project folder and open `http://localhost:3000` in the browser, you should see an empty tic-tac-toe field. We recommend following [these instructions](https://babeljs.io/docs/editors/) to configure syntax highlighting for your editor.
### Help, I'm Stuck! {#help-im-stuck} If you get stuck, check out the [community support resources](/community/support.html). In particular, [Reactiflux Chat](https://discord.gg/reactiflux) is a great way to get help quickly. If you don't receive an answer, or if you remain stuck, please file an issue, and we'll help you out. ## Overview {#overview} Now that you're set up, let's get an overview of React! ### What Is React? {#what-is-react} React is a declarative, efficient, and flexible JavaScript library for building user interfaces. It lets you compose complex UIs from small and isolated pieces of code called "components". React has a few different kinds of components, but we'll start with `React.Component` subclasses: ```javascript class ShoppingList extends React.Component { render() { return (

Shopping List for {this.props.name}

); } } // Example usage: ``` We'll get to the funny XML-like tags soon. We use components to tell React what we want to see on the screen. When our data changes, React will efficiently update and re-render our components. Here, ShoppingList is a **React component class**, or **React component type**. A component takes in parameters, called `props` (short for "properties"), and returns a hierarchy of views to display via the `render` method. The `render` method returns a *description* of what you want to see on the screen. React takes the description and displays the result. In particular, `render` returns a **React element**, which is a lightweight description of what to render. Most React developers use a special syntax called "JSX" which makes these structures easier to write. The `
` syntax is transformed at build time to `React.createElement('div')`. The example above is equivalent to: ```javascript return React.createElement('div', {className: 'shopping-list'}, React.createElement('h1', /* ... h1 children ... */), React.createElement('ul', /* ... ul children ... */) ); ``` [See full expanded version.](babel://tutorial-expanded-version) If you're curious, `createElement()` is described in more detail in the [API reference](/docs/react-api.html#createelement), but we won't be using it in this tutorial. Instead, we will keep using JSX. 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. The `ShoppingList` component above only renders built-in DOM components like `
` and `
  • `. But you can compose and render custom React components too. For example, we can now refer to the whole shopping list by writing ``. Each React component is encapsulated and can operate independently; this allows you to build complex UIs from simple components. ### Inspecting the Starter Code {#inspecting-the-starter-code} If you're going to work on the tutorial **in your browser,** open this code in a new tab: **[Starter Code](https://codepen.io/gaearon/pen/oWWQNa?editors=0010)**. If you're going to work on the tutorial **locally,** instead open `src/index.js` in your project folder (you have already touched this file during the [setup](#setup-option-2-local-development-environment)). This Starter Code is the base of what we're building. We've provided the CSS styling so that you only need to focus on learning React and programming the tic-tac-toe game. By inspecting the code, you'll notice that we have three React components: * Square * Board * Game The Square component renders a single ` ); } } ``` Before: ![React Devtools](../images/tutorial/tictac-empty.png) After: You should see a number in each square in the rendered output. ![React Devtools](../images/tutorial/tictac-numbers.png) **[View the full code at this point](https://codepen.io/gaearon/pen/aWWQOG?editors=0010)** Congratulations! You've just "passed a prop" from a parent Board component to a child Square component. Passing props is how information flows in React apps, from parents to children. ### Making an Interactive Component {#making-an-interactive-component} 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()` function to this: ```javascript{4} class Square extends React.Component { render() { return ( ); } } ``` If you click on a Square now, you should see 'click' in your browser's devtools console. >Note > >To save typing and avoid the [confusing behavior of `this`](https://yehudakatz.com/2011/08/11/understanding-javascript-function-invocation-and-this/), we will use the [arrow function syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) for event handlers here and further below: > >```javascript{4} >class Square extends React.Component { > render() { > return ( > > ); > } >} >``` > >Notice how with `onClick={() => console.log('click')}`, we're passing *a function* as the `onClick` prop. React will only call this function after a click. Forgetting `() =>` and writing `onClick={console.log('click')}` is a common mistake, and would fire every time the component re-renders. As a next step, we want the Square component to "remember" that it got clicked, and fill it with an "X" mark. To "remember" things, components use **state**. React components can have state by setting `this.state` in their constructors. `this.state` should be considered as private to a React component that it's defined in. Let's store the current value of the Square in `this.state`, and change it when the Square is clicked. First, we'll add a constructor to the class to initialize the state: ```javascript{2-7} class Square extends React.Component { constructor(props) { super(props); this.state = { value: null, }; } render() { return ( ); } } ``` >Note > >In [JavaScript classes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes), you need to always call `super` when defining the constructor of a subclass. All React component classes that have a `constructor` should start with a `super(props)` call. Now we'll change the Square's `render` method to display the current state's value when clicked: * Replace `this.props.value` with `this.state.value` inside the ` ); } } ``` By calling `this.setState` from an `onClick` handler in the Square's `render` method, we tell React to re-render that Square whenever its ` ); } } ``` When a Square is clicked, the `onClick` function provided by the Board is called. Here's a review of how this is achieved: 1. The `onClick` prop on the built-in DOM ` ); } ``` We have changed `this.props` to `props` both times it appears. **[View the full code at this point](https://codepen.io/gaearon/pen/QvvJOv?editors=0010)** >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). ### Taking Turns {#taking-turns} We now need to fix an obvious defect in our tic-tac-toe game: the "O"s cannot be marked on the board. We'll set the first move to be "X" by default. We can set this default by modifying the initial state in our Board constructor: ```javascript{6} class Board extends React.Component { constructor(props) { super(props); this.state = { squares: Array(9).fill(null), xIsNext: true, }; } ``` Each time a player moves, `xIsNext` (a boolean) will be flipped to determine which player goes next and the game's state will be saved. We'll update the Board's `handleClick` function to flip the value of `xIsNext`: ```javascript{3,6} handleClick(i) { const squares = this.state.squares.slice(); squares[i] = this.state.xIsNext ? 'X' : 'O'; this.setState({ squares: squares, xIsNext: !this.state.xIsNext, }); } ``` With this change, "X"s and "O"s can take turns. Try it! Let's also change the "status" text in Board's `render` so that it displays which player has the next turn: ```javascript{2} render() { const status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O'); return ( // the rest has not changed ``` After applying these changes, you should have this Board component: ```javascript{6,11-16,29} class Board extends React.Component { constructor(props) { super(props); this.state = { squares: Array(9).fill(null), xIsNext: true, }; } handleClick(i) { const squares = this.state.squares.slice(); squares[i] = this.state.xIsNext ? 'X' : 'O'; this.setState({ squares: squares, xIsNext: !this.state.xIsNext, }); } renderSquare(i) { return ( this.handleClick(i)} /> ); } render() { const status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O'); return (
    {status}
    {this.renderSquare(0)} {this.renderSquare(1)} {this.renderSquare(2)}
    {this.renderSquare(3)} {this.renderSquare(4)} {this.renderSquare(5)}
    {this.renderSquare(6)} {this.renderSquare(7)} {this.renderSquare(8)}
    ); } } ``` **[View the full code at this point](https://codepen.io/gaearon/pen/KmmrBy?editors=0010)** ### Declaring a Winner {#declaring-a-winner} Now that we show which player's turn is next, we should also show when the game is won and there are no more turns to make. Copy this helper function and paste it at the end of the file: ```javascript function calculateWinner(squares) { const lines = [ [0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [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]; } } return null; } ``` Given an array of 9 squares, this function will check for a winner and return `'X'`, `'O'`, or `null` as appropriate. We will call `calculateWinner(squares)` in the Board's `render` function to check if a player has won. If a player has won, we can display text such as "Winner: X" or "Winner: O". We'll replace the `status` declaration in Board's `render` function with this code: ```javascript{2-8} render() { const winner = calculateWinner(this.state.squares); let status; if (winner) { status = 'Winner: ' + winner; } else { status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O'); } return ( // the rest has not changed ``` We can now change the Board's `handleClick` function to return early by ignoring a click if someone has won the game or if a Square is already filled: ```javascript{3-5} handleClick(i) { const squares = this.state.squares.slice(); if (calculateWinner(squares) || squares[i]) { return; } squares[i] = this.state.xIsNext ? 'X' : 'O'; this.setState({ squares: squares, xIsNext: !this.state.xIsNext, }); } ``` **[View the full code at this point](https://codepen.io/gaearon/pen/LyyXgK?editors=0010)** Congratulations! You now have a working tic-tac-toe game. And you've just learned the basics of React too. So *you're* probably the real winner here. ## Adding Time Travel {#adding-time-travel} As a final exercise, let's make it possible to "go back in time" to the previous moves in the game. ### Storing a History of Moves {#storing-a-history-of-moves} If we mutated the `squares` array, implementing time travel would be very difficult. However, we used `slice()` to create a new copy of the `squares` array after every move, and [treated it as immutable](#why-immutability-is-important). This will allow us to store every past version of the `squares` array, and navigate between the turns that have already happened. We'll store the past `squares` arrays in another array called `history`. The `history` array represents all board states, from the first to the last move, and has a shape like this: ```javascript history = [ // Before first move { squares: [ null, null, null, null, null, null, null, null, null, ] }, // After first move { squares: [ null, null, null, null, 'X', null, null, null, null, ] }, // After second move { squares: [ null, null, null, null, 'X', null, null, null, 'O', ] }, // ... ] ``` Now we need to decide which component should own the `history` state. ### Lifting State Up, Again {#lifting-state-up-again} We'll want the top-level Game component to display a list of past moves. It will need access to the `history` to do that, so we will place the `history` state in the top-level Game component. Placing the `history` state into the Game component lets us remove the `squares` state from its child Board component. Just like we ["lifted state up"](#lifting-state-up) from the Square component into the Board component, we are now lifting it up from the Board into the top-level Game component. This gives 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: ```javascript{2-10} class Game extends React.Component { constructor(props) { super(props); this.state = { history: [{ squares: Array(9).fill(null), }], xIsNext: true, }; } render() { return (
    {/* status */}
      {/* TODO */}
    ); } } ``` 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: * Delete the `constructor` in Board. * Replace `this.state.squares[i]` with `this.props.squares[i]` in Board's `renderSquare`. * Replace `this.handleClick(i)` with `this.props.onClick(i)` in Board's `renderSquare`. The Board component now looks like this: ```javascript{17,18} class Board extends React.Component { handleClick(i) { const squares = this.state.squares.slice(); if (calculateWinner(squares) || squares[i]) { return; } squares[i] = this.state.xIsNext ? 'X' : 'O'; this.setState({ squares: squares, xIsNext: !this.state.xIsNext, }); } renderSquare(i) { return ( this.props.onClick(i)} /> ); } render() { const winner = calculateWinner(this.state.squares); let status; if (winner) { status = 'Winner: ' + winner; } else { status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O'); } return (
    {status}
    {this.renderSquare(0)} {this.renderSquare(1)} {this.renderSquare(2)}
    {this.renderSquare(3)} {this.renderSquare(4)} {this.renderSquare(5)}
    {this.renderSquare(6)} {this.renderSquare(7)} {this.renderSquare(8)}
    ); } } ``` We'll update the Game component's `render` function to use the most recent history entry to determine and display the game's status: ```javascript{2-11,16-19,22} render() { const history = this.state.history; const current = history[history.length - 1]; const winner = calculateWinner(current.squares); let status; if (winner) { status = 'Winner: ' + winner; } else { status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O'); } return (
    this.handleClick(i)} />
    {status}
      {/* TODO */}
    ); } ``` 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: ```js{1-4} render() { return (
    {this.renderSquare(0)} {this.renderSquare(1)} {this.renderSquare(2)}
    {this.renderSquare(3)} {this.renderSquare(4)} {this.renderSquare(5)}
    {this.renderSquare(6)} {this.renderSquare(7)} {this.renderSquare(8)}
    ); } ``` Finally, we need to move the `handleClick` method from the Board component to the Game component. We also need to modify `handleClick` because the Game component's state is structured differently. Within the Game's `handleClick` method, we concatenate new history entries onto `history`. ```javascript{2-4,10-12} handleClick(i) { const history = this.state.history; const current = history[history.length - 1]; const squares = current.squares.slice(); if (calculateWinner(squares) || squares[i]) { return; } squares[i] = this.state.xIsNext ? 'X' : 'O'; this.setState({ history: history.concat([{ squares: squares, }]), xIsNext: !this.state.xIsNext, }); } ``` >Note > >Unlike the array `push()` method you might be more familiar with, the `concat()` method doesn't mutate the original array, so we prefer it. At this point, the Board component only needs the `renderSquare` and `render` methods. The game's state and the `handleClick` method should be in the Game component. **[View the full code at this point](https://codepen.io/gaearon/pen/EmmOqJ?editors=0010)** ### Showing the Past Moves {#showing-the-past-moves} Since we are recording the tic-tac-toe game's history, we can now display it to the player as a list of past moves. We learned earlier that React elements are first-class JavaScript objects; we can pass them around in our applications. To render multiple items in React, we can use an array of React elements. In JavaScript, arrays have a [`map()` method](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map) that is commonly used for mapping data to other data, for example: ```js const numbers = [1, 2, 3]; const doubled = numbers.map(x => x * 2); // [2, 4, 6] ``` Using the `map` method, we can map our history of moves to React elements representing buttons on the screen, and display a list of buttons to "jump" to past moves. Let's `map` over the `history` in the Game's `render` method: ```javascript{6-15,34} render() { const history = this.state.history; const current = history[history.length - 1]; const winner = calculateWinner(current.squares); const moves = history.map((step, move) => { const desc = move ? 'Go to move #' + move : 'Go to game start'; return (
  • ); }); let status; if (winner) { status = 'Winner: ' + winner; } else { status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O'); } return (
    this.handleClick(i)} />
    {status}
      {moves}
    ); } ``` **[View the full code at this point](https://codepen.io/gaearon/pen/EmmGEa?editors=0010)** As we iterate through `history` array, `step` variable refers to the current `history` element value, and `move` refers to the current `history` element index. We are only interested in `move` here, hence `step` is not getting assigned to anything. For each move in the tic-tac-toe game's history, we create a list item `
  • ` which contains a button `
  • ); }); ``` **[View the full code at this point](https://codepen.io/gaearon/pen/PmmXRE?editors=0010)** Clicking any of the list item's buttons throws an error because the `jumpTo` method is undefined. Before we implement `jumpTo`, we'll add `stepNumber` to the Game component's state to indicate which step we're currently viewing. First, add `stepNumber: 0` to the initial state in Game's `constructor`: ```js{8} class Game extends React.Component { constructor(props) { super(props); this.state = { history: [{ squares: Array(9).fill(null), }], stepNumber: 0, xIsNext: true, }; } ``` Next, we'll define the `jumpTo` method in Game to update that `stepNumber`. We also set `xIsNext` to true if the number that we're changing `stepNumber` to is even: ```javascript{5-10} handleClick(i) { // this method has not changed } jumpTo(step) { this.setState({ stepNumber: step, xIsNext: (step % 2) === 0, }); } render() { // this method has not changed } ``` Notice in `jumpTo` method, we haven't updated `history` property of the state. That is because state updates are merged or in more simple words React will update only the properties mentioned in `setState` method leaving the remaining state as is. For more info **[see the documentation](/docs/state-and-lifecycle.html#state-updates-are-merged)**. We will now make a few changes to the Game's `handleClick` method which fires when you click on a square. The `stepNumber` state we've added reflects the move displayed to the user now. After we make a new move, we need to update `stepNumber` by 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. We will also replace reading `this.state.history` with `this.state.history.slice(0, this.state.stepNumber + 1)`. This ensures that if we "go back in time" and then make a new move from that point, we throw away all the "future" history that would now be incorrect. ```javascript{2,13} handleClick(i) { const history = this.state.history.slice(0, this.state.stepNumber + 1); const current = history[history.length - 1]; const squares = current.squares.slice(); if (calculateWinner(squares) || squares[i]) { return; } squares[i] = this.state.xIsNext ? 'X' : 'O'; this.setState({ history: history.concat([{ squares: squares }]), stepNumber: history.length, xIsNext: !this.state.xIsNext, }); } ``` Finally, we will modify the Game component's `render` method from always rendering the last move to rendering the currently selected move according to `stepNumber`: ```javascript{3} render() { const history = this.state.history; const current = history[this.state.stepNumber]; const winner = calculateWinner(current.squares); // the rest has not changed ``` If we click on any step in the game's history, the tic-tac-toe board should immediately update to show what the board looked like after that step occurred. **[View the full code at this point](https://codepen.io/gaearon/pen/gWWZgR?editors=0010)** ### Wrapping Up {#wrapping-up} Congratulations! You've created a tic-tac-toe game that: * Lets you play tic-tac-toe, * Indicates when a player has won the game, * Stores a game's history as a game progresses, * Allows players to review a game's history and see previous versions of a game's board. Nice work! We hope you now feel like you have a decent grasp of how React works. Check out the final result here: **[Final Result](https://codepen.io/gaearon/pen/gWWZgR?editors=0010)**. 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: 1. Display the location for each move in the format (col, row) in the move history list. 2. Bold the currently selected item in the move list. 3. Rewrite Board to use two loops to make the squares instead of hardcoding them. 4. Add a toggle button that lets you sort the moves in either ascending or descending order. 5. When someone wins, highlight the three squares that caused the win. 6. When no one wins, display a message about the result being a draw. Throughout this tutorial, we touched on React concepts including elements, components, props, and state. For a more detailed explanation of each of these topics, check out [the rest of the documentation](/docs/hello-world.html). To learn more about defining components, check out the [`React.Component` API reference](/docs/react-component.html).