useState
로 배열과 객체를 관리하고 할 때가 있다. 하위 컴포넌트의 체크 여부를 한꺼번에 관리한다거나 복잡한 자료를 객체로 정리해서 하위 컴포넌트에 props
로 넘겨주고자 할 수도 있다.
useState
에 Primitive Type
즉 원시 자료형
을 관리할 때는 문제가 없다. 값이 바뀌면 리액트에서는 state
의 수정이 있었음을 인지하고 관련된 컴포넌트의 수정사항을 렌더링 한다.
하지만 배열
이나 객체
형식의 Reference Type
, 즉 참조 자료형
은 어떻게 인지를 할까?
import React, {useState} from "react";
function App(){
const [arr, setArr] = useState([]);
const clickHandler = ()=>{
setArr(prevArr=>{
prevArr.push(prevArr.length + 1);
return prevArr;
})
// setArr([...arr, arr.length+1]);
// 기존의 작성된 코드를 주석처리하고 이 주석을 지우면 잘 작동합니다.
}
const checkHandler = ()=>{
console.log(arr);
}
return (
<div>
<button onClick={clickHandler}>Add Array</button>
<button onClick={checkHandler}>Check Array</button>
<ul>
{arr.map(ele => {
return <li key={ele}>{ele}</li>
})}
</ul>
</div>
)
}
export default App;
간단한 웹앱을 만들어주었다. arr
이라는 배열 State
를 만들어주었다. "Add Array" 버튼을 누르면 숫자를 1부터 차례대로 배열에 추가한다. "Check Array" 버튼을 누르면 현재 arr
배열의 상태를 console
로 확인할 수 있다.
우리는 clickHandler
의 setArr
의 사용을 확인해야 한다. 우선 활성화되어 있는 코드문을 살펴보겠다. prevArr
로 이전 상태의 arr
을 가져온다. arr
에 직접적으로 push
함수를 사용하여 새로운 숫자를 넣어준다. 그리고 해당 배열을 리턴하여 arr
에 저장하였다.
렌더링이 잘 되고 있을까? 다음과 같이 작동이 잘 안되고 있음을 알 수 있다.
그리고 주석이 되어 있었던 부분의 코드를 활성화하고, 기존 코드 작성문을 주석처리하고 난 이후에 작동화면이다. 활성화되는 코드는 arr
를 spread
처리해주고, 새로운 숫자와 같이 새 배열에 넣어주었다.
React
는 원래 State
값과 Props
의 값이 변화했을 때, 해당 값과 관련되어 있는 엘리먼트들만 리렌더링 해주는 방식으로 UI 화면을 제공한다.
하지만 처음 우리가 확인했던 방식으로는 배열의 변화를 React
가 인식하지 못하고 있는 것처럼 보인다. React
공식문서에서도 useState
의 설명 중 이런 문제에 대해서 설명하고 있다.
출처 : React 공식문서
비단 배열만이 아닌 객체도 똑같은 문제가 발생하고 있음을 알 수 있다.
내가 추측하기에는 state
의 참조값, 즉 메모리 주소가 바뀌어야 React
에서 값의 변경이 일어났다는 것을 인지하는 것 같다. 이 때문에 배열이든, 객체이든 useState
의 set함수
를 통해 저장된 요소를 바꾸려고 한다면 새로운 배열이나 객체를 반환해줘야 한다는 것을 알고 있어야겠다.