안녕하세요 펭귄 교수입니다.
리액트를 개발 중에 자꾸만 Warning이 떠서 이 부분을 해결하는 과정에 대해 글을 써보고자 합니다.
Warning 전문
Selector unknown returned a different result when called with the same parameters.
This can lead to unnecessary rerenders.
Selectors that return a new reference (such as an object or an array) should be memoized:
https://redux.js.org/usage/deriving-data-selectors#optimizing-selectors-with-memoization
번역하면 다음과 같습니다.
선택기를 알 수 없습니다. 동일한 매개 변수로 호출했을 때 다른 결과가 반환되었습니다.
이로 인해 불필요한 렌더링이 발생할 수 있습니다.
개체 또는 배열과 같이 새로운 참조를 반환하는 선택기는 메모해야 합니다:
Warning 분석
해당 Warning 은 redux에서 useSelector를 사용할 때 일어납니다.
정확히는 useSelector를 할 때 가져오는 데이터와 할당할 데이터의 매칭이 일치하지 않는다는 것입니다.
그렇다보니 데이터가 변경될 때 원하는 데이터가 아닌 다른 데이터가 변경 되어 불필요한 렌더링이 발생할 수 있음을 나타냅니다.
코드로 보면 다음과 같습니다.
// redux store
state = {
open: true,
state: {
sub_state_1: [1, 2, 3],
sub_state_2: [4, 5, 6]
}
};
// Component.js
const { state } = useSelector((state) => ({
state: state.state // state 값이 Dictionary 형태로 받다보니 이것은 1대1 매치로 보기 힘들다.
}));
해당 코드에서 sub_state 두 개를 모두 사용하는 상황일 수도 있지만, sub_state_1만을 사용하는 상황이라 가정했을 때
sub_state_2가 변경되었을 때도 해당 컴포넌트가 렌더링이 되기에, 이러한 상황이 비효율적인 자원 소모를 할 수 있다는 것입니다.
해결
두 가지 방법이 있습니다.
해결 방법 1
직관적으로 1대 1 매치를 시켜주는 겁니다.
// redux store
state = {
open: true,
state: {
sub_state_1: [1, 2, 3],
sub_state_2: [4, 5, 6]
}
};
// Component.js
const { sub_state_1, sub_state_2 } = useSelector((state) => ({
sub_state_1: state.state.sub_state_1,
sub_state_2: state.state.sub_state_2,
}));
이러한 방식으로 재렌더링 되는 상황을 막을 수 있습니다.
해결 방법 2
shallowEqual 를 사용하는 방법입니다.
코드로 먼저 보여드리겠습니다.
// Component.js
import { useSelector, shallowEquals } from 'react-redux';
const { state } = useSelector((state) => ({
state: state.state
}), shallowEquals); // 두 번째 인자로 shallEquals 를 넣어준다.
shallowEquals 의 기능은 다음과 같습니다.
const a = { foo: "bar" }
const b = { foo: "bar" }
console.log( a === b ) // will log false
console.log( shallowEquals(a, b)) // will log true
기본적으로 Object를 사용하는 언어들은 같은 값을 저장하는 객체더라도 Equal 연산에서는 서로 다른 메모리를 할당하고 있기에 False를 출력합니다.
shallowEquals, 말 그대로 얕은 등가라는 뜻으로 값만을 비교해서 객체에 Equal 연산을 한다고 보면 되겠습니다.
마무리
이렇게 두 방법을 통해 해당 Warning을 해결할 수 있습니다.
프로그래밍을 공부함에 있어서 중요한 것은 에러를 분석하고, 해결하는 과정에서
단순히 코드 복붙이 아닌, 왜 에러가 났으며, 이러한 방법은 왜 해결할 수 있는 지를 이해하는 것이 중요해보입니다.
참조
'프로그래밍 > Error' 카테고리의 다른 글
[Scoop Error] Couldn't find manifest for 'adopt8-hotspot'. (0) | 2024.10.30 |
---|---|
[티스토리 스킨 버그] 카테고리의 다른 글 두 개 표시, 해결 방법 (1) | 2024.09.27 |
pymysql Error : (1366, "Incorrect string value: '\\xED\\x83\\x84\\xED\\x83\\x84...' for column 'lunch_1_menu' at row 1") 해결 방법 (0) | 2024.09.12 |
[티스토리 스킨 버그] 흰색 프로필 박스 해결 방법 (1) | 2023.11.23 |
[파이썬 venv] Visual Studio Code에서 venv 활성화가 되지 않을 때 (0) | 2023.05.30 |