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

state-and-event-handling #38

Merged
merged 11 commits into from
Jun 15, 2021
Merged

state-and-event-handling #38

merged 11 commits into from
Jun 15, 2021

Conversation

tildeee
Copy link
Collaborator

@tildeee tildeee commented Jun 13, 2021

No description provided.

@anselrognlie anselrognlie self-assigned this Jun 14, 2021
Copy link
Contributor

@anselrognlie anselrognlie left a comment

Choose a reason for hiding this comment

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

comments for event handling
preview branch with suggestions applied at: https://github.com/Ada-Developers-Academy/core-unit-3/tree/ar/state-and-event-handling


## Goals

Our React web apps are more fulfilling when they handle user events. To handle events in React, we must learn the React conventions.
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this conveys the intent with a bit more clarity

Suggested change
Our React web apps are more fulfilling when they handle user events. To handle events in React, we must learn the React conventions.
Our React web apps become more capable when they handle user events. To handle events in React, we must learn the React conventions.


## Event Listeners

For any element to listen to an event, we set an attribute to the element.
Copy link
Contributor

Choose a reason for hiding this comment

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

current phrasing could be read as meaning we assign the element to its own attribute, which is a little odd

Suggested change
For any element to listen to an event, we set an attribute to the element.
For any element to listen to an event, we set an attribute on the element.


For click events, we set the `onClick` attribute.

When submitting a form, for submit events, we set the `onSubmit` attribute. To handle when a `<input type="text">` element changes, we set the `onChange` attribute.
Copy link
Contributor

Choose a reason for hiding this comment

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

I read <input> the same as "input", that is with an initial vowel, so I prefer "an"

Suggested change
When submitting a form, for submit events, we set the `onSubmit` attribute. To handle when a `<input type="text">` element changes, we set the `onChange` attribute.
When submitting a form, for submit events, we set the `onSubmit` attribute. To handle when an `<input type="text">` element changes, we set the `onChange` attribute.

