이벤트에 응답하기
🎈 이벤트 핸들러 추가하기
이벤트 핸들러를 추가하려면 먼저 함수를 정의한 다음 이를 적절한 JSX 태그에 prop으로 전달합니다.
올바른 함수 전달 ⭕
<button onClick={handleClick}>
handleClick 함수가 onClick 이벤트 핸들러로 전달됩니다. 이렇게 하면 react가 이를 기억하고 사용자가 버튼을 클릭할 때만 함수를 호출하도록 지시합니다.
잘못된 함수 호출 ❌
<button onClick={handleClick()}>
handleClick()끝에 있는 ()은 클릭없이 렌더링 중에 즉시 함수를 실행합니다. 이는 JSX의 내부의 javascript가 바로 실행되기 때문입니다.
올바른 함수 전달 ⭕
<button onClick={() => alert('...')}>
이와 같이 인라인 코드를 전달하면 클릭시 실행되지 않고 컴포넌트가 렌더링될 때마다 실행됩니다.
이벤트 핸들러를 인라인으로 정의하려면 익명 함수로 감싸주세요
렌더링할 때마다 내부에서 코드를 실행하는 대신 나중에 로출할 함수를 생성합니다.
잘못된 함수 호출 ❌
<button onClick={alert('...')}>
🎈 이벤트 핸들러에서 props 읽기
이벤트 핸들러는 컴포넌트 내부에서 선언되기 때문에 컴포넌트의 props에 접근할 수 있습니다. 다음은 클릭하면 message prop과 함께 alert을 표시하는 버튼입니다.
function AlertButton({ message, children }) {
return (
<button onClick={() => alert(message)}>
{children}
</button>
);
}
export default function Toolbar() {
return (
<div>
<AlertButton message="Playing!">
Play Movie
</AlertButton>
<AlertButton message="Uploading!">
Upload Image
</AlertButton>
</div>
);
}
🎈 이벤트 핸들러를 props로 전달하기
가끔 부모 컴포넌트가 자식의 이벤트 핸들러를 지정하고 싶을 때가 있습니다. Button 컴포넌트를 사용하는 위치에 따라 버튼은 동영상을 재생하고 다른 버튼은 이미지를 업로드하는 등 서로 다른 기능을 실행하고 싶을 수 있습니다.
컴포넌트가 부모로부터 받는 prop을 이벤트 핸들러로 다음과 같이 전달합니다.
function Button({ onClick, children }) {
return (
<button onClick={onClick}>
{children}
</button>
);
}
function PlayButton({ movieName }) {
function handlePlayClick() {
alert(`Playing ${movieName}!`);
}
return (
<Button onClick={handlePlayClick}>
Play "{movieName}"
</Button>
);
}
function UploadButton() {
return (
<Button onClick={() => alert('Uploading!')}>
Upload Image
</Button>
);
}
export default function Toolbar() {
return (
<div>
<PlayButton movieName="Kiki's Delivery Service" />
<UploadButton />
</div>
);
}
여기서 Toolbar 컴포넌트는 playButton과 UploadButton을 렌더링합니다.
PlayButton은 handlePlayClick을 onClick prop으로 내부의 Button에 전달합니다.
마지막으로 Button 컴포넌트는 onClick이라는 prop을 받습니다. 해당 prop을 브라우저의 빌트인 <button>으로 직접 전달하며, onClick={onClick}을 사용합니다. 이는 클릭시 전달된 함수를 호출하도록 react에 지시합니다.
🎈이벤트 핸들러 props 이름 정하기
<button> 및 <div>와 같은 기본 제공 컴포넌트는 onClick과 같은 브라우저 이벤트 이름만 지원합니다. 하지만 자체 컴포넌트를 빌드할 때는 이벤트 핸들러 prop의 이름을 원하는 방식으로 지정할 수 있습니다.
관례상 이벤트 핸들러 props는 on으로 시작하고 그 뒤에 대문자가 와야 합니다.
예를 들어, Button 컴포넌트의 onClick prop은 onSmash로 호출할 수 있습니다.
function Button({ onSmash, children }) {
return (
<button onClick={onSmash}>
{children}
</button>
);
}
export default function App() {
return (
<div>
<Button onSmash={() => alert('Playing!')}>
Play Movie
</Button>
<Button onSmash={() => alert('Uploading!')}>
Upload Image
</Button>
</div>
);
}
이 예제에서 <button onClick={onSmash}> 는 브라우저 <button> (소문자)에 여전히 onClick이라는 prop이 필요하지만 사용자 정의 Button컴포넌트가 수신하는 prop이름은 사용자가 지정할 수 있음을 보여줍니다
🎈 이벤트 전파
이벤트 핸들러는 컴포넌트에 있을 수 있는 모든 하위 컴포넌트의 이벤트도 포착합니다. 이벤트가 트리 위로 버블 또는 전파되는 것을 이벤트가 발생한 곳에서 시작하여 트리 위로 올라간다고 합니다.
export default function Toolbar() {
return (
<div className="Toolbar" onClick={() => {
alert('You clicked on the toolbar!');
}}>
<button onClick={() => alert('Playing!')}>
Play Movie
</button>
<button onClick={() => alert('Uploading!')}>
Upload Image
</button>
</div>
);
}
두 버튼 중 하나를 클릭하면 해당 버튼의 onClick이 먼저 실행되고 그 다음에 부모 div의 onClick이 실행됩니다.
🎈 전파 중지하기
이벤트 핸들러는 이벤트 객체를 유일한 인수로 받습니다. 이것은 관례상 event를 의미하는 e라고 불립니다. 이 객체를 사용하여 이벤트에 대한 정보를 읽을 수 있습니다.
해당 이벤트 객체를 사용하면 전파를 중지할 수도 있습니다. 이벤트가 상위 컴포넌트에 도달하지 못하도록 하려면 아래 Button 컴포넌트처럼 e.stopPropagation()을 호출해야 합니다.
function Button({ onClick, children }) {
return (
<button onClick={e => {
e.stopPropagation();
onClick();
}}>
{children}
</button>
);
}
export default function Toolbar() {
return (
<div className="Toolbar" onClick={() => {
alert('You clicked on the toolbar!');
}}>
<Button onClick={() => alert('Playing!')}>
Play Movie
</Button>
<Button onClick={() => alert('Uploading!')}>
Upload Image
</Button>
</div>
);
}
버튼 클릭 -> react는 onClick 핸들러 호출-> 이벤트가 더이상 버블링되지 않도록 e.stopPropagation()을 호출-> Toolbar 컴포넌트에 전달된 props인 onClick 호출-> 경고 표시 -> 전파 중지
<div onClickCapture={() => { /* this runs first | 먼저 실행됨 */ }}>
<button onClick={e => e.stopPropagation()} />
<button onClick={e => e.stopPropagation()} />
</div>
드물게 전파 중지를 해도 하위 요소의 모든 이벤트가 포착되는 경우에 쓰임
🎈 전파의 대안으로 핸들러 전달하기
부모가 전달한 onClick prop을 호출하는 방식:
function Button({ onClick, children }) {
return (
<button onClick={e => {
e.stopPropagation();
onClick();
}}>
{children}
</button>
);
}
부모 onClick 이벤트 핸들러를 호출하기 전에 코드추가- 전파에 대한 대안을 제공합니다. 자식 컴포넌트가 이벤트를 처리하는 동시에 부모 컴포넌트가 몇 가지 추가동작을 지정할 수 있게 해줍니다.
🎈기본 동작 방지
export default function Signup() {
return (
<form onSubmit={() => alert('Submitting!')}>
<input />
<button>Send</button>
</form>
);
}
전체 페이지를 다시 로드함
export default function Signup() {
return (
<form onSubmit={e => {
e.preventDefault();
alert('Submitting!');
}}>
<input />
<button>Send</button>
</form>
);
}
e.preventDefault()를 호출하여 이런 일이 발생하지 않도록 함
▶️ e.stopPropagation() 은 위 태그에 연결된 이벤트 핸들러의 실행 중지
▶️e.preventDefault()는 해당 이벤트가 있는 몇가지 이벤트에 대해 기본 브라우저 동작 방지
- <button>과 같은 요소에 함수를 prop으로 전달하여 이벤트를 처리할 수 있습니다.
- 이벤트 핸들러는 호출이 아니라 전달해야 합니다! onClick={handleClick()}이 아니라 onClick={handleClick}입니다.
- 이벤트 핸들러 함수를 개별적으로 또는 인라인으로 정의할 수 있습니다.
- 이벤트 핸들러는 컴포넌트 내부에 정의되므로 props에 액세스할 수 있습니다.
- 부모에서 이벤트 핸들러를 선언하고 이를 자식에게 prop으로 전달할 수 있습니다.
- 이름을 지정하여 이벤트 핸들러 prop을 직접 정의할 수 있습니다.
- 이벤트는 위쪽으로 전파됩니다. 이를 방지하려면 첫 번째 인수에 e.stopPropagation()을 호출하세요.
- 이벤트에 원치 않는 기본 브라우저 동작이 있을 수 있습니다. 이를 방지하려면 e.preventDefault()를 호출하세요.
- 자식 핸들러에서 이벤트 핸들러 prop을 명시적으로 호출하는 것은 전파에 대한 좋은 대안입니다.
'react.js' 카테고리의 다른 글
| react 공식문서로 학습하기 - state로 입력에 반응하기 (0) | 2023.11.30 |
|---|---|
| react 공식문서 학습- Updating Objects in State (1) | 2023.11.28 |
| 한입 크기로 잘라 먹는 리액트 - props (0) | 2023.10.07 |
| 한입 크기로 잘라 먹는 리액트 - State (0) | 2023.10.07 |
| 한입 크기로 잘라 먹는 리액트- jsx (0) | 2023.10.06 |