const Category = () => {
const { category } = useParams();
const categoriesMap = useSelector(selectCategoriesMap)
const [products, setProducts] = useState(categoriesMap[category]);
useEffect(() => {
setProducts(categoriesMap[category]);
}, [category, categoriesMap]);
category 컴포넌트가 렌더링될 때, 위 사진에서 보듯 SET_CURRENT_USER가 category 컴포넌트를 리렌더링 시킨다.
왜 그럴까?
export const rootReducer = combineReducers({
user: userReducer,
categories: categoriesReducer,
});
rootReducer에서 user나 categories 둘 중 하나의 reducer라도 업데이트 될 시, 전체 store object가 새로운 object로 업데이트 되기 때문.
useSelector은 redux store 내장 훅이기 때문에, action이 들어오면 refire 된다.
const categoriesMap = useSelector(selectCategoriesMap)
컴포넌트가 렌더링 될 때 useSelector도 실행되는데, useSelector가 selectCategoriesMap function을 사실상 캐싱하고 있지 못한다.
export const selectCategoriesMap = (state) => {
return state.categories.categories.reduce((acc, category) => {
const { title, items } = category;
acc[title.toLowerCase()] = items;
return acc;
}, {});
};
따라서 selectCategoriesMap함수가 매 렌더링 때마다 새로 실행된다. 즉 categoriesMap은 매 렌더링 때마다 새로 계산되어 생성된다 => 메모리 낭비!
categories가 변할 때에만 selector function이 실행됐으면 좋겠다.