2차 프로젝트에서 팀 프로젝트로 진행한 에어비앤비 웹사이트는 검색형식의 네브바를 가지고 있는데 라우터가 넘어갈 때마다 검색바의 값들을 유지해주는 것이 중요했다.
프로젝트를 진행할 적에는 router 객체의 state 부분에 필요한 위치, 체크인 아웃 날짜, 게스트 인원 수를 담아서 라우터가 넘어감에 따라 상태 값을 꺼내오는 방법을 택했는데 라우터 url에 따라 상태 값에 조건을 달아주는 것이 번거롭고 또 상태가 변경되면 다시 다음 url로 상태를 넘겨주는 작업이 필요하기에 전역에서 상태를 관리해주는 게 편하겠다 생각하게 되어 리팩토링으로 작업하게 되었다
검색 바 컴포넌트에서 검색바에 들어가는 위치, 체크인 아웃 날짜, 게스트 수를 상태관리 하였다. url에 따라 메인에서 리스트 페이지로 넘어가는 경우 라우터 props 중 state에 담긴 이전 상태 값을 꺼내와서 보여주는 방법을 택했다.
this.state = {
currentTab: 0,
startDate:
this.props.location.pathname === '/list'
? moment(this.props.location.state.startDate)
: null,
endDate:
this.props.location.pathname === '/list'
? moment(this.props.location.state.endDate)
: null,
focusedInput: null,
adult:
this.props.location.pathname === '/list'
? this.props.location.state.adult
: 0,
child:
this.props.location.pathname === '/list'
? this.props.location.state.child
: 0,
kid:
this.props.location.pathname === '/list'
? this.props.location.state.kid
: 0,
searchList: [],
searchInputValue:
this.props.location.pathname === '/list'
? this.props.location.state.searchVal
: '',
};
}
메인에서 리스트 페이지로 넘어가게 해주는버튼 클릭 이벤트 함수 내에 체크인아웃 날짜가 있는 경우와 없는 경우를 나뉘어서 pathname이 리스트페이지의 url인 경우 상태 프로퍼티에 검색바에 들어가게 될 상태들을 넣어서 같이 보냈다.
const goToList = () => {
if (startDate && endDate) {
props.history.push({
pathname: '/list',
state: {
startDate: startDate._d,
endDate: endDate._d,
longitude: searchList.filter(list => list.gu === searchInputValue)[0]
.longitude,
latitude: searchList.filter(list => list.gu === searchInputValue)[0]
.latitude,
adult: guestQty.adult,
child: guestQty.child,
kid: guestQty.kid,
searchVal: searchInputValue,
},
});
} else {
props.history.push({
pathname: '/list',
state: {
startDate: new Date('14 / 02 / 2021'),
endDate: new Date('06 / 02 / 2021'),
longitude: searchList.filter(list => list.gu === searchInputValue)[0]
.longitude,
latitude: searchList.filter(list => list.gu === searchInputValue)[0]
.latitude,
adult: guestQty.adult,
child: guestQty.child,
kid: guestQty.kid,
searchVal: searchInputValue,
},
});
}
};
전역 상태관리 툴로는 리덕스를 적용하였다. 이벤트가 일어날 부분을 액션으로 구분해주고 어떻게 상태를 업데이트 해줄 것인가에 대해 리듀서에서 정의해주었다.
//액션
export const locationSearchValAction = val => {
return {
type: 'LOCATION_SEARCH_VAL',
payload: val,
};
};
export const setKidQtyAction = () => {
return {
type: 'KID_QTY',
};
};
export const plusGuestQtyAction = selected => {
return {
type: 'PLUS_GUEST',
payload: selected,
};
};
export const minusGuestQtyAction = selected => {
return {
type: 'MINUS_GUEST',
payload: selected,
};
};
//게스트 상태관리 리듀서
const initState = {
adult: 0,
child: 0,
kid: 0,
};
export const guestQtyReducer = (state = initState, action) => {
switch (action.type) {
case 'KID_QTY':
return {
...state,
adult: state.adult + 1,
kid: state.kid + 1,
};
case 'PLUS_GUEST':
return {
...state,
[action.payload]: state[action.payload] + 1,
};
case 'MINUS_GUEST':
return {
...state,
[action.payload]: state[action.payload] - 1,
};
default:
return state;
}
};
컴포넌트에서 전역 상태 가져오는 방법으론 useSelector()훅을 사용하고 업데이트는 useDispatch()훅을 사용하여 액션을 넣어주었다.
//redux 적용 부분
const searchInputValue = useSelector(state => state.locationValReducer);
const guestQty = useSelector(state => state.guestQtyReducer);
const dispatch = useDispatch();
//위치 상태를 업데이트하는 방법
const selectLocation = selected => {
dispatch(locationSearchValAction(selected));
setCurrentTab(0);
};
url이 바뀌는 것과 상관 없이 네브바의 검색 상태 값들은 그대로 유지된다!
1. 리스트페이지 화면
2. 상세 페이지 화면