yamoo9 / likelion-FEQA

질문/답변 — 프론트엔드 스쿨, 멋사
29 stars 9 forks source link

[LAB-13] 버튼 이벤트 관련 문제 #214

Closed ddengmin closed 1 year ago

ddengmin commented 1 year ago

질문 작성자

최영민

문제 상황

Mar-23-2023 21-25-51

이 프로그램을 찜하지 않았을 시 찜버튼을 누르면 모달창에 "찜했습니다" 라는 이벤트가 걸리고 이 프로그램을 찜했을 시 찜버튼을 다시 누르면 모달창에 "찜을 해제하였습니다" 이벤트를 걸려고 하는데. 모달페이지를만들고, usestate를 만들어 버튼 이벤트를 걸었는데 모달창에서 나가지지 않고 저창이 계속 유지가 되고 있는데 어디가 문제인지 몰라 질문드립니다. ㅠㅠ

프로젝트 저장소 URL

https://github.com/ddengmin/LAB13-PROJECT/tree/feature/youngmin/detailpage

feature/youngmin/detailpage 브랜치의 /src/component/detailpage입니다.

환경 정보

yamoo9 commented 1 year ago

문제 분석

문제 해결을 위해서는 리액트 Props를 사용한 컴포넌트 상태 공유 및 업데이트 방법에 대한 이해가 필요합니다. 그리고 모달 다이얼로그를 닫기 위한 이벤트 리스너(함수)와 닫기 버튼이 필요합니다.

문제 해결

리액트 Props 전달 방법으로 상위 ←→ 하위 컴포넌트 간 상태 공유 및 상태 업데이트 방법을 사용해야 합니다. React 공식 문서 Passing Event handlers as props을 참고하세요.

LikeButton.jsx

import { useState } from 'react';
import styles from './LikeButton.module.css';
import Modal from './Modal';

function Button() {
  const [isActive, setIsActive] = useState(false);
  const [isBookmarked, setIsBookmarked] = useState(false);

  const handleOpenModal = () => {
    setIsActive(true);
    setIsBookmarked(prevIsBookmarked => !prevIsBookmarked);
  };

  const handleCloseModal = ({ target, currentTarget }) => {
    if (target.localName === 'button' || target === currentTarget) {
      setIsActive(false);
    }
  };

  return (
    <>
      <button
        type="button"
        className={`${styles.button} ${isActive ? styles.active : ''}`}
        onClick={handleOpenModal}
      >
        {isBookmarked ? '찜 해제하기' : '찜 하기'}
      </button>
      {isActive && (
        <Modal onClose={handleCloseModal}>
          <p>이 아이템을 {isBookmarked ? '찜했습니다.' : '찜하시겠습니까?'}</p>
        </Modal>
      )}
    </>
  );
}

export default Button;

Modal.jsx

/* eslint-disable jsx-a11y/no-static-element-interactions */
/* eslint-disable jsx-a11y/click-events-have-key-events */

import PropTypes from 'prop-types';
import styles from './Modal.module.css';

function Modal({ children, onClose }) {
  return (
    <div className={styles.overlay} onClick={onClose}>
      <div className={styles.modal}>{children}</div>
      <button type="button">닫기</button>
    </div>
  );
}

Modal.propTypes = {
  children: PropTypes.node.isRequired,
  onClose: PropTypes.func.isRequired,
};

export default Modal;