로그인 성공시 혹은 protectedRouter에 인증되지 않은 유저가 접근할 경우 그냥 바로 홈화면으로 이동하게 되는데, '로그인에 성공하셨습니다!'라든가 '회원만 접근 가능합니다!'라는 글자를 보여주는 게 더 사용자 경험에 좋을 거란 생각이 들었다.
MUI 홈페이지에서 snackbar랑 alert를 보면서 뭐가 더 좋은거지 고민을 했다. 그리고 이런 snackbar, modal 같은 디자인적인 용어(?)들에 대해 잘 정리해놓은 글이 있어서 한 번 더 참고하면 좋겠다는 생각을 했다.
사실 하루면 다 만들 줄 알았는데, 하루를 꼬박 넘기게 되었다.
원래는 toastSlice 하나로 메세지 여러개 활용하려고 했는데, 메세지 활용은커녕 snackbar 자체가 아예 화면에 나오지도 않아서 무척 당황했다.
//src/store/slice/toastSlice.ts
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
const initialState = {
isOpen: false,
};
const toastSlice = createSlice({
name: 'toast',
initialState,
reducers: {
openToast: (state) => {
state.isOpen = true;
// state.message = action.payload;
},
closeToast: (state) => {
state.isOpen = false;
},
},
});
export const { openToast, closeToast } = toastSlice.actions;
export default toastSlice.reducer;
혹시 내가 redux 코드를 잘못 만들었나 싶어서, 다 콘솔로 찍어봐도 계속 state.isOpen은 true로 나오는데 왜 화면에 안나오지?????
얼마나 간단한 문제이면, 이 문제에 대해 검색해봐도 딱히 나오는 답도 없었다...ㅠㅠ
답답한 나머지, 일단은 그냥 전부 다 state로 만들어져있던 예제코드를 발견해 사용해봤다.
const SignInForm = () => {
const {
register,
handleSubmit,
formState: { errors },
getValues,
reset,
} = useForm<FormData>({ mode: 'onChange' });
const [showSnackbar, setShowSnackbar] = useState(false);
const onOpenClickHandler = () => {
setShowSnackbar(true);
};
const onCloseClickHandler = (event) => {
setShowSnackbar(false);
};
const CustomSnackbar = (props) => (
<Snackbar
autoHideDuration={1500}
open={showSnackbar}
onClose={onCloseClickHandler}
anchorOrigin={{ horizontal: 'center', vertical: 'top' }}
children={props.children}
></Snackbar>
);
const onSubmit = (data: FormData) => {
const userData = {
email: data.email,
password: data.password,
};
loginUser(userData)
.then((response) => {
reset();
onOpenClickHandler();
setCookie('accessToken', response['accessToken'], { path: '/' });
// navigate('/');
// dispatch(openToast('로그인함!'));
})
.catch((err) => console.log(err));
};
return (
<S.SignInContainer onSubmit={handleSubmit(onSubmit)}>
<S.LoginText>Login</S.LoginText>
<S.SignInWrapper>
(로그인, 비밀번호 입력 폼 생략)
</S.SignInWrapper>
{showSnackbar && (
<CustomSnackbar>
<Alert severity='success'>로그인에 성공했습니다!</Alert>
</CustomSnackbar>
)}
</S.SignInContainer>
);
};
export default SignInForm;
잘 작동했다.
그럼 그냥 이제 저것을 slice에 넣고, snackbar는 컴포넌트로 빼면 되겠구나 싶어 코드를 수정해보았더니 이제 잘 작동한다!!

아니 근데 대체 뭐가 문제였던거지 하고 다시 살펴보니
Snackbar에 onClose 속성이 required인지 몰라서 헤맸고, 함수명으로 적어야되는지 몰라서 이후에도 좀 더 시간이 걸렸다.
이전에 onClose를 넣었을땐 함수명을 넣지 않고 dispatch(closeToast)이런식으로 넣었기 때문에 당연히 화면에 안 나타났던 것...ㅠ_ㅠ

이번 일을 통해 내가 실수한 점을 생각해봤는데,
첫째로는, 공식문서를 보긴 봤는데 snackbar에 대한 간단한 소개글(?) 같은 section만 보고 있었다는 것이다.

저길 볼 게 아니라 제일 하단에 API에 들어가서 snackbar에 관련된 모든 props, classes가 기재된 docs를 봤어야 했다.

docs를 보면 onClose에 관한 내용이 있는데, 떡하니 func을 적으면 된다고 나와있다. 근데 required인 속성인줄 몰라서 이걸 계속 열어만 두고 있었던 것이다. 잘 읽어보면 open prop을 제어할 수 있다고 나온다^^

오늘의 일기: 어쨌든 끝났다아ㅏ.....
