sonner 라이브러리로 Toast 기능 만들기

루비·2024년 9월 23일
0

shadcn-ui

목록 보기
1/1

서론

기존에 유저의 액션의 성공/실패 여부를 빠르게 만들기 위해서 Alert로 사용하였다. 그래서 이번에 시간이 남았을 때, Alert 기능 대신 Toast 기능을 사용하려고 하였다.

현재 어드민 페이지는, shadcn-ui의 디자인을 따라갔다. 그리고 애니메이션의 라이브러리는 아직 도입하지 않았던 상태이다.

프로덕션에서는 Toast를 만들었기 때문에, 그 기능을 그대로 가져오려고 하였다.

Toast에 대해서 구글링을 검색하였는데, 한 레딧에서 Toast UI vs sonner을 투표하였다. 그 결과 sonner이 거의 5.5~6으로 이겼어서, 나는 인터넷에 npm i sonner를 검색하였다.

생각보다 많은 다운로드 수를 기록해있고, 공식 홈페이지에서 찾아보니, 내가 필요했던 기능들로 구성되어있어서 이것을 사용하기를 결심하였다.

본론

npx shadcn@latest add sonner

shadcn에서 sonner을 제공함으로 나는 위의 방식대로 다운로드하였다.

npm i sonner

다음과 같은 방법으로도 다운로드가 가능하다.

Layout(app) 상단에

import { Toaster } from "@/components/ui/sonner"
 
export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <head />
      <body>
        <main>{children}</main>
        <Toaster />
      </body>
    </html>
  )
}

sonner은 크게, Toast의 디자인을 꾸며주는 Toaster와 실제 Toast의 기능적인 부분을 담당하는 toast로 구성된다.

그리고 꼭 상단 layout.tsx 파일에 <Toaster />을 입력해야한다.
만약 위와 같이 진행하지 않고, component 안마다 <Toaster />을 작성한다면,

  1. Toast 사용 시 UI가 버벅 거림의 렌더링
  2. <SignInForm /> 컴포넌트에서 성공/실패 시 <Toaster />를 부르고, 성공했을 때<Dashboard /> 컴포넌트로 넘어가게 된다면, dulation을 무시하고, 페이지가 넘어가지면, <Toaster />의 UI가 없어지게 된다.

그래서 반드시 제일 app.tsx 혹은 layout.tsx 페이지 안에 작성해야한다.

useToast의 기능을 만들기

sonner 라이브러리의 사용 방법은 다음과 같다.

// 성공
toast.success("Success")

// 실패
toast.error("Error")

// 경고
toast.warning("Warning")

// 정보
toast.info("Info") 

...

sonner 문서

나는 성공/실패/경고/정보의 타입 유형만 사용하고, 이것을 useToast()hooks를 통해서 관리해주는 것이 좋아보였다.

그래서 useToast() 훅을 만들었다.

import { toast } form "sonner";

interface IToast {
	message: string;
    type?: "success" | "error" | "warning" | "info"
}

export const useToast() => {
	const addToast = ({ messgage, type = "success" } : IToast => {
    	if ( type === "success" ) toast.success(message);
        if ( type === "error" ) toast.error(message);
        if ( type === "warning" ) toast.warning(message);
        if ( type === "info ) toast.info(message);
    }
    
    return { addToast } 
}
// switch 문 
export const useToast = () => {
	const addToast = ({ message, type = "success" }: IToast) => {
		switch (type) {
			case "error":
				toast.error(message);
				break;
			case "warning":
				toast.warning(message);
				break;
			case "info":
				toast.info(message);
				break;
			default:
				toast.success(message); // default fallback
				break;
		}
	};

	return { addToast };
};

if 문으로 뺐는데, case문이 더 적합할 것 같다. 내일 case 문으로 수정해서 배포해야겠다.

스타일 적용하기

layout파일에는 모두 Component로 구성되어 있는 걸 선호하여서 <Toaster />의 스타일을 적용하기 위해서 <Toast /> 컴포넌트를 만들었다.

import { Toaster } from 'sonner'; 

export const Toast = () => {
	return (
    	<Toaster /> 
    )
}

이 때 richColors의 속성을 적용하면, toast를 구성하는 type (예: 성공/실패/경고/정보) 별로의 색상들이 지정된다.

그리고 맨 위 그리고 가운데에 Toast의 위치를 설정해주고 싶어서 position="top-center"duration={1500}로 설정했다.

import { Toaster } from "sonner"

export const Toast = () => {
	return (
    	<Toaster richColors position="top-center" duration={1500} /> 
    )
}

으로 설정하였다.

	...
    const { addToast } = useToast(); 
    ...
  	onSuccess: () => {
      addToast({
        message: "Event has been created",
      });
    },
   ...

위와 같은 방식으로 편하게 사용하면 된다.

결과

그러면 쉽게 Toast 를 만들 수 있다. 끝.

profile
개발훠훠

0개의 댓글