개발자
류준열
훅, 컴포넌트 밖에서 사용가능한 toast 유틸 만들기
React에서 useToast()를 커스텀 훅으로 만들어쓰고 있었다.
const { addToast } = useToast(); addToast({ type: "success", content: "저장되었습니다!", });
그런데 이러한 방식은 axios intercepter하여 토큰 만료시 갱신 처리하는 곳 등 훅, 컴포넌트 외부에서는 toast를 사용할 수 없는 단점이 있다.
전역 toast 유틸 객체 만들기
// toast.ts
const toast = {
addToast: () => {
console.warn("ToastProvider가 아직 초기화되지 않았습니다.");
},
removeToast: () => {
console.warn("ToastProvider가 아직 초기화되지 않았습니다.");
},
_setFunctions(add, remove) {
this.addToast = add;
this.removeToast = remove;
},
};
export default toast;
이 toast 객체는 React 바깥에서도 접근 가능한 전역 싱글턴이다. 초기에는 아무 기능도 없지만, 나중에 ToastProvider가 마운트되면서 내부 함수가 주입된다.
ToastProvider안에서 함수 주입과 this 바인딩
toast._setFunctions = function(add, remove) {
this.addToast = add; // toast.addToast에 등록
this.removeToast = remove;
};
export const ToastProvider= ({...}:ToastProps) => {
...
const addToast = (...) => {...}
const removeToast =(...) => {...}
useEffect(() => {
toast._setFunctions(addToast, removeToast);
}, []);
...
}
function App(){
return (
<ToastProvider maxToasts={10}>...<AppRouter /> ... </ToastProvider>
toast._setFunction
는 this가 해당 객체(toast
)를 가리킨다. 덕분에 외부에서도 toast.addToast()
를 쓸 수 있게 된다.
this는 호출방식에 따라 바인딩되는 객체가 달라진다.
사용방식
// utils/handleError.ts
import toast from "@/utils/toast";
export function handleError(message: string) {
toast.addToast({
type: "delete",
content: `에러 발생: ${message}`,
options: { autoClose: true },
});
}
정리
React 커스텀 훅은 범위(scope)에 제한이 있다는 단점이 있다. 그 한계를 벗아나기 위해서는 this 바인딩을 활용한 전역 유틸 패턴을 사용하는 것이 좋은 해결책이 될 수 있다.
이런 패턴은 toast뿐 아니라, 전역 알림, 로딩 처리, 다이얼로그 관리등에도 확장할 수 있다.