본문 바로가기
개발이야기/React

[React] 이벤트 핸들링 HTML과 비교

by dev.josh 2022. 11. 10.
반응형
리액트가 만들어주는 가상DOM Element와 HTML DOM Element 에서 사용되는 이벤트 핸들러의 사용법을 비교해 보았다.

 

 

1. onClick 이벤트

 

HTML

<button onClick='htmlHandleClick()'>HTML onClick</button>
function htmlHandleClick() {
   console.log('You clicked onClick.');
}

일반적인 함수 호출형 방식

 

React

<button onClick={handleClick}>React onClick</button>
function handleClick() {
  console.log('You clicked onClick.');
}

리액트에서는 onClick={ } 안에서 자바스크립트 함수를 동작시킬 수 있는데, 함수 선언 으로 

함수의 이름으로 연결해 주는 방식을 사용한다. 만약 onClick={ handleClick() } 처럼 함수 호출식으로 사용하게 되면 해당 컴포넌트가 로드 될때 함수가 바로 실행되버리게 된다..

  

 

 

2. 이벤트 전파 방지

from태그에서 submit이벤트를 발생시키면 페이지가 새로고침이 발생된다. 아래 예제에서는 submit이벤트를 발생시키지만 원치 않은 새로고침은 이벤트는 발생시키지 않게 테스트 해보았다.

 

HTML

<form onSubmit='htmlHandleSubmit(event)'>
   <button type="submit">HTML onSubmit 1</button>
</form>
<form id='form'>
   <button type="submit">HTML onSubmit 2</button>
</form>
function htmlHandleSubmit(e) {
   e.preventDefault();
   console.log('You clicked submit 1.'); 
}
document.getElementById('form').onsubmit = () => {
   console.log('You clicked submit 2.'); 
   return false;
}

HTML onSubmit 1 버튼에서 event를 인자값으로 넘겨 preventDefault() 함수를 실행시킨다.

preventDefault()는 함께 실행되는 이벤트를 방지하는 역할을 수행하는데, 해당 함수에서는 새로고침이 발생되지 않는다.

preventDefault는 사용될 경우가 많았는데 예를들면 onClick 이벤트를 가진 부모와 자식 엘리먼트가 겹쳐 있을때, 자식 엘리먼트를 Click하여 이벤트를 발생시키려고 하면 부모영역에도 해당되어 의도치않게 부모이벤트도 함께 발생된다.

preventDefault()를 자식 엘리먼트에서 사용하면 자식의 이벤트는 실행되나, 부모로 전파되는 이벤트는 막을 수 있다. 

 

HTML onSubmit 2 버튼 에서는 form 태그에 id값으로 onsubmit이벤트를 등록 시켜주는 방식으로 함수를 선언 해주었는데, 여기서는 이벤트 동작 후에, return false로 이벤트 전파를 막을수 있다.

 

React

<form onSubmit={handleSubmit}>
   <button type="submit">React onSubmit 1</button>
</form>
function handleSubmit(e) {
   e.preventDefault();
   console.log('You clicked submit 1.'); 
}

리액트 에서는 함수 연결 방식에서 기본적으로 이벤트값을 인자로 넘겨주는것을 확인 할수있다.

 

 

3. toggle 동작과 변수 랜더링

 

HTML

<button onClick='htmlHandleToggle()'>
   HTML Toggle <span id="toggleStatus">Off</span>
</button>
let isToggleOn = false;
let toggleStatus = document.getElementById('toggleStatus');

function htmlHandleToggle() {
   console.log('You clicked toggle.'); 
   isToggleOn = !isToggleOn;
   if(isToggleOn) toggleStatus.innerText = 'On';
   else  toggleStatus.innerText = 'Off';
}

 

React

<button onClick={toggleClick}>
   React Toggle {isToggleOn ? 'ON' : 'OFF'}
</button>
const [isToggleOn, setIsToggleOn] = React.useState(false);

function toggleClick() {
   console.log('You clicked toggle.'); 
   setIsToggleOn(!isToggleOn);
}

 

4. 인자값 전달

 

HTML

<button onClick='htmlHandleArgument(event)'>HTML Argument</button>
function htmlHandleArgument(event) {
   console.log('You clicked argument.'); 
   console.log(event);
}

콘솔로그로 이벤트를 찍어보면 아래와 같다.

HTML의 이벤트 객체

 

React

<button onClick={(event) => argument(event)}>React Argument 1</button>
<button onClick={argument.bind(event)}>React Argument 2</button>
function argument(event) {
   console.log('You clicked argument.'); 
   console.log(event);
}

콘솔로그로 이벤트를 찍어보면 아래와 같다.

리액트의 이벤트 객체

