redux를 사용하게 되면서 store의 state를 가져오기 위해 useSelector를 사용
하게 되었다.
하지만 문제는 아래의 방식으로 작성하면서 useSelector 내부에서 새로운 object를 생성하기 때문에 변했다고 인식하여 해당 컴포넌트가 리렌더링이 되어버린다.
useSelector hook은 엄격한
"===" 참조 비교
를 한다.
// reducer initialState
const initialState = {
location: '',
checkin: '',
checkout: '',
guestNum: {
adult: 0,
child: 0,
infant: 0,
},
};
// calendarContainer.js
const { checkin, checkout } = useSelector(state => ({
checkin: state.searchForm.checkin,
checkout: state.searchForm.checkout,
}));
불필요한 리렌더링이 되지 않도록 store의 state를 가져오는 방법은 크게 두가지가 있다.
const checkin = useSelector(state => state.searchForm.checkin);
const checkout = useSelector(state => state.searchForm.checkout);
독립적으로 불러오게 되면 값의 변화가 없을 때는 해당 컴포넌트는 리렌더링하지 않는다.
useSelector(selector: Function, equalityFn?: Function)
useSelector의 두번째 파라미터는 equalityFn자리이다.
equalityFn
을 이용하여 이전 값과 다음 값을 비교하여 리렌더링할지말지를 결정한다.
직접 equalityFn를 작성해도 되지만 react-redux에서 제공하는 shallowEqual 함수를 사용
해도 된다.
import { shallowEqual, useSelector } from 'react-redux';
const { checkin, checkout } = useSelector(
state => ({
checkin: state.searchForm.checkin,
checkout: state.searchForm.checkout,
}),
shallowEqual,
);
react-redux에서 제공하는 shallowEqual 함수는
깊은 객체까지는 비교해주지 못하기 때문
에 객체의 형태가 깊어진다면 다른 방식을 사용해야 한다.
기존의 속성은 최대한 유지하면서 반응형 웹으로 수정 중인데 grid 속성과 flex 속성을 이용하여 구현한 부분이 많아 크기를 줄여도 자연스럽게 줄여 줄 수 있었다.
다만, font-size같은 경우 px로 고정한 경우가 많아 나중에 반응형 작업을 위한 폰트 단위 em / rem으로 변경해야 할 것 같다.
em: 부모 태그의 영향을 받는 상대적인 길이
rem: 최상위 요소인 html요소에 비례하여 크기를 가지는 상대적인 길이
아래는 화면 해상도가 1128px일 때의 모습이다.