Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated tutorial page with React hooks #3063

Closed
wants to merge 1 commit into from

Conversation

DaniAkash
Copy link

@DaniAkash DaniAkash commented Jun 25, 2020

Addresses reactjs/rfcs#153

This PR contains the Tutorials page rewritten with React Hooks & CodeSandbox. This will help new developers learn React hooks with a more hands-on approach. All the individual stages have been organized in separate CodeSandboxes.

Open to hear feedbacks & improvements from the community. Try out the tutorial ﹣ https://github.com/DaniAkash/reactjs.org/blob/hooks-tutorial/content/tutorial/tutorial.md

Copy link

@alansegar alansegar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great to see this is getting updated. I've gone through the updated tutorial and added comments as I've found things.
Not related to the original tutorial / updating to use hooks but some other ideas on potential improvements:

  • codesandbox.io can run Jest tests so it might be good to add those to the tutorial as long as it doesn't over complicate things
  • codesandbox.io supports using multiple js files so maybe having each component in a separate file would demonstrate how a real project would often be structured and could also be easier to follow

Now we'll change the Square's `return` statement to display the current state's value when clicked:

* Replace `props.value` with `value` inside the `<button>` tag.
* Replace the `onClick={...}` event handler with `onClick={() => setValue("X")}`.

After these changes, the `<button>` tag that is returned by the Square's `render` method looks like this:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
After these changes, the `<button>` tag that is returned by the Square's `render` method looks like this:
After these changes, the `<button>` tag that is returned by the Square's `return` statement looks like this:

{props.value}
</button>
);
};
```

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 `<button>` component tells React to set up a click event listener.
2. When the button is clicked, React will call the `onClick` event handler that is defined in Square's `render()` method.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
2. When the button is clicked, React will call the `onClick` event handler that is defined in Square's `render()` method.
2. When the button is clicked, React will call the `onClick` event handler that is defined in Square's `return` statement.

5. We have not defined the `handleClick()` method yet, so our code crashes. If you click a square now, you should see a red error screen saying something like "this.handleClick is not a function".
3. This event handler calls `props.onClick()`. The Square's `onClick` prop was specified by the Board.
4. Since the Board passed `onClick={() => handleClick(i)}` to Square, the Square calls `this.handleClick(i)` when clicked.
5. We have not defined the `handleClick()` function yet, so our code crashes. If you click a square now, you should see a red error screen saying something like "this.handleClick is not a function".

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
5. We have not defined the `handleClick()` function yet, so our code crashes. If you click a square now, you should see a red error screen saying something like "this.handleClick is not a function".
5. We have not defined the `handleClick()` function yet, so our code crashes. If you click a square now, you should see a red error screen saying something like "handleClick is not a function".

image

4. Since the Board passed `onClick={() => this.handleClick(i)}` to Square, the Square calls `this.handleClick(i)` when clicked.
5. We have not defined the `handleClick()` method yet, so our code crashes. If you click a square now, you should see a red error screen saying something like "this.handleClick is not a function".
3. This event handler calls `props.onClick()`. The Square's `onClick` prop was specified by the Board.
4. Since the Board passed `onClick={() => handleClick(i)}` to Square, the Square calls `this.handleClick(i)` when clicked.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
4. Since the Board passed `onClick={() => handleClick(i)}` to Square, the Square calls `this.handleClick(i)` when clicked.
4. Since the Board passed `onClick={() => handleClick(i)}` to Square, the Square calls `handleClick(i)` when clicked.

@@ -721,37 +596,32 @@ Given an array of 9 squares, this function will check for a winner and return `'

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:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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:
We will call `calculateWinner(squares)` in the Board function component 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 the Board function component with this code:

const renderSquare = i => (
<Square value={props.squares[i]} onClick={() => props.onClick(i)} />
);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At this point in the tutorial the handleClick function hasn't yet been moved from Board to Game.

Suggested change
const handleClick = i => {
if (calculateWinner(squares) || squares[i]) {
return;
}
const newSquares = squares.slice();
newSquares[i] = xIsNext ? "X" : "O";
setSquares(newSquares);
setXIsNext(!xIsNext);
}


return (
<div>
<div className="status">{props.status}</div>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this line (776) is the one being referred to above in the following text:

Since the Game component is now rendering the game's status, we can remove the corresponding code from the Board component. After refactoring, the Board component looks like this:

as corresponding code so I think line 776 needs deleting here.


For each move in the tic-tac-toe 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 in the developer tools console that says:
For each move in the tic-tac-toe 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 `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 in the developer tools console that says:

> Warning:
> Each child in an array or iterator should have a unique "key" prop. Check the render method of "Game".

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The wording of this appears to have changed at some point. I now see the following:

Warning: Each child in a list should have a unique "key" prop.

an array or iterator has changed to a list
image

const current = history[history.length - 1];
```javascript{2-4,9-15}
const handleClick = i => {
const newHistory = history;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure how best to change this but I'm unsure whether having this line here is helpful. It may require some rewording further through the tutorial but I think removing this line and using history in place of newHistory at this point may be clearer.


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 become incorrect.
We will also replace reading `newHistory` with `history.slice(0, 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 become incorrect.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Following on from an earlier comment about newHistory, maybe consider rewording this so that the concept of newHistory is first introduced here.
Also, I'd find historyToStepNumber or similar clearer than newHistory

@harish-sethuraman
Copy link
Collaborator

The react documentation site is being rewritten with hooks and is a work in progress. You can view it at https://beta.reactjs.org

Please see reactjs/reactjs.org#3308.

Thanks 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants