컴포넌트에서 콜백 함수
- 콜백 함수란 정의된 위치에서 실행되지 않고, 이후 특정 상황에서 실행되는 함수를 말함
- 하위 컴포넌트에서 프로퍼티를 변경해야 할 때 프로퍼티 원본을 수정할 수 있는 함수를 하위 컴포넌트에 제공하면 됨
- 따라서, 콜백 함수를 프로퍼티로 전달하면 됨
- 콜백 함수로 프로퍼티 수정 :
(src/App.js)
└ App 컴포넌트에서 state로 관리하는 count 값을 변경할 수 있지만 Counter 컴포넌트에서는 변경할 수 없는 상태import React from 'react'; import Counter from './ex/Counter2'; class App extends React.Component { constructor(props) { super(props); this.state = { count: 1 }; } increase() { this.setState(({ count }) => ({ count: count + 1})); } render() { return ( <Counter count={this.state.count} /> ); } } export default App;
(src/App.js)
└ 위와 같이 increase() 함수를 프로퍼티 형태로 전달하면 count 값을 변경할 수 있음import React from 'react'; import Counter from './ex/Counter2'; class App extends React.Component { constructor(props) { super(props); this.state = { count: 1 }; } increase() { this.setState(({ count }) => ({ count: count + 1})); } render() { return ( <Counter count={this.state.count} onAdd={this.increase} /> ); } } export default App;
(src/ex/Counter.jsx)
import React from 'react'; import PropTypes from 'prop-types'; class Counter2 extends React.Component { render() { return ( <div> 현재 카운트: {this.props.count} <button onClick={() => this.props.onAdd()}>카운트 증가</button> </div> ); } } Counter2.propTypes = { count: PropTypes.number, onAdd: PropTypes.func }; export default Counter2;
결과 :
└ Counter2 컴포넌트에서 프로퍼티로 받아 실행한 onAdd() 함수에서 참조하는 this의 범위 때문에 오류가 발생함
└ onAdd() 함수에 구현되어 있는 this.setState()는 상위(App) 컴포넌트에 정의되어 있지만
하위(Counter2) 컴포넌트에서 실행되기 때문에 오류가 발생함
- bind() 함수로 this 범위 오류 해결
└ increase() 함수가 호출되는 this 범위가 App 컴포넌트에 묶여 제대로 동작함import React from 'react'; import Counter from './ex/Counter2'; class App extends React.Component { constructor(props) { super(props); this.state = { count: 1 }; } increase() { this.setState(({ count }) => ({ count: count + 1})); } render() { return ( <Counter count={this.state.count} onAdd={this.increase.bind(this)} /> ); } } export default App;
└ 이와 같이 bind() 함수는 constructor() 함수에 모아두면import React from 'react'; import Counter from './ex/Counter2'; class App extends React.Component { constructor(props) { super(props); this.increase = this.increase.bind(this); this.state = { count: 1 }; } increase() { this.setState(({ count }) => ({ count: count + 1})); } render() { return ( <Counter count={this.state.count} onAdd={this.increase} /> ); } } export default App;
매번 render() 함수를 호출할 때마다 새로 작성하지 않아도 됨
결과 :
- 컴포넌트에서 DOM 객체 함수 사용
- 컴포넌트에서 DOM 객체 함수를 사용하려면 DOM 객체를 컴포넌트 변수에 할당해야 함
- 이때 특수 프로퍼티인 ref를 사용함
- ref 프로퍼티는 document.getElementById()가 반환하는 객체를 반환함
- ref 프로퍼티는 DOM 객체 함수가 필요한 엘리멘트에 콜백 함수 형태로 전달됨
- 예시 :
└ 위 코드는 화면 스크롤이 변화할 때마다 객체 함수의 위치를 읽어 현재 위치가 화면 안인지 밖인지 측정함import React from 'react'; export default class Scroll extends React.PureComponent { constructor(props) { super(props); this.setRef = this.setRef.bind(this); this.checkPosition = this.checkPosition.bind(this); } setRef(ref) { this.ref = ref; // ⓐ } checkPosition() { if (this.ref.getBoundingClientRect().top < window.innerHeight) { // ⓑ console.log('enter'); } else { console.log('exit'); } } componentDidMount() { window.addEventListener('scroll', this.checkPosition); // ⓒ this.checkPosition(); } componentWillUnmount() { window.removeEventListener('scroll', this.checkPosition); // ⓓ } render() { return <div ref={this.setRef} /> } }
└ ⓐ : ref 프로퍼티에서 반환된 객체를 컴포넌트 변수에 할당했음
└ ⓑ : 현재 DOM 객체의 위치가 스크롤 화면 안인지 밖인지 측정하고 있음
└ ⓒ : 윈도우의 스크롤 이동 이벤트를 감지하여 checkPosition() 함수가 실행되도록 함
└ ⓓ : 컴포넌트가 소멸할 때 화면 스크롤 감시 함수를 메모리에서 제거함
- 컴포넌트에서 DOM 이벤트 사용
- 컴포넌트에서 출력된 특정 DOM 객체에 이벤트 컴포넌트가 반응하기 위해서는 DOM 이벤트 프로퍼티를 사용해야 함
- 이벤트 프로퍼티는 특수 프로퍼티로 콜백 함수 형태로 전달해 처리함
- HTML 엘리먼트의 이벤트들은 JSX 내에서 'on+이벤트명' 형태의 프로퍼티로 제공됨
- 자주 사용하는 DOM 이벤트 프로퍼티
이벤트 이름 이벤트 호출 시점 JSX DOM 이벤트 프로퍼티 submit 엘리먼트의 마우스나 키보드가 클릭될 때 onClick submit 폼의 데이터가 전송될 때 onSubmit mousemove 엘리먼트 위에서 마우스 커서가 움직일 때 onMouseMove mouseover 엘리먼트 영역 위로 마우스 커서가 돌아다닐 때 onMouseOver mouseout 엘리먼트 위에 있던 마우스 커서가 영역을 떠나갈 때 onMouseOut keydown 키보드 버튼이 눌렸을 때 onKeyDown keypress 키보드 버튼 입력이 완료되었을 때 onKeyPress
- 예시 (src/ex/Counter3) :
import React from 'react'; class Counter3 extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; this.increase = this.increase.bind(this); this.reset = this.reset.bind(this); } increase() { this.setState({ count: 0 }); } render() { return ( <div> 현재 카운트: {this.state.count} <button onClick = {this.increase} onMouseOut = {this.reset} >카운트 증가</button> 버튼 밖으로 커서가 움직일 시 0으로 초기화 </div> ); } }
- 결과 :
└ 버튼을 눌렀을 때 '카운트 증가'가 잘 작동됨
└ 만약 버튼 밖으로 마우스 커서를 움직일 경우 카운트가 초기화 됨
'React > Component' 카테고리의 다른 글
컴포넌트 (5) - 클래스형, 함수형, 배열 (0) | 2021.09.10 |
---|---|
컴포넌트(4) - 생명주기 (0) | 2021.09.08 |
컴포넌트(3) - 상태 관리 (0) | 2021.09.07 |
컴포넌트(2) - 프로퍼티 (0) | 2021.09.07 |
컴포넌트 (1) - JSX, 컴포넌트 (0) | 2021.08.31 |