일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 깃허브 레포지토리와 로컬 코드 연결하기
- 배포
- 프론트엔드개발자양성과정
- 스나이퍼팩토리
- 유데미
- 디지털취업
- kdt
- 개발자교육과정
- `
- DIGITALHANARO
- 버전생성프로세스
- 프론트엔드배포
- Next.js
- 디지털교육
- udemy
- 백틱
- 맥북백틱입력
- s3
- 부트캠프
- 네이버로그인창만들기
- 미래내일일경험
- 웅진씽크빅
- 디지털하나로입학식
- github
- 프로젝트캠프
- 하나은행
- 취준생
- 디지털하나로
- 맥북백틱
- Today
- Total
Land of Joe
Link와 useNavigate의 활용도 차이 (Link태그 내 이벤트 존재 시 이벤트 작동 안 함 문제 해결을 위한 useNavigate 활용) 본문
Link와 useNavigate의 활용도 차이 (Link태그 내 이벤트 존재 시 이벤트 작동 안 함 문제 해결을 위한 useNavigate 활용)
Arendt 2024. 4. 18. 10:28
[ 내가 원하는 작동 방식 ]
회색 알람 아이템을 하나 누르면 그 아이템의 type에 해당하는 url로 이동한다.
그러나 알람 아이템 안의 DELETE 버튼을 누르면 url 이동이 아닌, deleteAlarmEvent 이벤트가 작동해야한다!
import React from "react";
import styled from "styled-components";
import { Span } from "../style/TextStyle";
import { Div, Article } from "../style/LayoutStyle";
import ImgTextBtnItem from "./ImgTextBtnItem";
import DeleteIcon from "../img/deleteIcon.svg";
import { useCookies } from "react-cookie";
import { Link } from "react-router-dom";
import TimeStampUtil from "../util/TimeStampUtil";
const NotificationListItem = (props) => {
const { idx, user_idx, type, post_idx, game_idx, created_at, post_title, game_title } =
props.data;
const [cookies] = useCookies(["token"]);
// (일반사용자) 알림 삭제하기 DELETE
const deleteAlarmEvent = async (event) => {
event.stopPropagation(); // 이벤트 캡쳐링 방지 (url 이동 막기 위함)
const response = await fetch(`${process.env.REACT_APP_API_KEY}/account/notification/${idx}`, {
method: "DELETE",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${cookies.token}`,
},
});
if (response.status === 200) {
window.location.reload();
}
if (response.status === 400) {
return alert("유효하지 않은 요청입니다.");
}
if (response.status === 401) {
return alert("권한이 없는 사용자입니다.");
}
if (response.status === 500) {
console.log("서버 내부 에러입니다.");
}
};
// 알림 내용과 URL 설정
let content, url;
if (type === 1) {
content = `사용자의 "${post_title}" 게시글에 새로운 댓글이 달렸습니다. 어서 확인해보세요~!`;
url = `/game/${game_idx}/post/${post_idx}`;
}
if (type === 2) {
content = `사용자가 작성했던 "${game_title}" 위키가 다른 사용자에 의해 수정되었습니다. 어떻게 바뀌었나 궁금하지 않으세요?`;
url = `/game/${game_idx}`;
}
if (type === 3) {
content = `요청하신 "${game_title}" 게임 생성이 거절되었습니다..ㅠㅠ `;
url = `./`;
}
return (
<Div $flex="v_start_start" $width="100%" $margin="70px 0 0 0">
{/* 알람 시각 */}
<Span $margin="0 0 10px 0">{TimeStampUtil(created_at)}</Span>
{/* 알람 내용, 알람 클릭 시 해당 url로 이동 */}
<MoveLink to={`${url}`}>
<BorderStyleArticle
$flex="h_between_center"
$width="100%"
$backgroundColor="lightGray"
$height="100px"
$padding="0 3%"
>
<Div>
<Span $fontWeight="bold">{content}</Span>
</Div>
<ImgTextBtnItem
img={DeleteIcon}
text="DELETE"
color="major"
backgroundColor="default"
onClick={(event) => deleteAlarmEvent(event, idx)}
/>
</BorderStyleArticle>
</MoveLink>
</Div>
);
};
export default NotificationListItem;
나는 <MoveLink to={`${url}`}></MoveLink>를 통해 알람 아이템을 감싸서
아이템의 어디를 클릭하든 해당 경로로 이동하도록 구현했었다.
그리고 이 Link 기능이 <ImgTextBtnItem /> 내 onClick 이벤트인 deleteAlarmEvent에 영향을 주지 않도록
이벤트 캡쳐링 방지를 위해 event.stopPropagation()을 적용했었다.
그러나 원하는 대로 되지 않았다.
[ 문제 상황 ]
DELETE 버튼을 눌러도 url 이동이 우선적으로 작동한다.
[ 해결 과정 ]
1. 백엔드 쪽 데이터베이스 내역을 실시간으로 확인하고,
또 url 이동이 이뤄졌다가 다시 알람 페이지로 돌아와 남아있는 알람 내역 확인을 통해
알람 삭제 API는 정상적으로 작동하고 있다는 사실을 파악했다.
2. 처음엔 이벤트 버블링/캡쳐링을 의심했다.
사실 이벤트 캡쳐링이라는 게 있는지도 몰랐다. '하나의 영역만 클릭했는데 다른 영역까지 이벤트 핸들러가 작동하는 것'이라는 정도로 '이벤트 버블링' 키워드만 알고있던 정도라 검색을 해보았고, 그 둘의 차이와 해결방법 등에 대해 알아볼 수 있었다.
그러한 이유로 deleteAlarmEvent 내에 event.stopPropagation()라는 이벤트 캡쳐링 방지 함수를 넣어보기도 했다.
* 이벤트 버블링: 이벤트가 타겟에서 시작해서 DOM트리를 타고 Window 객체까지 전파되는 현상(기본적으로 항상 발생)
* 이벤트 캡쳐링: 이벤트가 Window 객체에서 출발해서 DOM트리를 타고 타겟까지 전파되는 현상
* event.preventDefault(): 브라우저 기본 동작 취소
* event.stopPropation(): 그 다음 요소로의 전파 방지event.stopImmediatePropation()도 있음
그러나 원하는 대로 작동은 하지 않았고........
가만히 앉아 생각하다보니... React Router의 Link는 이벤트가 아니잖아!!!!!!!!!
[ 해결 방법 ]
기존에 회색 알람 아이템(<BorderStyleArticle/>) 전체를 <Link>로 감싸서 원하는 url로 이동시켰던 것과 다르게,
알람 아이템에 onClick 이벤트를 통해 useNavigate로 원하는 url로 이동하도록 하였다.
return (
<Div $flex="v_start_start" $width="100%" $margin="70px 0 0 0">
{/* 알람 시각 */}
<Span $margin="0 0 10px 0">{TimeStampUtil(created_at)}</Span>
{/* 알람 내용, 알람 클릭 시 해당 url로 이동 */}
<BorderStyleArticle
$flex="h_between_center"
$width="100%"
$backgroundColor="lightGray"
$height="100px"
$padding="0 3%"
onClick={(e) => moveURLEvent(e)}
>
<Div>
<Span $fontWeight="bold">{content}</Span>
</Div>
<ImgTextBtnItem
img={DeleteIcon}
text="DELETE"
color="major"
backgroundColor="default"
onClick={(event) => deleteAlarmEvent(event, idx)}
/>
</BorderStyleArticle>
</Div>
);
이렇게 하니 DELETE 버튼(deleteAlarmEvent)는 버튼대로, 페이지 이동은 페이지 이동대로
너무너무 잘 작동하는 것으로 해결 완~!~!
'🌐 Web > ⚛️ React' 카테고리의 다른 글
메모이제이션과 상태 관리 (useCallback, useMemo, React.memo, useReducer, ContextAPI) (0) | 2024.07.25 |
---|---|
리액트에서 로그인 처리하는 방법 (1) | 2024.07.23 |
CRA 생성 안됨 오류 Unknown command: "create-react-app" (0) | 2024.03.01 |
[react-redux] Actions must be plain objects. 오류 (0) | 2024.01.17 |
[React] CRA 내 파일 구성에 대한 개인적 고찰 (0) | 2024.01.13 |