Browse Source

Make CodePen links more prominent and consistent

main
Dan 7 years ago
parent
commit
db66436112
  1. 8
      content/docs/components-and-props.md
  2. 8
      content/docs/composition-vs-inheritance.md
  3. 8
      content/docs/conditional-rendering.md
  4. 6
      content/docs/forms.md
  5. 2
      content/docs/handling-events.md
  6. 14
      content/docs/integrating-with-other-libraries.md
  7. 2
      content/docs/introducing-jsx.md
  8. 6
      content/docs/lifting-state-up.md
  9. 10
      content/docs/lists-and-keys.md
  10. 4
      content/docs/portals.md
  11. 14
      content/docs/state-and-lifecycle.md
  12. 4
      content/docs/uncontrolled-components.md
  13. 36
      content/tutorial/tutorial.md
  14. 2
      gatsby-config.js

8
content/docs/components-and-props.md

@ -76,7 +76,7 @@ ReactDOM.render(
);
```
[](codepen://components-and-props/rendering-a-component).
[](codepen://components-and-props/rendering-a-component)
Let's recap what happens in this example:
@ -118,7 +118,7 @@ ReactDOM.render(
);
```
[](codepen://components-and-props/composing-components).
[](codepen://components-and-props/composing-components)
Typically, new React apps have a single `App` component at the very top. However, if you integrate React into an existing app, you might start bottom-up with a small component like `Button` and gradually work your way to the top of the view hierarchy.
@ -152,7 +152,7 @@ function Comment(props) {
}
```
[](codepen://components-and-props/extracting-components).
[](codepen://components-and-props/extracting-components)
It accepts `author` (an object), `text` (a string), and `date` (a date) as props, and describes a comment on a social media website.
@ -231,7 +231,7 @@ function Comment(props) {
}
```
[](codepen://components-and-props/extracting-components-continued).
[](codepen://components-and-props/extracting-components-continued)
Extracting components might seem like grunt work at first, but having a palette of reusable components pays off in larger apps. A good rule of thumb is that if a part of your UI is used several times (`Button`, `Panel`, `Avatar`), or is complex enough on its own (`App`, `FeedStory`, `Comment`), it is a good candidate to be a reusable component.

8
content/docs/composition-vs-inheritance.md

@ -44,7 +44,7 @@ function WelcomeDialog() {
}
```
[Try it on CodePen.](https://codepen.io/gaearon/pen/ozqNOV?editors=0010)
**[Try it on CodePen](https://codepen.io/gaearon/pen/ozqNOV?editors=0010)**
Anything inside the `<FancyBorder>` JSX tag gets passed into the `FancyBorder` component as a `children` prop. Since `FancyBorder` renders `{props.children}` inside a `<div>`, the passed elements appear in the final output.
@ -77,7 +77,7 @@ function App() {
}
```
[Try it on CodePen.](https://codepen.io/gaearon/pen/gwZOJp?editors=0010)
[**Try it on CodePen**](https://codepen.io/gaearon/pen/gwZOJp?editors=0010)
React elements like `<Contacts />` and `<Chat />` are just objects, so you can pass them as props like any other data. This approach may remind you of "slots" in other libraries but there are no limitations on what you can pass as props in React.
@ -110,7 +110,7 @@ function WelcomeDialog() {
}
```
[Try it on CodePen.](https://codepen.io/gaearon/pen/kkEaOZ?editors=0010)
[**Try it on CodePen**](https://codepen.io/gaearon/pen/kkEaOZ?editors=0010)
Composition works equally well for components defined as classes:
@ -160,7 +160,7 @@ class SignUpDialog extends React.Component {
}
```
[Try it on CodePen.](https://codepen.io/gaearon/pen/gwZbYa?editors=0010)
[**Try it on CodePen**](https://codepen.io/gaearon/pen/gwZbYa?editors=0010)
## So What About Inheritance?

8
content/docs/conditional-rendering.md

@ -41,7 +41,7 @@ ReactDOM.render(
);
```
[Try it on CodePen.](https://codepen.io/gaearon/pen/ZpVxNq?editors=0011)
[**Try it on CodePen**](https://codepen.io/gaearon/pen/ZpVxNq?editors=0011)
This example renders a different greeting depending on the value of `isLoggedIn` prop.
@ -115,7 +115,7 @@ ReactDOM.render(
);
```
[Try it on CodePen.](https://codepen.io/gaearon/pen/QKzAgB?editors=0010)
[**Try it on CodePen**](https://codepen.io/gaearon/pen/QKzAgB?editors=0010)
While declaring a variable and using an `if` statement is a fine way to conditionally render a component, sometimes you might want to use a shorter syntax. There are a few ways to inline conditions in JSX, explained below.
@ -145,7 +145,7 @@ ReactDOM.render(
);
```
[Try it on CodePen.](https://codepen.io/gaearon/pen/ozJddz?editors=0010)
[**Try it on CodePen**](https://codepen.io/gaearon/pen/ozJddz?editors=0010)
It works because in JavaScript, `true && expression` always evaluates to `expression`, and `false && expression` always evaluates to `false`.
@ -237,6 +237,6 @@ ReactDOM.render(
);
```
[Try it on CodePen.](https://codepen.io/gaearon/pen/Xjoqwm?editors=0010)
[**Try it on CodePen**](https://codepen.io/gaearon/pen/Xjoqwm?editors=0010)
Returning `null` from a component's `render` method does not affect the firing of the component's lifecycle methods. For instance `componentDidUpdate` will still be called.

6
content/docs/forms.md

@ -64,7 +64,7 @@ class NameForm extends React.Component {
}
```
[Try it on CodePen.](https://codepen.io/gaearon/pen/VmmPgp?editors=0010)
[**Try it on CodePen**](https://codepen.io/gaearon/pen/VmmPgp?editors=0010)
Since the `value` attribute is set on our form element, the displayed value will always be `this.state.value`, making the React state the source of truth. Since `handleChange` runs on every keystroke to update the React state, the displayed value will update as the user types.
@ -178,7 +178,7 @@ class FlavorForm extends React.Component {
}
```
[Try it on CodePen.](https://codepen.io/gaearon/pen/JbbEzX?editors=0010)
[**Try it on CodePen**](https://codepen.io/gaearon/pen/JbbEzX?editors=0010)
Overall, this makes it so that `<input type="text">`, `<textarea>`, and `<select>` all work very similarly - they all accept a `value` attribute that you can use to implement a controlled component.
@ -254,7 +254,7 @@ class Reservation extends React.Component {
}
```
[Try it on CodePen.](https://codepen.io/gaearon/pen/wgedvV?editors=0010)
[**Try it on CodePen**](https://codepen.io/gaearon/pen/wgedvV?editors=0010)
Note how we used the ES6 [computed property name](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Object_initializer#Computed_property_names) syntax to update the state key corresponding to the given input name:

2
content/docs/handling-events.md

@ -91,7 +91,7 @@ ReactDOM.render(
);
```
[Try it on CodePen.](http://codepen.io/gaearon/pen/xEmzGg?editors=0010)
[**Try it on CodePen**](http://codepen.io/gaearon/pen/xEmzGg?editors=0010)
You have to be careful about the meaning of `this` in JSX callbacks. In JavaScript, class methods are not [bound](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind) by default. If you forget to bind `this.handleClick` and pass it to `onClick`, `this` will be `undefined` when the function is actually called.

14
content/docs/integrating-with-other-libraries.md

@ -100,7 +100,7 @@ componentWillUnmount() {
}
```
[Try it on CodePen.](http://codepen.io/gaearon/pen/qmqeQx?editors=0010)
[**Try it on CodePen**](http://codepen.io/gaearon/pen/qmqeQx?editors=0010)
Note that React assigns no special meaning to the `this.el` field. It only works because we have previously assigned this field from a `ref` in the `render()` method:
@ -131,7 +131,7 @@ handleChange(e) {
}
```
[Try it on CodePen.](http://codepen.io/gaearon/pen/bWgbeE?editors=0010)
[**Try it on CodePen**](http://codepen.io/gaearon/pen/bWgbeE?editors=0010)
Finally, there is one more thing left to do. In React, props can change over time. For example, the `<Chosen>` component can get different children if parent component's state changes. This means that at integration points it is important that we manually update the DOM in response to prop updates, since we no longer let React manage the DOM for us.
@ -186,7 +186,7 @@ class Chosen extends React.Component {
}
```
[Try it on CodePen.](http://codepen.io/gaearon/pen/xdgKOz?editors=0010)
[**Try it on CodePen**](http://codepen.io/gaearon/pen/xdgKOz?editors=0010)
## Integrating with Other View Libraries
@ -247,7 +247,7 @@ ReactDOM.render(
);
```
[Try it on CodePen.](http://codepen.io/gaearon/pen/RVKbvW?editors=1010)
[**Try it on CodePen**](http://codepen.io/gaearon/pen/RVKbvW?editors=1010)
You can have as many such isolated components as you like, and use `ReactDOM.render()` to render them to different DOM containers. Gradually, as you convert more of your app to React, you will be able to combine them into larger components, and move some of the `ReactDOM.render()` calls up the hierarchy.
@ -275,7 +275,7 @@ const ParagraphView = Backbone.View.extend({
});
```
[Try it on CodePen.](http://codepen.io/gaearon/pen/gWgOYL?editors=0010)
[**Try it on CodePen**](http://codepen.io/gaearon/pen/gWgOYL?editors=0010)
It is important that we also call `ReactDOM.unmountComponentAtNode()` in the `remove` method so that React unregisters event handlers and other resources associated with the component tree when it is detached.
@ -347,7 +347,7 @@ class List extends React.Component {
}
```
[Try it on CodePen.](http://codepen.io/gaearon/pen/GmrREm?editors=0010)
[**Try it on CodePen**](http://codepen.io/gaearon/pen/GmrREm?editors=0010)
### Extracting Data from Backbone Models
@ -434,6 +434,6 @@ ReactDOM.render(
);
```
[Try it on CodePen.](http://codepen.io/gaearon/pen/PmWwwa?editors=0010)
[**Try it on CodePen**](http://codepen.io/gaearon/pen/PmWwwa?editors=0010)
This technique is not limited to Backbone. You can use React with any model library by subscribing to its changes in the lifecycle hooks and, optionally, copying the data into the local React state.

2
content/docs/introducing-jsx.md

@ -68,7 +68,7 @@ ReactDOM.render(
);
```
[](codepen://introducing-jsx).
[](codepen://introducing-jsx)
We split JSX over multiple lines for readability. While it isn't required, when doing this, we also recommend wrapping it in parentheses to avoid the pitfalls of [automatic semicolon insertion](http://stackoverflow.com/q/2846283).

6
content/docs/lifting-state-up.md

@ -56,7 +56,7 @@ class Calculator extends React.Component {
}
```
[Try it on CodePen.](https://codepen.io/gaearon/pen/ZXeOBm?editors=0010)
[**Try it on CodePen**](https://codepen.io/gaearon/pen/ZXeOBm?editors=0010)
## Adding a Second Input
@ -110,7 +110,7 @@ class Calculator extends React.Component {
}
```
[Try it on CodePen.](https://codepen.io/gaearon/pen/jGBryx?editors=0010)
[**Try it on CodePen**](https://codepen.io/gaearon/pen/jGBryx?editors=0010)
We have two inputs now, but when you enter the temperature in one of them, the other doesn't update. This contradicts our requirement: we want to keep them in sync.
@ -299,7 +299,7 @@ class Calculator extends React.Component {
}
```
[Try it on CodePen.](https://codepen.io/gaearon/pen/WZpxpz?editors=0010)
[**Try it on CodePen**](https://codepen.io/gaearon/pen/WZpxpz?editors=0010)
Now, no matter which input you edit, `this.state.temperature` and `this.state.scale` in the `Calculator` get updated. One of the inputs gets the value as is, so any user input is preserved, and the other input value is always recalculated based on it.

10
content/docs/lists-and-keys.md

@ -42,7 +42,7 @@ ReactDOM.render(
);
```
[Try it on CodePen.](https://codepen.io/gaearon/pen/GjPyQr?editors=0011)
[**Try it on CodePen**](https://codepen.io/gaearon/pen/GjPyQr?editors=0011)
This code displays a bullet list of numbers between 1 and 5.
@ -94,7 +94,7 @@ ReactDOM.render(
);
```
[Try it on CodePen.](https://codepen.io/gaearon/pen/jrXYRR?editors=0011)
[**Try it on CodePen**](https://codepen.io/gaearon/pen/jrXYRR?editors=0011)
## Keys
@ -202,7 +202,7 @@ ReactDOM.render(
);
```
[Try it on CodePen.](https://codepen.io/gaearon/pen/ZXeOGM?editors=0010)
[**Try it on CodePen**](https://codepen.io/gaearon/pen/ZXeOGM?editors=0010)
A good rule of thumb is that elements inside the `map()` call need keys.
@ -246,7 +246,7 @@ ReactDOM.render(
);
```
[Try it on CodePen.](https://codepen.io/gaearon/pen/NRZYGN?editors=0010)
[**Try it on CodePen**](https://codepen.io/gaearon/pen/NRZYGN?editors=0010)
Keys serve as a hint to React but they don't get passed to your components. If you need the same value in your component, pass it explicitly as a prop with a different name:
@ -296,6 +296,6 @@ function NumberList(props) {
}
```
[Try it on CodePen.](https://codepen.io/gaearon/pen/BLvYrB?editors=0010)
[**Try it on CodePen**](https://codepen.io/gaearon/pen/BLvYrB?editors=0010)
Sometimes this results in clearer code, but this style can also be abused. Like in JavaScript, it is up to you to decide whether it is worth extracting a variable for readability. Keep in mind that if the `map()` body is too nested, it might be a good time to [extract a component](/docs/components-and-props.html#extracting-components).

4
content/docs/portals.md

@ -46,7 +46,7 @@ A typical use case for portals is when a parent component has an `overflow: hidd
>
> It is important to remember, when working with portals, you'll need to make sure to follow the proper accessibility guidelines.
[Try it on CodePen.](https://codepen.io/gaearon/pen/yzMaBd)
[**Try it on CodePen**](https://codepen.io/gaearon/pen/yzMaBd)
## Event Bubbling Through Portals
@ -147,6 +147,6 @@ function Child() {
ReactDOM.render(<Parent />, appRoot);
```
[Try it on CodePen.](https://codepen.io/gaearon/pen/jGBWpE)
[**Try it on CodePen**](https://codepen.io/gaearon/pen/jGBWpE)
Catching an event bubbling up from a portal in a parent component allows the development of more flexible abstractions that are not inherently reliant on portals. For example, if you render a `<Modal />` component, the parent can capture its events regardless of whether it's implemented using portals.

14
content/docs/state-and-lifecycle.md

@ -28,7 +28,7 @@ function tick() {
setInterval(tick, 1000);
```
[Try it on CodePen.](http://codepen.io/gaearon/pen/gwoJZk?editors=0010)
[**Try it on CodePen**](http://codepen.io/gaearon/pen/gwoJZk?editors=0010)
In this section, we will learn how to make the `Clock` component truly reusable and encapsulated. It will set up its own timer and update itself every second.
@ -54,7 +54,7 @@ function tick() {
setInterval(tick, 1000);
```
[Try it on CodePen.](http://codepen.io/gaearon/pen/dpdoYR?editors=0010)
[**Try it on CodePen**](http://codepen.io/gaearon/pen/dpdoYR?editors=0010)
However, it misses a crucial requirement: the fact that the `Clock` sets up a timer and updates the UI every second should be an implementation detail of the `Clock`.
@ -100,7 +100,7 @@ class Clock extends React.Component {
}
```
[Try it on CodePen.](http://codepen.io/gaearon/pen/zKRGpo?editors=0010)
[**Try it on CodePen**](http://codepen.io/gaearon/pen/zKRGpo?editors=0010)
`Clock` is now defined as a class rather than a function.
@ -192,7 +192,7 @@ ReactDOM.render(
);
```
[Try it on CodePen.](http://codepen.io/gaearon/pen/KgQpJd?editors=0010)
[**Try it on CodePen**](http://codepen.io/gaearon/pen/KgQpJd?editors=0010)
Next, we'll make the `Clock` set up its own timer and update itself every second.
@ -301,7 +301,7 @@ ReactDOM.render(
);
```
[Try it on CodePen.](http://codepen.io/gaearon/pen/amqdNA?editors=0010)
[**Try it on CodePen**](http://codepen.io/gaearon/pen/amqdNA?editors=0010)
Now the clock ticks every second.
@ -436,7 +436,7 @@ function FormattedDate(props) {
}
```
[Try it on CodePen.](http://codepen.io/gaearon/pen/zKRqNB?editors=0010)
[**Try it on CodePen**](http://codepen.io/gaearon/pen/zKRqNB?editors=0010)
This is commonly called a "top-down" or "unidirectional" data flow. Any state is always owned by some specific component, and any data or UI derived from that state can only affect components "below" them in the tree.
@ -461,7 +461,7 @@ ReactDOM.render(
);
```
[Try it on CodePen.](http://codepen.io/gaearon/pen/vXdGmd?editors=0010)
[**Try it on CodePen**](http://codepen.io/gaearon/pen/vXdGmd?editors=0010)
Each `Clock` sets up its own timer and updates independently.

4
content/docs/uncontrolled-components.md

@ -37,7 +37,7 @@ class NameForm extends React.Component {
}
```
[Try it on CodePen.](https://codepen.io/gaearon/pen/WooRWa?editors=0010)
[**Try it on CodePen**](https://codepen.io/gaearon/pen/WooRWa?editors=0010)
Since an uncontrolled component keeps the source of truth in the DOM, it is sometimes easier to integrate React and non-React code when using uncontrolled components. It can also be slightly less code if you want to be quick and dirty. Otherwise, you should usually use controlled components.
@ -80,5 +80,5 @@ You should use the File API to interact with the files. The following example sh
`embed:uncontrolled-components/input-type-file.js`
[Try it on CodePen](codepen://uncontrolled-components/input-type-file)
[](codepen://uncontrolled-components/input-type-file)

36
content/tutorial/tutorial.md

@ -18,7 +18,7 @@ redirect_from:
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.
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 is updated as the game progresses.
@ -38,7 +38,7 @@ There are two ways to complete this tutorial: you can either write the code in y
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.
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.
@ -135,9 +135,7 @@ The `ShoppingList` component above only renders built-in DOM components like `<d
## 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,** open `src/index.js` in your project folder (you have already touched this file during the [setup](#setup-option-2-local-development-environment)).
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 focus on learning React and programming the tic-tac-toe game.
@ -184,7 +182,7 @@ After: You should see a number in each square in the rendered output.
![React Devtools](../images/tutorial/tictac-numbers.png)
**[View the current code.](https://codepen.io/gaearon/pen/aWWQOG?editors=0010)**
**[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.
@ -288,7 +286,7 @@ By calling `this.setState` from an `onClick` handler in the Square's `render` me
When you call `setState` in a component, React automatically updates the child components inside of it too.
**[View the current code.](https://codepen.io/gaearon/pen/VbbVLg?editors=0010)**
**[View the full code at this point](https://codepen.io/gaearon/pen/VbbVLg?editors=0010)**
### Developer Tools
@ -389,7 +387,7 @@ We will now use the prop passing mechanism again. We will modify the Board to in
}
```
**[View the current code.](https://codepen.io/gaearon/pen/gWWQPY?editors=0010)**
**[View the full code at this point](https://codepen.io/gaearon/pen/gWWQPY?editors=0010)**
Each Square will now receive a `value` prop that will either be `'X'`, `'O'`, or `null` for empty squares.
@ -500,7 +498,7 @@ class Board extends React.Component {
}
```
**[View the current code.](https://codepen.io/gaearon/pen/ybbQJX?editors=0010)**
**[View the full code at this point](https://codepen.io/gaearon/pen/ybbQJX?editors=0010)**
After these changes, we're again able to click on the Squares to fill them. However, now the state is stored in the Board component instead of the individual Square components. When the Board's state changes, the Square components re-render automatically. Keeping the state of all squares in the Board component will allow it to determine the winner in the future.
@ -568,10 +566,10 @@ function Square(props) {
}
```
**[View the current code.](https://codepen.io/gaearon/pen/QvvJOv?editors=0010)**
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 functional component, we also changed `onClick={() => this.props.onClick()}` to a shorter `onClick={props.onClick}` (note the lack of parentheses on *both* sides). In a class, we used an arrow function to access the correct `this` value, but in a functional component we don't need to worry about `this`.
@ -673,7 +671,7 @@ class Board extends React.Component {
}
```
**[View the current code.](https://codepen.io/gaearon/pen/KmmrBy?editors=0010)**
**[View the full code at this point](https://codepen.io/gaearon/pen/KmmrBy?editors=0010)**
### Declaring a Winner
@ -733,7 +731,7 @@ We can now change the Board's `handleClick` function to return early by ignoring
}
```
**[View the current code.](https://codepen.io/gaearon/pen/LyyXgK?editors=0010)**
**[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.
@ -965,7 +963,7 @@ Finally, we need to move the `handleClick` method from the Board component to th
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 current code.](https://codepen.io/gaearon/pen/EmmOqJ?editors=0010)**
**[View the full code at this point](https://codepen.io/gaearon/pen/EmmOqJ?editors=0010)**
### Showing the Past Moves
@ -1025,7 +1023,7 @@ Let's `map` over the `history` in the Game's `render` method:
}
```
**[View the current code.](https://codepen.io/gaearon/pen/EmmGEa?editors=0010)**
**[View the full code at this point](https://codepen.io/gaearon/pen/EmmGEa?editors=0010)**
For each move in the tic-tac-toes's game's history, we create a list item `<li>` which contains a button `<button>`. The button has a `onClick` handler which calls a method called `this.jumpTo()`. We haven't implemented the `jumpTo()` method yet. For now, we should see a list of the moves that have occurred in the game and a warning that says:
@ -1089,7 +1087,7 @@ In the Game component's `render` method, we can add the key as `<li key={move}>`
});
```
**[View the current code.](https://codepen.io/gaearon/pen/PmmXRE?editors=0010)**
**[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.
@ -1164,10 +1162,10 @@ Finally, we will modify the Game component's `render` method from always renderi
// the rest has not changed
```
**[View the current code.](https://codepen.io/gaearon/pen/gWWZgR?editors=0010)**
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
Congratulations! You've created a tic-tac-toe game that:
@ -1179,7 +1177,7 @@ Congratulations! You've created a tic-tac-toe game that:
Nice work! We hope you now feel like you have a decent grasp on how React works.
Check out the final result here: [Final Result](https://codepen.io/gaearon/pen/gWWZgR?editors=0010).
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:

2
gatsby-config.js

@ -60,7 +60,7 @@ module.exports = {
{
resolve: 'gatsby-remark-code-repls',
options: {
defaultText: 'Try it on CodePen',
defaultText: '<b>Try it on CodePen</b>',
directory: `${__dirname}/examples/`,
externals: [
`//unpkg.com/react/umd/react.development.js`,

Loading…
Cancel
Save