Comment on lines 46 to 54
const Post = () => {
const printMessage = () => {
console.log('Hello! We\'re in printMessage!');
}

return (<section>
<button onClick={printMessage}>Like</button>
</section>)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

spacing and ;

Suggested change
const Post = () => {
const printMessage = () => {
console.log('Hello! We\'re in printMessage!');
}
return (<section>
<button onClick={printMessage}>Like</button>
</section>)
}
const Post = () => {
const printMessage = () => {
console.log('Hello! We\'re in printMessage!');
};
return (
<section>
<button onClick={printMessage}>Like</button>
</section>
);
};

<!-- prettier-ignore-end -->

![An app with a "like" button, and browser Dev Tools that read "Hello! We're in printMessage!" in the console.](../assets/state-and-event-handling_event-handling_printMessage.png)
_Fig. An app with a "like" button, and browser Dev Tools that read "Hello! We're in printMessage!" in the console._
Copy link
Contributor

Choose a reason for hiding this comment

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

update caption

Suggested change
_Fig. An app with a "like" button, and browser Dev Tools that read "Hello! We're in printMessage!" in the console._
_Fig. Clicking the Like button calls `printMessage`, with our message appearing in the console_

Comment on lines 112 to 126
const Post = () => {
const printName = (name) => {
console.log('We\'re in printName!');
console.log(`Hello, ${name}!`);
}

const printMessage = () => {
printName('Ada Lovelace');
console.log('Now, we\'re in printMessage!');
}

return (<section>
<button onClick={printMessage}>Like</button>
</section>)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

spacing and ;

Suggested change
const Post = () => {
const printName = (name) => {
console.log('We\'re in printName!');
console.log(`Hello, ${name}!`);
}
const printMessage = () => {
printName('Ada Lovelace');
console.log('Now, we\'re in printMessage!');
}
return (<section>
<button onClick={printMessage}>Like</button>
</section>)
}
const Post = () => {
const printName = (name) => {
console.log('We\'re in printName!');
console.log(`Hello, ${name}!`);
};
const printMessage = () => {
printName('Ada Lovelace');
console.log('Now, we\'re in printMessage!');
};
return (
<section>
<button onClick={printMessage}>Like</button>
</section>
);
};

state-and-event-handling/event-handling.md Show resolved Hide resolved
Comment on lines 146 to 155
const Post = () => {
const printName = (name) => {
console.log('We\'re in printName!');
console.log(`Hello, ${name}!`);
}

return (<section>
<button onClick={() => printName('Ada Lovelace')}>Like</button>
</section>)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

spacing and ;

Suggested change
const Post = () => {
const printName = (name) => {
console.log('We\'re in printName!');
console.log(`Hello, ${name}!`);
}
return (<section>
<button onClick={() => printName('Ada Lovelace')}>Like</button>
</section>)
}
const Post = () => {
const printName = (name) => {
console.log('We\'re in printName!');
console.log(`Hello, ${name}!`);
};
return (
<section>
<button onClick={() => printName('Ada Lovelace')}>Like</button>
</section>
);
};


Every time we click on our "like" button, our anonymous function will fire. This, in turn, invokes `printName('Ada Lovelace')`!

This is a common pattern in React code.
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think this is clear about the pattern. Let's be a little more explicit and warn about a common error students run into.

Suggested change
This is a common pattern in React code.
Using anonymous functions for event handlers is a common pattern in React, especially when the function we want to call needs us to pass in some parameters.
A common mistake when trying to call a function that takes an argument as an event handler is to try to write the function call, in this case `printName('Ada Lovelace')`, directly as the even handler.
But this does not have the desired result! Instead, it:
1. Calls `printName('Ada Lovelace')` as the button is being rendered rather than when it is clicked. This causes the output message to appear while the page is still being rendered. Not what we wanted!
1. Sets the _result_ of calling `printName('Ada Lovelace')` as the click handler. Since `printName` returns nothing, the result is `undefined`. So no event handler is registered for `onClick`, and the button does nothing when it is clicked. Also not what we wanted!


This is a common pattern in React code.

When our event handler has at least one parameter, we can use this technique.
Copy link
Contributor

Choose a reason for hiding this comment

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

expand this part of the explanation too. recognize this pattern works well in some situations, but named functions still work better in others.

Suggested change
When our event handler has at least one parameter, we can use this technique.
So when our desired behavior takes at least one parameter, we can use this technique of wrapping it in an anonymous function.
An anonymous function lets us call arbitrary code exactly where the event registration occurs, which can be good for understandability. But we may find that, if we need to do more than one or two things in the event handler, then using a named function may still be more understandable.

Copy link
Contributor

@anselrognlie anselrognlie left a comment

Choose a reason for hiding this comment

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

comments for using state
updated preview branch with suggestions applied at: https://github.com/Ada-Developers-Academy/core-unit-3/tree/ar/state-and-event-handling


Consider the following front-end features:

- In a weather web app, a button that increases the temperature displayed from 31 to 32
Copy link
Contributor

Choose a reason for hiding this comment

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

Aside: I love the thought of the different reactions folx could have to this statement depending on whether their default frame of reference is Fahrenheit or Celsius! Either "brrr, that's cold" or "ugh, that's warm!"

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'm really really really glad you picked up on this 😂 😂 😂 !!!


### !callout-info

## Getting the Initial Value From Props
Copy link
Contributor

Choose a reason for hiding this comment

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

This has to be done carefully and with great intention, or else it can become an anti-pattern: https://medium.com/@justintulk/react-anti-patterns-props-in-initial-state-28687846cc2e

The question is why would we bother storing this in state when the value is already available in props? And once we divorce the value from the props by putting it in state, we run the risk of any prop changes not being reflected in the state (since it will only initialize once). To get around this, we would need to register a dependency on the particular prop value to update the state when the prop changes. But if we do that, we might as well simply read from the prop the whole time.

Now maybe this is OK (say the prop value indicates some range and we need to some some pre-calculation over the range and store the result in state, then register an effect to run if the prop updates), but in general, if we find ourselves tempted to initialize state from props, we should double check, and think about it again, and then probably not do that.

Copy link
Contributor

Choose a reason for hiding this comment

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

Offline discussion resulted in decision to cut this callout


We can't, because of how React renders components!

React is known for rendering UI really quickly! Under the hood, React achieves its speed by detecting changes in state, and re-rendering the component.
Copy link
Contributor

Choose a reason for hiding this comment

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

a little more detail about how react renders things

Suggested change
React is known for rendering UI really quickly! Under the hood, React achieves its speed by detecting changes in state, and re-rendering the component.
React is known for rendering UI really quickly! Under the hood, React achieves its speed by detecting changes in state, and re-rendering only those components that depend on that state.

`useState` is a function. It returns an _array_ of two things.

1. In index `0` of the returned array, there is a _variable_ that references the piece of state we're managing
1. In index `1`, there is a _function_ that updates that piece of state
Copy link
Contributor

Choose a reason for hiding this comment

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

explicitly mention that its a reference
existing phrasing could sound like getting the function itself is what causes the update

Suggested change
1. In index `1`, there is a _function_ that updates that piece of state
1. In index `1`, there is a _reference to a function_ for updating that piece of state

state-and-event-handling/using-state.md Show resolved Hide resolved

### Example: `useState`

Imagine a social media web app that has a list of posts. Each `Post` component that needs to display the number of likes it has.
Copy link
Contributor

Choose a reason for hiding this comment

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

typo

Suggested change
Imagine a social media web app that has a list of posts. Each `Post` component that needs to display the number of likes it has.
Imagine a social media web app that has a list of posts. Each `Post` component needs to display the number of likes it has.

Comment on lines 141 to 149
import { useState } from "react";

const Post = () => {
const [likesCount, setLikesCount] = useState(0);

return (<section>
<p>What is the number of likes we should display? {likesCount}</p>
</section>)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

quotes, spacing and ;

Suggested change
import { useState } from "react";
const Post = () => {
const [likesCount, setLikesCount] = useState(0);
return (<section>
<p>What is the number of likes we should display? {likesCount}</p>
</section>)
}
import { useState } from 'react';
const Post = () => {
const [likesCount, setLikesCount] = useState(0);
return (
<section>
<p>What is the number of likes we should display? {likesCount}</p>
</section>
);
};

What is the number of likes we should display? 0
```

![A web app that displays the following text: "What is the number of likes we should display? 0"](../assets/state-and-event-handling_using-state_initial-state.png)
Copy link
Contributor

Choose a reason for hiding this comment

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

add caption

Suggested change
![A web app that displays the following text: "What is the number of likes we should display? 0"](../assets/state-and-event-handling_using-state_initial-state.png)
![A web app that displays the following text: "What is the number of likes we should display? 0"](../assets/state-and-event-handling_using-state_initial-state.png)
_Fig. The `Post` component can use its state like any other variable_

Comment on lines 165 to 187
### !callout-info

## Getting the Initial Value From Props

Instead of passing in a string literal to `useState`, what would happen if we passed in a variable?

<br/>

Sometimes, we'll get the initial value of state through _`props`_! Consider:

```
const SomeComponent = (props) => {
const [pieceOfState, setPieceOfState] = useState(this.props.initialPieceOfState);
}

SomeComponent.propTypes = {
initialPieceOfState: PropTypes.string.isRequired
};
```

In this example, `SomeComponent` requires a `prop` named `initialPieceOfState`. We read this property with `this.props.initialPieceOfState` and pass it into `useState`.

### !end-callout
Copy link
Contributor

Choose a reason for hiding this comment

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

cut this per offline discussion

Suggested change
### !callout-info
## Getting the Initial Value From Props
Instead of passing in a string literal to `useState`, what would happen if we passed in a variable?
<br/>
Sometimes, we'll get the initial value of state through _`props`_! Consider:
```
const SomeComponent = (props) => {
const [pieceOfState, setPieceOfState] = useState(this.props.initialPieceOfState);
}
SomeComponent.propTypes = {
initialPieceOfState: PropTypes.string.isRequired
};
```
In this example, `SomeComponent` requires a `prop` named `initialPieceOfState`. We read this property with `this.props.initialPieceOfState` and pass it into `useState`.
### !end-callout


<br/>

This lesson teaches managing state using React hooks. Both are valid ways to manage state. Using React hooks is considered better practice because it improves the ability to create independent, clean components. If we're curious, we can [read more about the motivation to use hooks in the official React docs](https://reactjs.org/docs/hooks-intro.html#motivation) anytime.
Copy link
Contributor

Choose a reason for hiding this comment

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

rephrase so to make it clear that these benefits are not something we're necessarily going to notice right now

Suggested change
This lesson teaches managing state using React hooks. Both are valid ways to manage state. Using React hooks is considered better practice because it improves the ability to create independent, clean components. If we're curious, we can [read more about the motivation to use hooks in the official React docs](https://reactjs.org/docs/hooks-intro.html#motivation) anytime.
This lesson teaches managing state using React hooks. Both are valid ways to manage state. Using React hooks is considered better practice because this method is designed to improve our long-term ability to create independent, clean components. If we're curious, we can [read more about the motivation to use hooks in the official React docs](https://reactjs.org/docs/hooks-intro.html#motivation) anytime.

Copy link
Contributor

@anselrognlie anselrognlie left a comment

Choose a reason for hiding this comment

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

comments for updating state
updated preview branch with suggestion applied at: https://github.com/Ada-Developers-Academy/core-unit-3/tree/ar/state-and-event-handling

state-and-event-handling/updating-state.md Outdated Show resolved Hide resolved
state-and-event-handling/updating-state.md Outdated Show resolved Hide resolved
state-and-event-handling/updating-state.md Outdated Show resolved Hide resolved
state-and-event-handling/updating-state.md Outdated Show resolved Hide resolved
state-and-event-handling/updating-state.md Outdated Show resolved Hide resolved
state-and-event-handling/updating-state.md Outdated Show resolved Hide resolved
state-and-event-handling/updating-state.md Outdated Show resolved Hide resolved
state-and-event-handling/updating-state.md Outdated Show resolved Hide resolved
state-and-event-handling/updating-state.md Outdated Show resolved Hide resolved
state-and-event-handling/updating-state.md Outdated Show resolved Hide resolved
Copy link
Contributor

@anselrognlie anselrognlie left a comment

Choose a reason for hiding this comment

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

completes review
updated preview branch with suggestion applied at: https://github.com/Ada-Developers-Academy/core-unit-3/tree/ar/state-and-event-handling

@tildeee tildeee merged commit c3f5cee into main Jun 15, 2021
@beccaelenzil beccaelenzil deleted the state-and-event-handling branch May 18, 2022 22:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants