프로젝트 구현 영상 : https://www.youtube.com/watch?v=3sZc05pvuCY
그런데 한가지 고민이 생겼다. "Nav바 상태나 회원정보는 쭉 유지하는게 어떨까?"라는 것이다.(위에서 해당 페이지를 알려주는 파란 밑줄도 Redux가 관리하는 값이다.)
1차 프로젝트 때도 했던 고민인데 보통 사이트들은 로그인을 하면 그 로그인 정보를 가지고 페이지가 변해도 가지고 있는다.
물론 페이지 이동 후 그때 그때 토큰값으로 계속 다시 회원정보를 받을 수 있을 것이다.
그러나 component가 언마운트되고 마운트 되는 라이프사이클을 고민하면서 하다보면 뭔가 Nav나 컴포넌트들이 의도치않게 리로드될 수 있다.
그렇다고 페이지마다 Nav로 모든 컴포넌트들을 다 감싸고 시작한다?
여러 개발자가 협업하는 상황에서 시간에 쫒기며 개발하는 상황에서 조금이라도 서로 약속이 틀어지면 원하는 방향으로 될 것 같지않았다.
그래서 난 이번에 배운 Redux가 해결책이라고 생각하였다.
navPick에 따른 색상변화를 위한 state,
로그인 유무에 따른 한페이지에서도 다르게 보여주는 것을 위한 state,
어느페이지에서건 로그인modal을 온오프 시켜줄 state,
로그인종류(google, facebook, 일반)에 따른 다른 로그인, 아웃 로직이지만 유저에게는 하나의 버튼으로 보이게 하기 위한 state.
//store/actions/index.js
// nav메뉴 클릭시 blue underline action
export const changeNavColor = pick => {
return {
type:"nav_pick",
payload: pick
}
}
// 로그인 action
export const changeLogin = check => {
return {
type:"login_check",
payload:check
}
}
// 로그인 종류에 따른 action
export const kindLogin = kind => {
return {
type:"login_kind",
payload:kind
}
}
// modal창 들어갔나 나오게할 action
export const changeModal = onoff => {
return {
type:"modal_onoff",
payload:onoff
}
}
// profile창 updown하게 할 action
export const changeProfile = updown => {
return {
type:"profile_updown",
payload:updown
}
}
최초에 이메일을 입력받고 비회원이면 회원가입으로, 회원이면 password를 묻는단계로 이루어져 있다. 모든 단계가 modal로 이루어져 있으며 그렇기에 어떤 페이지에서든 nav를 통해 modal을 띄웠다가 off할 수 있다.
즉, 글로벌하다는 뜻이다. 그렇기에 또한 store로 관리하도록 하였다.
// modal 발생시 백그라운드에 추가되는 것
useEffect(() => {
modalOnoff ? window.document.body.style.overflowY="hidden" : window.document.body.style.overflowY="scroll"
}, [modalOnoff]);
const ModalBackground = styled.div`
position:${props => props.modal?"fixed":""};
display:${props => props.modal?"":"none"};
opacity:${props => props.modal?"0.5":"0"};
z-index:${props => props.modal?"10000":"-1"};
top:0px;
width:100%;
height:100vh;
background-color:black;
`;
const ModalVisible = styled.div`
position:${props => props.modal?"fixed":""};
display:${props => props.modal?"":"none"};
opacity:${props => props.modal?"1":"0"};
z-index:${props => props.modal?"20000":"-1"};
display:${props => props.isView===0?"":"none"};
background-color:white;
top: 50%;
left: 50%;
width: 400px;
height: calc(100vh - 150px);
transform: translate(-50%, -50%);
border-radius: 5px;
overflow-y: scroll;
`;
const CvPage = ( { loginCheck, history } ) => {
//로그인 상태에 따라 보여줄 정보를 바꿀 state
const [isLogin, setLogin] = useState(false)
//각각의 토글기능 온오프를 위한 토클 state
const [isToggle, setToggle] = useState(0)
//로그인 상태에 따라 최초 정보를 위한 useEffect
useEffect(() => {
loginCheck?setLogin(true):setLogin(false)
}, [loginCheck])
//페이지 이동시 시작은 항상 scroll 재일 위니까!
useEffect(() => {
document.documentElement.scrollTop=0;
}, [])
///// map mothod 부분
return (
<>
{data.resume && data.resume.map((item, inx) => {
return (
<Cover>
<BoxWrap>
<InnerBox key={inx}>
<HeaderWarp onClick={() =>{moveDetailFunc(item.id); props.setToggle(0);}}>
<NameIng color={validation(item.intro)}>{item.title}</NameIng>
<DateSpan>{(item.updated_at).substring(0, 10)}</DateSpan>
</HeaderWarp>
<TextIng color={validation(item.intro)}>
<NonClickBox onClick={() => {moveDetailFunc(item.id); props.setToggle(0);}} color={validation(item.intro)}><span>{validation(item.intro)}</span></NonClickBox>
<ClickBox onClick={() => props.isToggle !== item.id ? props.setToggle(item.id) : props.setToggle(0)}><MdMoreVert/></ClickBox>
</TextIng>
</InnerBox>
</BoxWrap>
<UserCvListToggle index={item.id} isToggle={props.isToggle} getFunc={getFunc}/>
</Cover>
)
})}
</>
)
}
///토글부분 컴포넌트
<ToggleBox isToggle={props.isToggle} index={props.index}>
<ul>
<li onClick={() => props.getFunc}>이름 변경</li>
<li>다운로드</li>
<li onClick={deleteFunc}>삭제</li>
</ul>
</ToggleBox>
// 이력서페이지 최상위
<Nav/>
<Cv>
//비회원일시 보여주는 컴포넌트
<NonUser isLogin={isLogin}>
</NonUser>
//회원일시 보여주는 컴포넌트
<UserContents isLogin={isLogin}>
//모든 토글을 끄게 할 리스트 뒤에 깔릴 백그라운드
<Background onClick={() => setToggle(0)}/>
</UserContents>
</Cv>
<Footer/>
리엑트는 재밌다. 아니 프론트 엔드는 재밌다. 너무나도 재밌었다.
생각대로 만들어지는 것을 볼때는 너무나 즐거웠다.
또한 새로운 기술(스타일 컴포넌트나 훅, 리덕스)을 사용하니 배울 때는 힘들었지만 그 뿌듯함은 더욱 높다.
javascript는 더욱 깊게.!
더 나아가 typescript 등을 새롭게 공부할 것이다.