2024. 4. 17. 15:28ㆍ개발/토막난 상식
문제의 코드
useEffect(() => {
if (selectedData !== selectedRowKeys) {
setSelectedRowKeys(selectedData)
}
}, [selectedData])
useEffect(() => {
if (verifiedColumns.length > 0) {
if (useCheckbox) {
setSelectAddColumns([
{
//todo 컬럼 추가
title: (
<>
<Checkbox
checked={allChecked}
onChange={(e) => {
if (e.target.checked) {
setSelectedRowKeys(entireKeyList)
} else {
setSelectedRowKeys([])
}
}}
/>
</>
),
dataIndex: 'key',
key: 'key',
width: 35,
align: 'center',
style: { justifyContent: 'center' },
render: (text) => {
return (
<Checkbox
checked={selectedRowKeys?.includes(text)}
onChange={(e) => {
const keyList = [...selectedRowKeys]
if (e.target.checked) {
keyList.push(text)
} else {
const index = keyList.indexOf(text)
if (index > -1) {
keyList.splice(index, 1)
}
}
setSelectedRowKeys(keyList)
}}
/>
)
},
},
...verifiedColumns,
])
} else {
setSelectAddColumns(verifiedColumns)
}
}
}, [verifiedColumns, entireKeyList, allChecked, selectedRowKeys])
해결 방법
useEffect(() => {
// selectedData와 selectedRowKeys가 다르면 업데이트
if (!arraysEqual(selectedData, selectedRowKeys)) {
setSelectedRowKeys(selectedData)
}
}, [selectedData])
// 간단한 배열 비교 함수
function arraysEqual(a, b) {
if (a === b) return true
if (a == null || b == null) return false
if (a.length !== b.length) return false
for (let i = 0; i < a.length; ++i) {
if (a[i] !== b[i]) return false
}
return true
}
첫 번째 코드 조각과 두 번째 코드 조각 사이에는 중요한 차이가 있으며, 이 차이로 인해 두 번째 코드 조각에서 오류가 발생합니다.
첫 번째 코드 조각
첫 번째 코드 조각에서는 arraysEqual이라는 함수를 사용하여 selectedData와 selectedRowKeys 두 배열의 내용이 동일한지를 깊은 비교(deep comparison)로 확인. 이 함수는 두 배열의 길이와 각 요소가 동일한지를 하나하나 확인하여, 실제로 배열의 내용이 같은지를 판단. 따라서, 두 배열이 실제로 같은 내용을 가지고 있으면 상태 업데이트를 하지 않다. 이 방법은 배열의 내용이 같을 때 불필요한 상태 업데이트를 피할 수 있어 효율적이다.
두 번째 코드 조각
반면, 두 번째 코드 조각에서는 selectedData와 selectedRowKeys를 직접 비교하고 있다. 이 경우, JavaScript에서 배열은 참조 타입이기 때문에, 이 두 배열이 같은 객체를 참조하지 않는 한(즉, 메모리 상에서 완전히 동일한 위치를 가리키지 않는 한), 이 조건문은 항상 참(true)으로 평가. 이는 즉, 심지어 두 배열이 내용적으로는 동일하더라도, 다른 메모리 주소를 가리키고 있다면 다른 객체로 간주되어 setSelectedRowKeys(selectedData)가 계속 호출되어 상태 업데이트가 발생하고, 이는 무한 렌더링을 유발할 수 있다.
결론
따라서, 두 번째 코드 조각에서 오류가 발생하는 이유는 배열의 참조 비교로 인해, 실제로 배열의 내용이 변경되지 않았음에도 불구하고 상태 업데이트가 반복적으로 발생하기 때문이다. 배열이나 객체와 같은 참조 타입을 비교할 때는 내용이 동일한지 깊은 비교를 수행해야 하며, 단순히 === 연산자를 사용하는 것으로는 충분하지 않다.
'개발 > 토막난 상식' 카테고리의 다른 글
인텔리제이 웹스톰 젯브레인 jetbrain 자동완성 단축키 (0) | 2024.05.08 |
---|---|
React 19 Beta 번역 (0) | 2024.04.29 |
원티드 디자인 (피그마) (2) | 2024.04.03 |
노드 자바 성능 비교 (0) | 2024.04.03 |
[React] 리액트 차트 라이브러리 추천 비교 분석 (무료, 유료) 19 + 6 종 (0) | 2024.04.03 |