JSX를 사용하여 문자열이 아닌 함수로 이벤트 핸들러를 전달 합니다.
React 엘리먼트의 이벤트 처리 방식은 DOM 엘리먼트의 방법과 유사하다. 다만 몇 가지 문법의 차이가 있다.
//함수 컴포넌트
function ActionLink(){
function handleClicke(e){
e.preventDefault();
console.log('The Link was clicked.');
}
return (
<a href='#' onClick={handleClick}>
Click me
</a>
)
}
//class 컴포넌트
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// 콜백에서 `this`가 작동하려면 아래와 같이 바인딩 해주어야 합니다.
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(state => ({
isToggleOn: !state.isToggleOn
}));
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
JSX 콜백 안에서 this
의 의미를 주의해야 한다. JS에서 클래스 메서드는 기본적으로 바인딩 되어 있지 않습니다. this.hadleClick
을 바인딩 하지 않고 onClick
에 전달하면 this
는 undefined
가 된다.
만약 바인딩이 불편하다면 다음 두가지 방법으로 해결이 가능하다.
- 퍼블릭 클래스 필드 문법
handleClick = () => {...}
- 콜백에 화살표 함수 사용
<button onClick={() => this.handleClick()}>
콜백에 화살표 함수 사용 방법의 문제점은 렌더링 될 때마다 다른 콜백이 생성된다는 것이다. 때문에 가급적 퍼블릭 클래스 필드 문법사용을 권장한다.
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
엘리먼트를 저장하기 위해 변수를 사용할 수 있다. 출력의 다른 부분은 변하지 않은 채로 컴포넌트의 일부를 조건부로 렌더링 할 수 있다.
function UserGreeting(props) {
return <h1>Welcome back!</h1>;
}
function GuestGreeting(props) {
return <h1>Please sign up.</h1>;
}
function Greeting(props) {
const isLoggedIn = props.isLoggedIn;
if (isLoggedIn) {
return <UserGreeting />;
}
return <GuestGreeting />;
}
function LoginButton(props) {
return (
<button onClick={props.onClick}>
Login
</button>
);
}
function LogoutButton(props) {
return (
<button onClick={props.onClick}>
Logout
</button>
);
}
class LoginControl extends React.Component {
constructor(props) {
super(props);
this.handleLoginClick = this.handleLoginClick.bind(this);
this.handleLogoutClick = this.handleLogoutClick.bind(this);
this.state = {isLoggedIn: false};
}
handleLoginClick() {
this.setState({isLoggedIn: true});
}
handleLogoutClick() {
this.setState({isLoggedIn: false});
}
render() {
const isLoggedIn = this.state.isLoggedIn;
let button;
if (isLoggedIn) {
button = <LogoutButton onClick={this.handleLogoutClick} />;
} else {
button = <LoginButton onClick={this.handleLoginClick} />;
}
return (
<div>
<Greeting isLoggedIn={isLoggedIn} />
{button}
</div>
);
}
}
{ 조건식 && 참일 때 값 }
거짓일 때는 항상 false
로 평가된다. 만약 조건이 false
라면 React는 무시된다.
주의
render() {
const count = 0;
return (
<div>
{ count && <h1>Messages: {count}</h1>}
</div>
);
} // 이 경우 <div>0</div> 이 렌더에 반환된다.
{ 조건식 ? 참일 때 값 : 거짓일 때 값 }
render() {
const isLoggedIn = this.state.isLoggedIn;
return (
<div>
{isLoggedIn
? <LogoutButton onClick={this.handleLogoutClick} />
: <LoginButton onClick={this.handleLoginClick} />
}
</div>
);
}
조건이 너무 복잡하다면 컴포넌트를 분리하기 좋을 때 라는 것이다.
가끔 컴포넌트에 의해 렌더링될 때 컴포넌트 자체를 숨기고 싶을 때가 있을 수도 있다. 그때는 렌더링 결과를 출력하는 대신 null
을 반환하면 해결할 수 있다.
React에서 리스트를 만드는 방법은 배열에 map()
을 적용하여 만듭니다.
const arr = [/*인자들*/]
arr.map( (/*인자*/) => /*적용할 컴포넌트*/)
위 그림에서 보듯 있는 배열 자체에 map()
을 적용해주기만 하면 된다. 그리고 map을 통해서 적용할 내용을 함수대신에 컴포넌트에 들어가게 해주면 리스트 작성이 훨씬 수월해진다.
기본 리스트 컴포넌트 : 일반적으로 컴포넌트 안에서 리스트를 렌더링 한다.
Key는 어떤 항목을 변경, 추가 또는 삭제할지 식별하는 것을 돕는다. 배열 내부의 엘리먼트에 지정해야한다.
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
<li key={number.toString()}>
{number}
</li>
);
단, 항목의 순서가 바뀔 수 있는 경우 key에 인덱스를 사용하는 것은 권장하지 않는다.
key는 주변 배열의 context에서만 의미가 있다.
map()
함수 내부에 있는 엘리먼트에 key를 넣어주면 된다.
function ListItem(props) {
// 여기에는 key를 지정할 필요가 없다.
return <li>{props.value}</li>;
}
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
// 배열 안에 key를 지정해야 한다.
<ListItem key={number.toString()} value={number} />
);
return (
<ul>
{listItems}
</ul>
);
}
const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
<NumberList numbers={numbers} />,
document.getElementById('root')
);
말 그대로다.