리액트의 이벤트
리액트는 합성 이벤트 시스템을 구현해 리액트 애플리케이션과 인터페이스에 일관성과 고성능을 보장한다.
일관성을 위해 이 이벤트 시스템은 이벤트가 여러 다른 브라우저와 플랫폼에서 동일한 속성을 갖도록 이벤트를 정규화한다.
또한 고성능을 위해 자동으로 이벤트를 위임한다. 리액트가 이벤트 핸들러를 노드 자체에 연결하는 것은 아니다. 실제로는 단 하나의 이벤트 리스너가 문서 루트에 연결되며, 이벤트가 발생하면 리액트가 이를 적절한 컴포넌트 요소로 매핑한다. 또한 리액트는 이벤트 리스너가 언마운트될 때 자동으로 이를 제거한다.
DOM 이벤트 리스너
HTML은 태그 특성을 위한 간단하고 이해하기 쉬운 이벤트 처리 API를 제공한다. 이 API의 문제는 바람직하지 않은 부수효과가 많기 때문이다. 이 API는 전역 스코프를 오염시키며, 큰 HTML파일의 컨텍스트 안에서 추적하기 어렵고, 성능이 떨어지며, 메모리 누수의 원인이 될 수 있다.
JSX는 HTML의 이벤트 처리 API와 비슷하게 사용하기 쉽고 손쉽게 이해할 수 있는 API를 이용하지만 HTML이벤트 처리 API와 달리 바람직하지 않은 부수 효과는 제거했다. 콜백 함수는 컴포넌트 스코프이며 이벤트 위임과 자동 관리 언마운팅을 이용해 영리하게 작업을 처리한다. 그런데 원래 HTML 구현과는 몃 가지 사소한 차이점이 있다는 데 주의해야 한다. 리액트의 속성에는 카멜표기법이 적용된다. 또한 모든 브라우저와 장치에서 일관성을 유지하기 위해 여러 브라우저와 버전에 포함된 모든 변형의 하위 집합을 구현한다.
이전 칸반앱에서 에로우펀션을 활용해 onClick 이벤트 핸들러 안에 다음과 같은 인라인 함수를 추가.
onClick={
() => this.setState({showDetails: !this.state.showDetails})
}
render(){
let cardDetails;
if(this.state.showDetails){
cardDetails = (
<div className="card__details">
{this.props.description}
<CheckList cardId={this.props.id}
tasks = {this.props.tasks}/>
</div>
);
};
return (
<div className="card">
<div className="card__title" onClick={
() => this.setState({showDetails: !this.state.showDetails})
}
>{this.props.title}</div>
{cardDetails}
</div>
);
}
}
이놈을 아래와 같이 바꿀수 있다.
toggleDetails(){
this.setState({showDetails: !this.state.showDetails})
}
render(){
let cardDetails;
if(this.state.showDetails){
cardDetails = (
<div className="card__details">
{this.props.description}
<CheckList cardId={this.props.id}
tasks = {this.props.tasks}/>
</div>
);
};
return (
<div className="card">
<div className="card__title" onClick={
this.toggleDetails.bind(this)
}>{this.props.title}</div>
{cardDetails}
</div>
);
}
}
JSX 자세히 살펴보기
JSX는 자바스크립트 코드 안에 선언적인 XML 스타일의 구문을 작성할 수 있게 해주는 리액트의 선택적 자바스크립트 구문 확장이다.
리액트의 JSX는 웹 프로젝트에 대해서는 HTML과 비슷한 XML 태그 집합을 제공하지만, 다른 XML태그 집합을 이용해 사용자 인터페이스를 작성하는 사용 사례(예:리액트와 SVG, 리액트 캔버스, 리액트 네이티브)
트랜스파일(브라우저나 서버가 코드를 해석할 수 있도록 일반 자바스크립트로 변환)을 거치면 XML은 리액트 라이브러리에 대한 함수 호출로 변환된다.
<h1>Hello World</h1> => React.createElement("h1",null,"Hello World")
JSX의 장점
- XML은 특성을 이용한 요소 트리로 UI를 표현하는 데 아주 적절하다.
- 애플리케이션의 구조를 시각화하기 쉬우며 더 간결하다.
- 일반 자바스크립트이므로 언어의 의미를 변형시키지 않는다.
JSX의 특징
- 태그 특성은 카멜표기법으로 작성한다. ```HTML
=> React는
return 대문자 기입
- 모든 요소는 짝이 맞아야 한다.
```HTML
- 특성 이름은 DOM API 기반이다.
class 와 className
JSX의 특이점
JSX에는 다루기 까다로운 측면이 있다. 이번 절에서는 JSX로 컴포넌트를 작성할 때 경험할 수 있는 일반적인 문제에 대처하는 간단한 기법과 팁, 전략에 대해 알아보쟈
단일 루트 노드 리액트 컴포넌트는 단일 루트 노드만 렌더링 할 수 있다. 이러한 제한이 있는 이유를 알아보기 위해 다음 render 함수의 return문을 살펴보자.
return(
<h1>Hello World</h1>
)
// 이는 다음과 같이 변화된다.
return React.createElement("h1", null, "Hello World");
// 그러나 다음과 코드는 유효하지 않다.
return(
<h1>Hello World</h1>
<h2>Hello World</h2>
)
정확히 말하면 이것은 JSX의 제한이 아니라 자바스크립트의 특징이다. return문은 단일 값만 반환할 수 있지만, 이 코드는 두 개의 문을 반환하려고 한다. 해결책은 아주 간단한데, 일반 자바스크립트와 마찬가지로 모든 반환값을 루트 객체 하나에 래핑하면 된다. 예를 들어 다음과 같이 작성할 수 있다.
return(
<div>
<h1>Hello World</h1>
<h2>Hello World</h2>
</div>
)
// 위 코드는 다음과 같이 변환한다면,
return React.createElement("div", null,
React.createElement("h1", null, "Hello World"),
React.createElement("h2", null, "World"),
)
즉, 단일 값을 반환하는 유효한 자바스크립트 코드다.
조건 절
if문은 JSX와는 잘 어울리지 않지만 이는 JSX의 제한이 아니라 JSX가 사실은 일반 자바스크립트이기 때문이다. 이해하는 데 도움이 되도록 JSX가 일반 자바스크립트로 변환되는 방법을 다시 확인해보자.
다음과 같은 JSX가 있다고 가정해보자.
return(
<div className="salutation">Hello JSX</div>
)
그런데 다음과 같이 JSX중간에 IF절을 넣었다고 가정해 보자.
<div className={if(condition) {"salutation"}}>
Hello JSX
</div>
이렇게 되면 에러가 발생한다. 어떻게 해결하겠는가??
JSX안에 if문을 사용할 수 없지만 삼항식을 이용하고 조건에 따라 변수에 값을 할당하는 방법과 같은 해결책이 있다.
리액트는 null과 정의되지 않은 값을 인식하며 JSX에서 이스케이프 처리할 경우 아무것도 출력하지 않는다.
<해결 방안=""> 1. 삼항식 이용 ```javascript render(){ return( <div className={condition ? "salutation" : ""}> Hello JSX </div> ) } ``` 삼항식은 조건에 따라 전체 노드를 렌더링하는 경우에도 잘 동작한다. ```