function
vs. Arrow Function
onClick={ function() { console.log(this) }} // undefiend
onClick={ () => console.log(this) } // App { ... }
this가 가지는 값
function
스코프 내에서 this
는 해당 function
을 호출한 객체를 this
로 한다.화살표 함수
스코프 내에서 this
는 정적(Lexical)영역의 상위 객체를 this
로 한다.왜 window
가 아닌 undefined
가 나오는 이유
development
모드에서는 strict mode
를 검사하고, production build
에서는 포함되지 않는다.화살표 함수를 사용하면 bind
함수로 바인딩이 필요하지 않다.
this
는 사용된 곳의 상위 객체를 this
로 사용하기 때문에 this
는 선언된 해당 객체를 가리킨다.React가 권장하는 이벤트 바인딩 방법
// 생성자에서 bind()를 사용하는방법
class LoggingButton extends React.Component {
Constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
console.log('this is:', this);
}
render() {
return (
<button onClick={this.handleClick}>
Click me
</button>
);
}
}
// 사용할 곳에서 bind()를 사용하는 방법
class LoggingButton extends React.Component {
handleClick() {
console.log('this is:', this);
}
render() {
return (
<button onClick={this.handleClick.bind(this)}>
Click me
</button>
);
}
}
// 화살표 함수로 직접 호출하는 방법
// 이 방법은 LoggingButton이 랜더링 될 때마다 새로운 함수를 생성하는 문제가 있다.
// 콜백 함수 내에서 재랜더링을 발생시키는 경우 성능 문제가 발생할 수 있다.
class LoggingButton extends React.Component {
handleClick() {
console.log('this is:', this);
}
render() {
return (
<button onClick={(e) => this.handleClick(e)}>
Click me
</button>
);
}
}
// 화살표 함수로 선언하고 바인딩하는 방법
// 이 방법으로 이벤트를 바인딩 하는것을 권장한다.
class LoggingButton extends React.Component {
handleClick = () => {
console.log('this is:', this);
}
render() {
return (
<button onClick={this.handleClick}>
Click me
</button>
);
}
}
Handling Events
The best way to bind event handlers in React
생성자에서 this를 사용하기 위해서 super(props)
를 사용한다.
What's the difference between “super()” and “super(props)” in React
const ClickCounterButton = props => {
return (
<button onClick={props.handler}>Don`t touch me with your dirty hands!</button>
);
};
class Counter extends React.Component {
render() {
return <span>Clicked {this.props.value} thies.</span>;
}
}
class Content extends React.Component {
constructor(props) {
super(props);
this.state = { counter: 0 };
}
handleClick = (event) => {
this.setState({counter: ++this.state.counter });
}
render() {
return (
<div>
<ClickCounterButton handler={this.handleClick} />
<br/>
<Counter value={this.state.counter}/>
</div>
)
}
}
class Radio extends React.Component {
constructor(props) {
super(props);
let order = props.order;
let i = 1;
this.state = {
outerStyle: this.getStyle(4, i),
innerStyle: this.getStyle(1, i),
selectedStyle: this.getStyle(2, i),
taggerStyle: { top: order * 20, width: 25, height: 25 }
};
}
getStyle(i, m) {
let value = i * m;
return {
top: value,
bottom: value,
left: value,
right: value
};
}
componentDidMount() {
window.addEventListener("resize", this.handleResize);
}
componentWillUnmount() {
window.removeEventListener("resize", this.handleResize);
}
handleResize = event => {
let w = 1 + Math.round(window.innerWidth / 300);
this.setState({
taggerStyle: {
top: this.props.order * w * 10,
width: w * 10,
height: w * 10
},
textStyle: { left: w * 13, fontSize: 7 * w }
});
};
render() {
return (
<div>
<div className="radio-tagger" style={this.state.taggerStyle}>
<input type="radio" name={this.props.name} id={this.props.id} />
<label htmlFor={this.props.id}>
<div className="radio-text" style={this.state.textStyle}>
{this.props.label}
</div>
<div className="radio-outer" style={this.state.outerStyle}>
<div className="radio-inner" style={this.state.innerStyle}>
<div
className="radio-selected"
style={this.state.selectedStyle}
/>
</div>
</div>
</label>
</div>
</div>
);
}
}