# Goals
- Attach event handlers to components
- Bind to [this] with event handlers (and other aproach)
- Pass event handlers down as props to child components
- Undestand key props for mapping over data
## React event
- React use special reserved attributes for event handlings
- [All event list](https://ko.reactjs.org/docs/events.html)
## Method binding : the THIS keyword
- Without binding, you will lose the [this] context when you pass a function as a handler
- So, we need [bind(this)] again
import React, { Component } from 'react';
import './WiseSquare.css';
class WiseSquare extends Component {
constructor(props) {
super(props);
this.dispenseWisdom = this.dispenseWisdom.bind(this);
}
static defaultProps = {
messages: [
"you are so lazy",
"sleep less",
"read more book"
]
};
dispenseWisdom() {
// make variable called messages, and it should be same as messages in this props
let { messages } = this.props;
// let message = [
// "you are so lazy",
// "sleep less",
// "read more book"
// ];
let rIdx = Math.floor(Math.random() * messages.length);
console.log(messages[rIdx]);
}
render() {
return (
<div className='WiseSquare' onMouseEnter={this.dispenseWisdom}>
<span>😝</span>
</div>
);
}
}
export default WiseSquare;
- there is alternative way using [=()=>]
import React, { Component } from 'react';
import './WiseSquare.css';
class ExperWiseSquare extends Component {
static defaultProps = {
messages: [
"you are so lazy",
"sleep less",
"read more book"
]
};
// use arrow here, it's babel stage 2 magic
// automatically add constructor and this keyword to bind
dispenseWisdom = () => {
console.log("this is :", this);
// make variable called messages, and it should be same as messages in this props
let { messages } = this.props;
let rIdx = Math.floor(Math.random() * messages.length);
console.log(messages[rIdx]);
}
render() {
return (
<div className='WiseSquare' onMouseEnter={this.dispenseWisdom}>
<span>😝</span>
</div>
);
}
}
export default ExperWiseSquare;
## Method binding with Arguments
- What if we need to pass arguments to an event handler?
- => use .bind inline and pass the argu as second argu after this
- or arrow function and pass the argu
import React, { Component } from 'react';
import './ButtonList.css';
class ButtonList extends Component {
static defaultProps = {
colors: ['red', 'pink', 'orange', 'limegreen']
};
constructor(props) {
super(props);
this.state = { color: ' ' };
}
changeColor(boxColor) {
this.setState({ color: boxColor });
}
render() {
return (
<div className="ButtonList" style={{ backgroundColor: this.state.color }}>
{this.props.colors.map(color => {
const ColorBox = { backgroundColor: color };
//color변수를 bind의 두번째 변수로 넣어줌
// Both ways, we create new function
// onClick={()=>this.changeColor(color)} 도 가능
return (
<button style={ColorBox} onClick={this.changeColor.bind(this, color)}>
click me!
</button>
);
})}
</div>
);
}
}
export default ButtonList;
## Passing function to child components
import React, { Component } from 'react';
import BetterNumberItem from './BetterNumberItem';
class BetterNumberList extends Component {
constructor(props) {
super(props);
this.state = { nums: [1, 2, 3, 4, 5] };
this.remove = this.remove.bind(this);
}
remove(num) {
this.setState(st => ({
nums: st.nums.filter(n => n !== num)
}));
}
render() {
let nums = this.state.nums.map(n => (
<BetterNumberItem key={n} value={n} remove={this.remove} />
));
return (
<div>
<h1>Better Number List</h1>
<ul>{nums}</ul>
</div>
);
}
}
export default BetterNumberList;
import React, { Component } from 'react';
class BetterNumberItem extends Component {
constructor(props) {
super(props);
this.handleRemove = this.handleRemove.bind(this);
}
handleRemove(evt) {
this.props.remove(this.props.value);
}
render() {
return (
<li>
{this.props.value}
<button onClick={this.handleRemove}>X</button>
</li>
)
}
}
export default BetterNumberItem;
- the idea : child are not stateful, but still need to tell parents to change state.
- How we send data "back up" to the Parent component?
### How data flows
- Parent component defines a function
- the function is passed as a prop to a child component
- The child component invokes the prop
- The parent function is called, usually setting new state
- The parent component is re-rendered along with its children
### Where to bind?
- Higher components is the better
- If you need a parameter, pass it down to the child as props, then bind in parent and child
- Avoid render-inline arrow functions / binding
- Binding is only needed one time(in constructor!)
- IF YOU GET STUCK! don't worry about performance too much. just write code that working and we can refactor later!
### Naming convention
- For the consistency, try to follow the action/handleAction pattern:
- parent : remove, add, open, toggle..
- child : handleRemove, handleAdd, handleOpen, handleToggle..
## List and Key
- When mapping over data and returning components, you get a warning about keys for list items
- [KEY] is a special str attr to include when creating list of elements
- keys help react identify which items have changed
### Picking a key
- Use str that uniquely identifies item
- Most often we would use Ids from dataset as keys
- We can use Idx, but not a good idea
- 노드js에 쓸수있는 라이브러리 있음