내외부 구분, onBlur on react

broccoli·2021년 7월 2일
5

react

목록 보기
1/1
post-thumbnail

작업환경

  • next@10.1.3
  • react@17.0.3

1. react에서 내외부 구분방법

// jsx
...
<Backdrop onClick={onLeaveFocusLogin}>
  <Modal ref={loginBox}>
    <Cover>
	 ...
    </Cover>
  </Modal>
</Backdrop>

위와 같이 구분할 엘리먼트에 ref를 걸고 바깥쪽에 해당하는 박스에 onClick
을 바인딩한다. 이후 아래와 같이 boolean으로 타겟이 구분엘리먼트 안쪽인지 바깥쪽인지 구분해서 바깥쪽이면 원하는 엘리먼트 컨트롤을 종료하면 된다.

// jsx
  const onLeaveFocusLogin = useCallback((e) => {
    if (!loginBox.current) return
    if (!loginBox.current.contains(e.target)) {
      onCloseLogin()
    }
  }, [])

2. onBlur on react

2번글의 원래 목적은 input 엘리먼트의 focus/blur의 대한 목적이 아닌 컨트롤내부와 외부를 구분해서 외부를 클릭시 컨트롤을 종료하는 방법을 작성하기 위해 썼는 것이다. 현재 더 쉬운 방식으로 내부와 외부를 구분하는 방법을 알게됬음. 그래서 원래 목적이었던 내외부 구분하는 것을 위해서라면 2번방식이 아닌 위에 1번 방식을 사용하는 것이 맞다. 2번은 그냥 onBlur가 어떤 순서로 이벤트가 진행되는지까지만 확인하는 것으로 이해하도록 하자.

2-1. focus 이벤트 작업

Focus관련해서 일반적으로 js에서는 focusin, focusout이벤트가 있고 별도로 blur관련이벤트가 있다. 하지만 react에서는 onFocus, onBlur 두가지만 있다. 따라서 포커스가 떠남을 표현하고자 할 때는 onBlur를 사용해야한다. 참고로 onBlur를 사용할 때는 tabIndex속성을 같이 사용해줘야 onBlur이벤트가 트리거되다.

onBlur 이벤트는 onClick이벤트와 같이 사용하게 될 시 순서가 꼬일수있다.

아래 이미지는 콤보박스이다. 콤보박스의 헤더부분을 클릭하면 아래 리스트가 열리고 다시 헤더를 클릭하면 리스트가 닫힌다.

  • 콤보박스 이외의 부분을 클릭하게될 때 리스트가 역시 닫히길 원한다면 onBlur이벤트로 처리할 수 있다.
  • 리스트를 클릭하면 리스트아이템에 해당하는 핸들러가 동작하고 리스트가 닫혀야한다.

하지만 만약 리스트아이템의 핸들러를 onClick으로 받는다면 리스트아이템의 핸들러가 동작하기전에 onBlur에 의해 리스트가 닫힌다.

이벤트 진행순서 onBlur -> onClick

따라서 onClickonMouseDown으로 변경하면 해결된다.

이벤트 진행순서 onMouseDown -> onBlur -> onClick

2-2. 참고 예

<Container>
  <DisplayItem
    tabIndex={0}
    onClick={onShowListItems}
    onBlur={onLeaveFocusComboBox}
  >
    <span>{selectedItem.displayName}</span>
  </DisplayItem>
  <>
    {isShowList && (
      <DisplayList>
        {itemsSource.map((item) => (
          <Item
            onMouseDown={onSelectedItem(item)}
            isSelected={getIsSelected(item)}
          >
            {item.displayName}
          </Item>
        ))}
      </DisplayList>
    )}
  </>
</Container>

참고링크

profile
🌃브로콜리한 개발자🌟

1개의 댓글

comment-user-thumbnail
2022년 12월 20일

덕분에 1시간동안 고민하던 문제를 해결 할 수 있었습니다, 감사합니다 👍🏻

답글 달기