6.5 reselect 패키지로 선택자 함수 만들기
- 원본 데이터를 다양한 형태로 가공해서 사용할 수 있게 도와줌
- 리덕스 데이터를 리액트 컴포넌트에서 필요한 데이터로 가공하는 용도로 많이 사용
export const getTodoList = createSelector(getTodos, (todos) =>
todos.todoList.filter((todo) => !todo.isCompleted)
);
- createSelector를 사용하여 매개변수로 들어온 getTodos 값이 변하지 않으면 계산을 수행하지 않는다.
- 메모제이션 기능을 이용하여 이전값과 비교하여 변경되면 변경된값을 연산을 수행하고 아닌 경우 이전값을 그대로 사용한다.
- 상태값 외에도 속성값을 입력 받을 수 있다.
<FriendMain ageLimit={30} />
<FriendMain ageLimit={15} />
// FriendMain
export default function FriendMain({ ageLimit }) {
const friendsWithAgeLimit = useSelector(state =>
getFriendsWithAgeLimit(state, ageLimit)
);
}
- 위에서
ageLimit={30}
과 ageLimit={15}
에서는 reselect 의 메모제이션 기능이 제대로 동작하지 않는다.
- 렌더링 될 때마다 두 인스턴스는 같은 선택자 함수를 다른 속성값으로 호출한다.
- reselect 는 이전 결과값을 저장했다가 비교하는 역할을 해주는데 reselect 입장에서는 30과 15의 값이 들어오게 되고 이중 어느 값이 변경되는지 판단을 못하는 것 같다.
- 이를 방지하기 위해서 각 컴포넌트 인스턴스별로 독립된 메모제이션 기능을 제공하기 위해 reselect 함수도 여러 인스턴스로 만들어 줘야한다.
export const makeGetFriendsWithAgeLimit = (0 => {
return createSelector([getFriends, getAgeLimit]), (friends, ageLimit) =>
friends.filter(friend => friend.age <= ageLimit)
});
export default function FriendMain({ ageLimit }) {
const getFriendsWitchAgeLimit = useMemo(makeGetFriendsWithAgeLimit, []);
const friendsWithAgeLimit = useSelector(state =>
getFriendsWithAgeLimit(state, ageLimit))
};
- useMemo를 이용해 각 함수의 주소값을 고정한 후 개별적인 reselect 메모제이션 기능을 사용한다.