-
Notifications
You must be signed in to change notification settings - Fork 8
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
Conversation
There was a problem hiding this 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. |
There was a problem hiding this comment.
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
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. |
There was a problem hiding this comment.
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
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. |
There was a problem hiding this comment.
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"
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. |
const Post = () => { | ||
const printMessage = () => { | ||
console.log('Hello! We\'re in printMessage!'); | ||
} | ||
|
||
return (<section> | ||
<button onClick={printMessage}>Like</button> | ||
</section>) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
spacing and ;
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._ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
update caption
_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_ |
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>) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
spacing and ;
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> | |
); | |
}; |
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>) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
spacing and ;
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. |
There was a problem hiding this comment.
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.
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. |
There was a problem hiding this comment.
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.
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. |
There was a problem hiding this 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 |
There was a problem hiding this comment.
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!"
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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
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 |
There was a problem hiding this comment.
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
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 |
|
||
### 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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo
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. |
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>) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
quotes, spacing and ;
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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add caption
![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_ |
### !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 |
There was a problem hiding this comment.
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
### !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. |
There was a problem hiding this comment.
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
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. |
There was a problem hiding this 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
There was a problem hiding this 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
…-handling batch of state and event handling improvements
…ializing state w props Co-authored-by: Ansel Rognlie <[email protected]>
Co-authored-by: Ansel Rognlie <[email protected]>
Co-authored-by: Ansel Rognlie <[email protected]>
No description provided.