React로 토스트 알람(Toast Notification) Provider 만들어보기

김종식·2023년 1월 12일
1
post-thumbnail


위 사진에서 UI를 담당하는 Notification Component가 아니라 이를 구현하기 위한 Provider를 만들 예정이다.

필요한 기능들은 아래와 같다.
1. 토스트기능
2. Auto dismiss on/off 기능
3. dismiss ms 설정 기능
4. success,alert,info 3가지 종류

라이브러리는 안쓸 수 있으면 최대한 안쓰기로 마음먹었기에 별다른 토스트 라이브러리를 사용하지 않고 직접 구현하였다.

먼저 기본적으로 필요한 Type들을 정의해준다.

자동으로 Notification가 닫히는 시간을 5초로 정의하였으며 Auto Dismiss유무는 True로 정의하였다. 이 값은 사용자가 Option값을 넣지 않았을때의 기본값이다.

이후 Notification을 Provide하기 위한 Context를 선언해주며 Provider 함수를 만들어준다. 이는 프로젝트의 최상단에서 Notification을 각 페이지에 Provide할 예정이다.

추가적으로 단순한 Notification가 아닌 토스트 기능이 추가된 Notification이기에 이를 렌더하기 위한 NotiList state를 내부적으로 정의해주었다.

이후 각 페이지에서 실행하기 위한 ShowNoti함수를 구현하였다.
이 함수에서는 먼저 Notification을 close하기 위해 프로젝트 여기저기서 사용중인 cryptoRandomString 라이브러리를 사용하여 노티의 id를 생성하여 바인딩해주며 ms,autoDismiss옵션이 따로 정의되지 않았을경우 위에서 정의한대로 기본 값으로 설정해 주었다.

이후 렌더를 위해 notiList state의 맨 뒷부분에 Notification 노드를 추가해주며 autoDismiss옵션이 True일 경우 설정한 시간에 맞게 close해주도록 설정해주었다.

이는 추후

와 같이 사용될 예정이다.

이후 아래의 사진처럼 Notification의 close부분에 대한 함수를 구현하였다.

여기서 일반적인경우엔 destroyNoti만 존재해도 상관 없지만
close animation이 존재하는 Notification이기에 animation 실행을 위해 따로 show라는 값을 Notification에 추가하여 Notification Component 내부적으로 이 값의 변경 유무에 따라 애니메이션을 실행하며 애니메이션이 완료되면 nodeList state에서 id와 일치하는 noti를 destroy하도록 구현해주었다.

closeNoti는 유저가 혹은 autoDismiss에 의해 Notification이 종료되게되면 실행되어 해당하는 id의 Notification의 show 값을 false로 바꿔주어 종료 애니메이션을 실행시켜주는 역할을 한다.

destroyNoti는 애니메이션 종료 이후 자동으로 해당되는 id의 Notification을 필터링해주며 이는 유저가 건들일이 없는 함수이다.


잦은 rerender를 방지하기 위하여 useMemo로 Provide할 value값들을 감싸준다. (글을쓰다보니 이 부분에서는 감싸지 않더라도 감싼것과 다르지 않을 것 같다는 생각이 들었음.)


이후 위 사진과 같이 Provide해주면 토스트 Notification을 위한 Provider구현이 완료되게된다.

Provider 내부의 ul태그 부분 말고는 다른 부분을 rerender시키지 않는데 이는 React의 children의 특성 때문이다. 아마 다음 글에서 React의 re-render 조건들과 관련된 글을 작성할 것 같은데 거기에 들어갈 내용이 될 것 같다.

마지막으로

와 같이 useNoti hook을 따로 만들어준다. 이 때 NotiContext의 showNoti와 closeNoti는 Provider 함수가 실행되면 반드시 존재하므로 Type을 Required를 사용하여 변경하여준다.
이러면 구현이 완료되게 되며

이런식으로 사용할 수 있게된다.

profile
웹개발자 / 잘못된 정보에 대한 피드백은 언제나 환영입니다. ^^

0개의 댓글