Toast Message
Toast Message
Toast Message는 모바일에서든 웹에서든 자주 볼 수 있는 notification 스타일입니다. velog에 글을 쓸 때도 자주 만나볼 수 있어요.
혼자 과제하는 시간이 길어지다보니 이런저런 기능들을 넣고 싶은 욕심이 생깁니다;
localStorage에 저장할 수 있는 아이템 수를 정해두고, 유저가 그 이상 저장을 시도할 경우 alert창이 뜨도록 해뒀는데 그게 왜 그렇게 안 예뻐보이는지...ㅜㅜ
그래서 Toast message를 만들어보기로 했습니다.
1. 컴포넌트 만들기
2개의 컴포넌트가 필요했습니다.
배열로 쌓이는 noti-list 상태관리를 해줄 notification과 Toast 컴포넌트입니다.
Toast.js는 사라졌는지 아닌지 상태관리만 두고 setInterval을 이용해 지정된 시간이 지나면 사라지도록 했습니다.
toast는 아래 객체를 받아 보여주도록 했습니다.
let noti = {
id,
type: 'success' or 'danger',
description,
dismissalTime
}
처음 noti가 뜰 때는 애니메이션을 줬습니다.
const Toast = ({ item }) => {
const [isFading, setIsFading] = useState(false);
useEffect(() => {
const interval = setInterval(() => {
setIsFading(true);
}, item.dismissalTime);
return () => {
clearInterval(interval);
};
}, [item.dismissalTime]);
return (
<ToastMessage isFading={isFading}>
{item.description}
</ToastMessage>
);
};
export default Toast;
const show = keyframes`
from {
transform: translateX(100%);
} to {
opacity: 1;
transform: translateX(0px);
}
`;
const ToastMessage = styled.div`
animation: ${show} 1.5s ease-in-out;
${(props) =>
props.isFading &&
css`
opacity: 0;
transform: opacity 1.5s ease-in-out;
`}
`;
Notification.js는 단순합니다.
props를 쌓아서 상태관리를 해주고, list 배열을 돌며 Toast message가 만들어지도록 했습니다.
const Notification = ({ notification }) => {
const [toastList, setToastList] = useState();
useEffect(() => {
setToastList([...notification]);
}, [notification]);
return (
<Notifications>
{toastList?.map((item, index) => (
<Toast key={index} item={item} onDelete={onDelete} />
))}
</Notifications>
);
};
2. 컴포넌트 연결하기
이벤트가 발생할 때에 맞게, 각 키에 값을 할당해 list에 넣어줍니다.
const onDeleteRepo = (repo) => {
...
...
let noti = {
id: id,
type: 'success',
description: 'Repository를 삭제했습니다.',
dismissalTime: 3000,
};
setNotification([...notification, noti]);
...
...
};
타입별로 배경색이 다르게 적용해줍니다.
<ToastMessage isFading={isFading} type={`${item.type}`}>
{item.description}
</ToastMessage>
const ToastMessage = styled.div`
....
...
background-color: ${(props) =>
props.type === 'success' ? '#5cb85c' : '#d9534f'};
...
`
3. 완성
notification ui만 변경했을 뿐인데 프로젝트가 갑자기 퀄리티가 올라간 느낌입니다.
다시 한 번 ui의 중요성을 느낍니다.
(추가) Redux
리덕스를 추가하면서 notification을 위한 별도의 reducer를 만들었습니다.
const initialState = { data: [] };
export const notiReducer = createSlice({
name: 'notifications',
initialState,
reducers: {
addNoti: (state, actions) => {
const { type, description, dismissalTime } = actions.payload;
let item = {
id: Date.now(),
type: type,
description: description,
dismissalTime: dismissalTime ? dismissalTime : 3000,
};
state.data = [...state.data, item];
},
},
});
Toast Message를 만들면서 제일 신경쓰였던 것은 notification item객체가 배열에 계속 쌓인다는 것이었습니다.
이렇게 되면 페이지를 이동했다가 다시 현재 페이지로 돌아왔을 때 아래 보이는 사진처럼 알림이 한꺼번에 브라우저에 등장합니다;
어떻게든 저 배열들을 지우고 싶다....
강력한 욕구가 샘솟았습니다.
1. 언제 어떻게 삭제하나
알림이 곧장 삭제되거나 제대로 삭제되지 않는다면, 사용자 입장에서 굉장히 부자연스러운 알람을 볼 수 밖에 없습니다.
처음엔 별 생각없이 배열이 5개 이상 쌓이면 삭제되도록 했는데, 아래 처럼 한꺼번에 삭제되는 알람을 볼 수 있었습니다.
2. Reducer에 삭제 기능 추가
배열이 6개가 되는 시점에 이전 배열 5개가 삭제되도록 리듀서를 추가했습니다.
clearNoti: (state) => {
state.data.splice(0, 6);
},
배열이 6개가 되는 시점에 앞서 5개의 배열이 삭제 되도록해뒀기 때문에 그 시간을 계산해 5개 알람이 모두 보여졌다가 사라진 시간 이후 배열이 삭제 되도록 함수를 추가했습니다.
const spliceArray = useCallback(() => {
setInterval(() => {
dispatch(clearNoti());
}, 18000);
}, [dispatch]);
useEffect(() => {
if (notification?.length > 5) {
spliceArray();
}
return () => {
clearInterval(spliceArray);
};
}, [notification, spliceArray]);
자연스러운 알람을 볼 수 있습니다.(만세)
Author And Source
이 문제에 관하여(Toast Message), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@hyejeong/Toast-Message저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)