[React] 이벤트 처리 - onClick(), useState

newsilver·2021년 12월 20일
8

React

목록 보기
6/7
post-thumbnail

delete 버튼을 누르면 모달 창을 띄우고, 모달 창 이외의 영역을 누르면 모달 창을 닫는 이벤트를 만들어보자.

React 이벤트 처리

이벤트 처리를 위한 컴포넌트 추가하기

Todo 컴포넌트 추가하기

Todo List 내용이 들어가는 Todo 컴포넌트를 생성하고, App.js에 추가한다.

App.js

function App() {
  return (
    <div className="App">
      <h1>To Do List</h1>
      <Todo text="React TDL"/>
      <Todo text="Upload velog" />
      <Todo text="Read Deep Dive" />
      <Todo text="Read Clean Code" />
    </div>
  );
}

Todo.js

function Todo(props) {
  return (
    <div className="card">
      <h2>{props.text}</h2>
      <div className="actions">
        <button className="btn">Delete</button>
      </div>
    </div>
  );
}

모달창과 배경 영역을 만들고 스타일을 적용한다.

Modal.js

function Modal(props) {
  return (
  <div className="modal">
    <p>Are you sure?</p>
    <button className="btn btn--alt">Cancel</button>
    <button className="btn">Confirm</button>
  </div>
  );
}

Backdrop.js

function Backdrop(props) {
  return <div className="backdrop" />;
}

App.js

function App() {
  return (
    <div className="App">
      <h1>To Do List</h1>
      <Todo text="React TDL"/>
      <Todo text="Upload velog" />
      <Todo text="Read Deep Dive" />
      <Todo text="Read Clean Code" />
      <Modal />		// Modal 컴포넌트 추가
      <Backdrop />	// Backdrop 컴포넌트 추가
    </div>
  );
}

App.js에 Modal과 Backdrop 컴포넌트를 추가한 화면이다.
delete 버튼을 눌렀을 때만 모달 창이 뜨게 만들고 싶다.

함수형 컴포넌트의 이벤트 처리

함수형 컴포넌트에서 이벤트를 처리하는 방법은 두 가지이다.

  1. 리액트 훅인 useEffect 에 이벤트 리스너를 위치시킨다.
  2. html 요소의 내부 onClick 속성을 사용한다.

두 번째 방법을 사용해서 이벤트를 처리해보자.
(첫 번째 방법은 useEffect만 정리할 때 추가할 예정이다.)

onClick 속성에 함수 전달

Todo.js

function deleteHandler() {
 console.log("Clicked");
}

<button className="btn" onClick={deleteHandler}>Delete</button>

onClick속성에 문자열이 아닌 함수 이름을 전달한다.

onClick="deleteHandler()" ❌

onClick={deleteHandler()} ❌
// 렌더링되는 시점에서 함수가 호출되어버린다.

onClick={deleteHandler} ⭕️

클릭 후 deleteHandler() 함수가 실행된 것을 확인할 수 있다.
클릭 이벤트를 감지하여 모달과 배경 창을 실행시켜보자.

useState

상태를 동적으로 관리하기

useState는 리액트의 Hooks 중 하나이다.
컴포넌트에서 보여줘야 하는 내용이 사용자 인터랙션에 따라 바뀌어야 할 때 사용한다.
리액트 16.8 이전 버전에서는 함수형 컴포넌트에서는 상태를 관리할 수 없었지만, 리액트 16.8 에서 Hooks 라는 기능이 도입되면서 함수형 컴포넌트에서도 상태를 관리할 수 있게 되었다.

Todo.js

import { useState } from './react';
// useState 불러오기

export default function Todo(props) {
  const [modalIsOpen, setModalState] = useState(false);
  // 비구조화 할당

useState를 사용 할 때에는 상태의 기본값을 파라미터로 넣어서 호출해준다. 반환 값은 배열이며, 첫번째 원소는 현재 상태, 두번째 원소는 Setter 함수다.
Setter 함수는 파라미터로 전달 받은 값을 최신 상태로 설정한다.

  function deleteHandler() {
    setModalState(true);
    // modalIsOpen을 true로 변경.
  }
  
  function closeModalHandler() {
    setModalState(false);
    // modalIsOpen을 false로 변경.
  }

  return (...)

이제 delete 버튼을 클릭했을 때 modalIsOpen이 true로 설정되어 Modal 컴포넌트를 열어야 한다.

{modalIsOpen ? <Modal />}
{modalIsOpen ? <Backdrop />}

이렇게 Modal과 Backdrop 컴포넌트를 렌더링할 수 있지만

{modalIsOpen && <Modal />}
{modalIsOpen && <Backdrop />}

&& 연산자를 사용하여 간단하게 작성할 수 있다.

App.js에서 추가했던 Modal과 Backdrop 컴포넌트를 지우고

Todo.js

import { useState } from './react';

export default function Todo(props) {
  const [modalIsOpen, setModalState] = useState(false);
  
  function deleteHandler() {
    setModalState(true);
  }
  
  function closeModalHandler() {
    setModalState(false);
  }

  return (
    <div className="card">
      <h2>{props.text}</h2>
      <div className="actions">
        <button className="btn" onClick={deleteHandler}>Delete</button>
      </div>
      {modalIsOpen && <Modal />}
      {modalIsOpen && <Backdrop />}
    </div>
  );
}


모달 창 닫는 이벤트 추가하기

Todo.js

{modalIsOpen && <Modal onCancel = {closeModalHandler} />}
{modalIsOpen && <Backdrop onCancel = {closeModalHandler}/>}

Modal.js

export default function Modal(props) {
  function cancelHandler() {
    props.onCancel();
  }

  function confirmHandler() {
    props.onConfirm();
  }

  return (
  <div className="modal">
    <p>Are you sure?</p>
    <button className="btn btn--alt" onClick={cancelHandler}>Cancel</button>
    <button className="btn" onClick={confirmHandler()}>Confirm</button>
  </div>
  );
}

Backdrop.js

export default function Backdrop(props) {
  return <div className="backdrop" onClick={props.onCancel}/>;
}

profile
이게 왜 🐷

0개의 댓글