이벤트값을 콘솔로그로 찍어보면 HTML과 다른 이벤트 객체를 확인 할수 있는데, 리액트가 만들어주는 이벤트값은 HTML이벤트값을 토대로 만들어 주기때문에 서로 다른 이벤트객체 이지만, 이벤트 핸들링의 관점에서는 같다고 생각한다.

(이벤트 객체만의 차이점이라고 본다면 HTML은 DOM tree가 함께 보이는데, SPA의 가상 DOM 접근 방식과는 컨셉 자체가 다름으로 본 게시물에서는 다루지 않겠다...)

 

React Argument 1 버튼 처럼 인자 전달을 위해서 화살표 함수로써 이벤트 인자를 전달 할 수있고,

React Argument 2 버튼 처럼 자바스크립트의 bind() 함수를 사용함으로써 컴포넌트 로드와 동시에 이벤트를 발생 시키지않고 인자값을 넘겨 줄 수 있었다. 

1.onClick 이벤트 에서 함수호출 문제점도 해결된다.

 

 

전체소스

<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
  <container class="js-area">
    <h3>HTML Events</h3>
    <section class="button-group">
      <button onClick='htmlHandleClick()'>HTML onClick</button>
      <form onSubmit='htmlHandleSubmit(event)'>
        <button type="submit">HTML onSubmit 1</button>
      </form>
      <form id='form'>
        <button type="submit">HTML onSubmit 2</button>
      </form>
      <button onClick='htmlHandleToggle()'>HTML Toggle <span id="toggleStatus">Off</span></button>
      <button onClick='htmlHandleArgument(event)'>HTML Argument</button>
    </section>
  </container>

  <script>
    let isToggleOn = false;
    let toggleStatus = document.getElementById('toggleStatus');
    function htmlHandleClick() {
      console.log('You clicked onClick.');
    }
    function htmlHandleSubmit(e) {
      console.log(e);
      e.preventDefault();
      console.log('You clicked submit 1.'); 
    }
    document.getElementById('form').onsubmit = () => {
      console.log('You clicked submit 2.'); 
      return false;
    }
    function htmlHandleToggle() {
      console.log('You clicked toggle.'); 
      isToggleOn = !isToggleOn;
      if(isToggleOn) toggleStatus.innerText = 'On';
      else  toggleStatus.innerText = 'Off';
    }
    function htmlHandleArgument(event) {
      console.log('You clicked argument.'); 
      console.log(event);
    }
  </script>

  <div id="root" class="react-area"></div>
  <script type="text/babel">
    const App = () => {
      const [isToggleOn, setIsToggleOn] = React.useState(false);
      function handleClick() {
        console.log('You clicked onClick.');
      }
      function handleSubmit(e) {
        console.log(e);
        e.preventDefault();
        console.log('You clicked submit 1.'); 
      }
      function handleSubmit2(e) {
        e.preventDefault();
        console.log('You clicked submit 2.'); 
      }
      function toggleClick() {
        console.log('You clicked toggle.'); 
        setIsToggleOn(!isToggleOn);
      }
      function argument(event) {
        console.log('You clicked argument.'); 
        console.log(event);
      }

      return (
        <>
        <h3>React Events</h3>
          <section className="button-group">
            <button onClick={handleClick}>React onClick</button>
            <form onSubmit={handleSubmit}>
              <button type="submit">React onSubmit 1</button>
            </form>
            <form onSubmit={handleSubmit2}>
              <button type="submit">React onSubmit 2</button>
            </form>
            <button onClick={toggleClick}>
              React Toggle {isToggleOn ? 'ON' : 'OFF'}
            </button>
            <button onClick={(event) => argument(event)}>React Argument 1</button>
            <button onClick={argument.bind(event)}>React Argument 2</button>
          </section>
        </>
      );
    }

    const root = document.getElementById('root');
    ReactDOM.createRoot(root).render(<App/>);
  </script>
  <style>
    h3 {
      display: block;
      width: 100%;
      text-align: center;
    }
    .js-area {
      display: flex;
      border: 1px solid red;
      margin-bottom: 5px;
      align-items: flex-start;
      justify-content: center;
      flex-wrap: wrap;
      min-width: 1200px;
    }
    .react-area {
      display: flex;
      border: 1px solid blue;
      margin-bottom: 5px;
      align-items: flex-start;
      justify-content: center;
      flex-wrap: wrap;
      min-width: 1200px;
    }
    .button-group {
      display: flex;
      margin: auto;
      width: 1000px;
      justify-content: flex-start;
    }
    button {
      margin: 2rem;
      margin: 1rem;
      min-width: 150px;
      height: 40px;
    }
  </style>
</body>
</html>

 

참고

https://ko.reactjs.org/docs/handling-events.html

 

이벤트 처리하기 – React

A JavaScript library for building user interfaces

ko.reactjs.org

 

반응형

'개발이야기 > React' 카테고리의 다른 글

[React] 사진첩 게시판  (0) 2023.01.04