Skip to content

outsideClick 이슈

LeeSuKyeong edited this page Dec 9, 2020 · 2 revisions

outSideClick을 구현하면서 있었던 이슈를 정리해보겠습니다.

1.

처음에는 dropdown button들의 상위 컴포넌트인 <StyleComponent.Attributes>에 ref를 걸어두어 outsideClick을 만들려고 했습니다.
해당 컴포넌트 외 클릭 시 드롭다운이 close되지만, 다른 dropdown 버튼을 클릭하면 같은 드롭다운이라고 인식되어 outsideClick이 동작하지 않는 문제가 발생했습니다.

2.

문제 해결을 위해 각각의 버튼에 ref를 주어 outsideClick을 구현하기로 결정했습니다.
각 컴포넌트마다 useEffect와 outsideClick function을 구현해서 동작되는 것을 확인했습니다.
그리고 해당 부분이 중복적으로 계속 작성해야했기 때문에 outsideClick이라는 훅을 만들어 재사용하도록 했습니다.
아래는 작성한 파일입니다.

//hooks/outsideClick.ts

import { useEffect, MutableRefObject } from 'react';
import { useDispatch } from 'react-redux';

//참조하는 component, 해당 드롭다운의 state, outside click 시 줄 action을 파라미터로 넘겨주었습니다.
const outsideClick = (
  ref: MutableRefObject<HTMLDivElement>,
  state: boolean,
  action: any
) => {
  const dispatch = useDispatch();
  const click = (e: MouseEvent) => {
    //ref component가 click한 event target을 포함하지 않고, dropdown 상태가 열려있으면 close action을 dispatch해줍니다.
    if (ref && !ref.current.contains(e.target as Element)) {
      if (state) dispatch(action());
    }
  };
  useEffect(() => {
    document.addEventListener('click', click);
    return () => {
      document.removeEventListener('click', click);
    };
  });
};
export default outsideClick;

3.

outside click 시 정상적으로 작동하는 것을 확인했습니다.
다만, 그림판 드롭다운의 경우 닫겨서는 안되기 때문에 별도의 처리를 해야했고, 이 과정에서 그림판 드롭다운과 다른 드롭다운이 함께 켜져있는 상태에서 outsideClick 시 두 개다 close되는 이슈를 발견했습니다.

원인은 store/modules에 있는 각 리듀서의 action type들이 겹쳐있기 때문이었습니다.
별도의 파일에서 작성한 createAction하여 호출했음에도 같은 action으로 인식하여 함께 닫겼습니다.
action type 선언 시 접두로사로 파일명을 붙인 '파일명/CLOSE'로 변경했더니 해당 문제를 해결할 수 있었습니다.

ex)

// drawerDropdown.ts
//ACTION TYPE
const CLOSE = 'CLOSE';
// 액션 생성자로 생성 자동화
export const closeDropdown = createAction(CLOSE);
//리듀서
export const drawerDropdownHandler = handleActions(
 {
   [CLOSE]: (state = initialState) => {
      return { ...state, isDropdownShow: false };
   },
 }
)

// fontColorDropdown.ts
const CLOSE = 'CLOSE';
export const closeDropdown = createAction(CLOSE);
export const fontColorDropdownHandler = handleActions(
  {
    [CLOSE]: (state: State) => {
      return { ...state, isActive: false };
    },
  },
  initialState
);

위와 같이 선언되어있을 때, outSideClick을 발생시키면 outSideClick 내 click function에서 dispatch(fontColorDropdown.closeDropdown())를 발생시킵니다.
이 때, action type 명이 CLOSE로 같아서 fontColorDropdown의 closeDropdown을 실행했음에도 drawDropdown의 closeDropdown도 발생하게 됩니다.

ACTION TYPE 문제해결

앞서 말했듯이, ACTION TYPE 앞에 접두어를 붙여 다른 ACTION으로 인식하여 문제를 해결합니다.

EX)

// drawerDropdown.ts
//ACTION TYPE
const CLOSE = 'drawerDropdown/CLOSE';

// fontColorDropdown.ts
const CLOSE = 'fontColorDropdown/CLOSE';

참고:redux

🤝 Rules

🤖 개발 진행 공유

🧑‍🏫 학습 정리

📖 Document

😄데일리 스크럼
😄일일 회의록
😄주간 회고록

🗣 피어세션

🔥 트러블 슈팅

Clone this wiki locally