리액트를 다루는 기술 4~6장 스터디
by ag-lee
4. 이벤트 핸들링
이벤트(event)
는 사용자가 웹 브라우저에서 동작하는 것을 의미한다.
4.1 리액트의 이벤트 시스템
리액트의 이벤트 시스템은 HTML의 이벤트를 작성하는 방식과 거의 동일하다.
import React, { useState } from 'react';
const Say = () => {
const [message, setMessage] = useState('');
const onClickEnter = () => setMessage('안녕하세요!');
const onClickLeave = () => setMessage('안녕히 가세요!');
const [color, setColor] = useState('black');
return (
<div>
<button onClick={onClickEnter}>입장</button>
<button onClick={onClickLeave}>퇴장</button>
</div>
)
}
이벤트를 사용할 때 주의 사항
- 이벤트 이름은 카멜 케이스로 작성한다.
- 이벤트에 실행할 자바스크립트 코드를 전달하는 게 아닌 함수를 전달한다.
- DOM 요소에만 이벤트를 설정할 수 있다. (직접 만든 컴포넌트에는 이벤트 핸들링 X -> props로 함수를 전달할 뿐이다,)
4.2 예제
handleChange = e => {
this.setState({
[e.target.name]: e.target.value
})
}
객체 내부에서 key를 [ ]
로 감싸면 안에 넣은 레퍼런스 값이 key로 사용가능하다.
(중심적인 내용은 아니지만, 몰랐던 사실이라서 기록!)
#5. ref:DOM에 이름 달기
React 내부에서 HTML DOM element의 id처럼 DOM에 이름을 다는 것을 ref
라고 한다.
리액트 컴포넌트 안에서는 id 값을 사용할 수는 있지만, 사용을 권장하지 않는다.
JSX 내부에서 DOM에 id를 달면 사용을 할 수는 있지만, id는 고유값이다. 컴포넌트를 반복적으로 사용하게 되는 경우는 그대로 id가 노출되기 때문에 id의 유일성이 깨지게 된다.
ref는 전역적으로 작동하지 않고, 컴포넌트 내부에서만 작동하므로 이런 문제를 해결할 수 있다.
5.1 ref를 사용해야하는 경우?
ref
는 DOM을 직접 건드려야할 때 사용해야한다. 리액트는 state를 사용해 기능 구현을 하기 때문에 필요한 상황들이 별로 없지만, 몇 가지는 DOM을 직접 건드려야지만 해결이 가능하다.
- 특정 input에 포커스 주기
- 스크롤박스 조작
- Canvas 요소에 그림그리기 등
5.2 ref 사용
콜백 함수를 통한 ref 설정
가장 기본적인 방법. ref라는 콜백함수를 props로 전달해 주고, ref 값을 파라미터로 받아 ref를 컴포넌트의 멤버 변수로 설정해준다. 앞으로 this.input
은 input 요소의 DOM을 가리키게 된다.
<input ref={ref => {this.input=ref}}
createRef를 통한 ref 설정
리액트에 내장되어 있는 createRef 함수를 사용한다. 컴포넌트 내부의 멤버변수에 React.createRef()
를 담아주고 ref를 달고자하는 요소에 ref props로 넣어주면 설정이 완료된다. 나중에 DOM에 접근하려면 this.input.current
로 접근한다. 콜백과는 다르게 `.current 를 붙여 접근한다.
import React, {Component} from 'react';
class RefSample extends Component {
input = React.createRef();
handleFocus = () => {
this.input.current.focus();
}
render() {
return (
<div>
<input ref={this.input} />
</div>
)
}
}
6. 컴포넌트 반복
자바스크립트 배열의 map()
함수
import React from 'react';
const IterationSample = () => {
const names = ['눈사람', '얼음', '눈', '바람'];
const nameList = names.map((name, idx) => <li key={idx}>{name}</li>);
return <ul>{nameList}</ul>
}
key
리액트에서는 key는 컴포넌트 배열을 렌더링했을 때 어떤 원소에 변동이 있었는지 알아내려고 사용한다. key가 없을 때는 Virtual DOM을 비교할 때 순차적으로 하지만, key가 있으면 이 값으로 어떤 변화가 일어났는지 더 빠르게 알 수 있다.
Key 값으로 사용할 값이 없는 경우 idx를 사용할 수 있지만, 비효율적이므로 되도록 고유값을 사용한다.
const articleList = articles.map(article => (
<Article
title={article.title}
writer={article.writer}
key={article.id}
/>
));
응용
업데이트 & 삭제
import React, { useState } from 'react';
const IterationSample = () => {
const [names, setNames] = useState([
{ id: 1, text: '눈사람' },
{ id: 2, text: '얼음' },
{ id: 3, text: '눈' },
{ id: 4, text: '바람' }
]);
const [inputText, setInputText] = useState('');
const [nextId, setNextId] = useState('5');
const onChange = e => setInputText(e.target.value);
const onClick = () => {
const nextNames = names.concat({
id: nextId,
text: inputText
});
setNextId(nextId + 1);
setNames(nextNames);
setInputText('');
};
const nameList = names.map(name => <li key={name.id}>{name.text}</li>);
return (
<>
<input value={inputText} onChange={onChange}></input>
<button onClick={onClick}>추가</button>
<ul>{nameList}</ul>
</>
);
}
- 불변성 유지 : 리액트에서 상태를 업데이트할 때는 기존 상태를 그대로 두면서 새로운 값을 상태로 설정해야한다. 이를 이용해 나중에 리액트 컴포넌트의 성능을 최적화할 수 있다. 때문에 배열에 element를 추가하는 대신,
concat
을 이용해 새로운 배열을 만들어 배열을 아예 변경해주었다.
리액트를 다루는 기술 요약 정리 https://book.naver.com/bookdb/book_detail.nhn?bid=15372757