1 - 10, 11. 이벤트 핸들러 써보기

msg016·2022년 6월 19일
0

React lecture

목록 보기
7/8
패스트캠퍼스 '한 번에 끝내는 React의 모든 것' 수강 후 정리.

이벤트

HTML 이벤트란 브라우저가 무언가 행동하거나, 유저가 행동하는 것이다.
마우스를 클릭하거나 키보드를 누르는 등 사용자의 행위에 대해 발생할 수도 있고, HTML 문서의 로드가 완료되는 등 브라우저에서 발생할 수도 있다. 또는 JS 코드를 통해 프로그래밍 적으로도 발생시킬 수도 있다.

작성한 어플리케이션이 특정 이벤트에 대해 반응하여 정해진 동작을 수행하고 싶다면, 해당 이벤트가 발생했을 때 호출될 함수를 브라우저에게 알려 호출을 위임한다. 이 때 호출될 함수를 이벤트 핸들러라고 한다.

바닐라 JS에서 이벤트 핸들러 등록은 3가지 방식으로 이뤄질 수 있다.

  1. 이벤트 핸들러 어트리뷰트 방식
    Html 요소의 어트리뷰트 중에는 이벤트에 대응하는 이벤트 핸들러 어트리뷰트가 있다.
    onclick과 같이 on 접두사와 이벤트 타입으로 이뤄져 있으며, 해당 값으로 함수 참조가 아닌 함수 호출문 등의 문을 할당하는 것이 특징이다.

    <button onclick="sayHi('kim')">Click!</button> 
    <script>
      function sayHi(name) {
        console.log(`Hi! ${name}.`);
      }
    </script>
  2. 이벤트 핸들러 프로퍼티 방식
    window 객체와 Document, HTMLElement 타입의 DOM 노드 객체는 이벤트에 대응하는 핸들러 프로퍼티를 가지고 있다. 어트리뷰트와 동일하게 on 접두사가 붙은 이벤트 타입으로 이뤄져 있으며, 해당 프로퍼티에 함수를 바인딩하면 이벤트 핸들러가 등록된다.
    하나의 프로퍼티에 하나의 이벤트 핸들러만 등록가능한 단점이 있다.

    <button>Click!</button> 
    <script>
      const $button = document.querySelector('button');
      
    	$button.onclick = function() {
      	console.log('button clicked 1');
      }
      
      $button.onclick = function() {
      	console.log('button clicked 2');
      }
    </script>

    위의 경우 두 번째로 바인딩된 이벤트 핸들러만 실행되어 'button clicked 2'만 콘솔에 출력된다.

  3. addEventListener 메서드 방식
    EventTarget.prototype.addEventListener 메서드를 사용하여 이벤트 핸들러를 등록한다.

    <button>Click!</button> 
    <script>
      const $button = document.querySelector('button');
      
      $button.addEventListener('click', function() {
      	console.log('button clicked');
      })
    </script>

    메서드의 첫 번째 인자로 이벤트 타입을 전달하며, 이전과 달리 on 접두사가 붙지 않는다.
    두 번째 인자는 이벤트 핸들러를, 마지막 매개변수는 capture 사용 여부를 지정한다.(생략가능)
    이 방식은 이벤트 핸들러 프로퍼티 방식과 동시에 등록될 경우 모든 이벤트가 호출되며, 동일한 HTML 요소에서 발생한 동일 이벤트에 대해 하나 이상의 핸들러를 등록할 수 있다. 이 경우 등록 된 순서대로 호출된다.

리액트의 이벤트

리액트가 이벤트를 처리하는 방식은 DOM 엘리먼트의 처리방식과 유사하지만 약간 다르다.
리액트의 이벤트는 카멜 케이스를 사용하며, addEventListener를 사용하지 않고 핸들러를 전달한다.

<script type="text/babel">
  const $root = document.getElementById("root");
  const $button = <button onClick={() => alert("pressed")}>Press</button>;

  ReactDOM.render($button, $root);
</script>

button 엘리먼트를 생성할 때 JSX 내에 onclick이 아닌 onClick에 이벤트 핸들러를 전달하였다.
아래와 같이 전달 될 핸들러를 별개의 함수로 분리할 수 있다.

const handleClick = () => alert("pressed");

const $root = document.getElementById("root");
const $button = <button onClick={handleClick}>Press</button>;

ReactDOM.render($button, $root);

응용

<script type="text/babel">
  const $root = document.getElementById("root");
  const state = { keyword: "", typing: false, result: "" };

  const App = () => {
    function handleChange(e) {
      setState({ keyword: e.target.value, typing: true });
    }

    function handleClick() {
      setState({
        typing: false,
        result: `We find result of ${state.keyword}`
      });
    }

    return (
      <>
        <input onChange={handleChange} />
        <button onClick={handleClick}>Search</button>
        <p>
          {state.typing
            ? `Looking for ${state.keyword}...`
            : `${state.result}`}
        </p>
      </>
    );
  };

  function setState(newState) {
    Object.assign(state, newState);
    render();
  }

  function render() {
    ReactDOM.render(<App />, $root);
  }

  render();
</script>

위의 코드가 실행되면 입력 창 하나와 Search가 적힌 버튼이 생성된다.
입력창에 검색어를 입력하면 'looking for ...'이라는 글자가 표시되며, 검색 버튼을 클릭하면 'We find result of ...' 메세지가 출력된다.

신경써야 할 부분은 전역변수 state를 활용하여 상황에 따라 출력되는 내용을 달리하기 위한 상태를 관리하는 점, setState 함수를 정의하여 state의 변경에 불변성을 유지한 점, render 함수를 정의하여 상태가 변경될 때마다 다시 렌더링하도록 호출된 점이다.

profile
프론트엔드 개발자 지망생

0개의 댓글