React

리액트 useState 렌더링 관련 알게 된 것들 : 객체 상태 관리, 상태의 초기 값

hyriver(강화영) 2024. 5. 6. 15:28

1. useState를 사용해서 상태관리를 할 때, 객체나 배열의 상태가 업데이트 되는 경우 새로운 변수를 만들고 그 변수에 업데이트 되는 값을 넣은 뒤 그 변수를 상태변화함수에 넣어주도록 한다.

숫자나 문자열은 따로 새로운 변수를 만들지 않고, 바뀌는 값을 그대로 넣어도 되는데 왜 객체나 배열은 이렇게 새로운 변수를 만들어 줘야할까?

 

→ 리액트는 상태가 변경될 때 컴포넌트의 리렌더링이 결정된다. 상태 객체를 직접 변경하면 리액트가 이전 상태와 새로운 상태를 비교할 때 차이점을 감지하지 못할 수 있다. 왜냐하면 리액트의 상태 비교 알고리즘이 얕은 비교를 수행하기 때문이다. 즉, 객체의 참조가 변경되었는지만 확인한다. 객체의 내부 속성이 변경되어도 참조가 같다면 리액트는 상태가 변경되지 않았다고 판단하고 재렌더링을 하지 않는다. 이 문제를 피하기 위해 새로운 객체를 생성하는 것.

 

* 얕은비교(shallow comparison): 문자열/숫자 등 원시자료형은 값을 비교하고, 객체/배열 등 참조자료형은 참조의 위치를 비교하는 것. 참조자료형의 값까지 비교하는 것은 깊은 비교라고 한다.

 

// 객체 sums의 상태 관리
const [sums, setSums] = useState({});

useEffect(() => {
  //상태 sums에 업데이트 시킬 새로운 변수를 만들어준다
  const newSums = {};
    
  // newSums에 들어갈 데이터 가공. 어쩌구 저쩌구..

  // newSums을 상태 변화함수에 넣어 sums의 상태를 변화시킨다
  setSums(newSums);
}, []);

 

2. useState의 초기값을 설정할 때 props나 바뀌는 데이터로 설정하면 안된다.

const [isActive, setIsActive] = useState(data?.DEL === “Y”);

 

data가 계속 바뀌는 값일 때, isActive에 data?.DEL === “Y”를 넣으면 바뀌는 값에 따라 isActive가 바뀔 것이라고 생각하지만 그렇지 않다. useState의 초기값은 컴포넌트가 마운트될때(제일 첫 렌더링) 딱 한번만 작동한다. 데이터나 props가 변경된다고 이 초기값도 같이 업데이트 되는 것은 아니다.

 

→ 그래서 상태가 props 또는 상태가 변경될 때마다 상태값도 업데이트 시키고 싶다면 useEffect를 사용하여 해당 프롭스 또는 데이터를 의존성배열에 넣어주고 상태를 업데이트 시키는 로직을 추가하여야한다.

 

// 1.
<ModalHeader>{item?.BRD_NAME}</ModalHeader>

// 2. 
<Checkbox defaultChecked={item?.BRAND_NEW === "Y"} />

 

1. 이렇게 JSX에서 직접 props를 참조하여 렌더링하는 경우는 props가 변경될 때 재랜더링(업데이트)된다.

 

2. 그런데 2번의 defaultChecked 얘도 JSX인데 업데이트는 안된다. 이것도 useState의 초기값과 마찬가지로 체크박스가 처음 렌더링 될때 즉 마운트될 때만 고려되는 속성이다. 그래서  defaultChecked 대신 checked 속성을 사용한다. 이렇게 보니 초기값 설정은 모두 마운트 될때만 설정되는 속성인 것같다. 초기값에는 유동적인 값은 넣지 않거나 따로 변경하는 작업을 해줘야겠다.

 

 

 

* 참고

https://choisuhyeok.tistory.com/34

 

[React] useState 초기값으로 props를 사용하면 안된다.

props로 받아온 값을 useState의 초기값으로 사용하여 렌더링 할 때 값이 분명 변경되었는데 useState에 들어간 값이 변하지 않는 문제가 생겼다. 이유는 useState의 초기값으로 props를 사용했기 때문이

choisuhyeok.tistory.com

 

 

-

이렇게보니 엄청 기초적인 내용인데, 막상 개발할때는 생각이 나지 않는 것 같다. 내가 알고있는 것을 실제로 코딩할때 적용하도록 노력해야겠다.