makeState - Obejct를 상태로 쓰고 있다고요?!

비고
Tags
상태 관리
Select
 

올바른 상태 관리의 필요성

 

makeState (커스텀)

makeVar로 생성하는 global state를 효율적으로 사용하기 위함.
오브젝트로 상태를 선언할 경우, 오브젝트 내의 프로퍼티 하나만 바뀌더라도 해당 오브젝트를 상태로 사용하는 모든 곳에서 업데이트가 일어난다.
 
예를 들면 다음과 같다.
export interface DeviceState { tabletImei: string; companyName: string; contractType: DeviceContractType | ''; isServiceStarted: boolean; isDeviceAttached: boolean; isConnected: boolean; temperature: number | undefined; isTemperatureLow: boolean; isCoverOpened: boolean | undefined; isRebooted: boolean; firmwareVersion: string | null; errorFromUsbDevice: string; canUpdateFirmware: boolean; isGuestEnabled: boolean; errorPositions: ErrorPositionData[]; hasChangedCartridge: boolean; isBeingTestUpdated: boolean; isAfterDispensing: boolean; isTmpInspectionEnabled: boolean; isSyncedWithServerInspection: boolean; isReadingCartridges: boolean; isVendingMachineMode: boolean; hasCodePushUpdate: boolean; }
 
위의 엄청난 프로퍼티들 중에서 isAfterDispensing 값만 변경한다고 가정해 보자.
setState( prevState => ({...prevState, isAfterDispensing: true }) )
다른 프로퍼티들은 그대로 유지한 채, isAfterDispensing의 값만 바뀌길 원했을 것이다.
당연히 isAfterDispensing만 바뀌었으므로 isAfterDispensing 값을 참조하는 부분에서만 리렌더링이 일어나길 바랬을 것이다.
하지만 현실은 그렇지 않다. 리액트의 상태 관리 로직을 제대로 이해하지 못한 것이다.
 
setState를 통해 변경한 것이 무엇인가?
setState( prevState => ( {블라블라} <-- 오브젝트! ) )
특정 프로퍼티의 값을 변경한 것으로 새로운 오브젝트를 만들어서 넘겨주고 있다!
즉, 상태의 본체는 Object 이고, setState를 통해 새로운 Object로 바꿔주는 것이라는 사실을 이해해야 한다.
 
물론 얕은복사로 새로운 오브젝트를 만들었으니까 기존 상태 오브젝트가 가지고 있던 프로퍼티 값들은 그대로 유지된다.
하지만 결국 setState로 관리하고 있는 것은 오브젝트이며, 상태 변경이 일어날 때마다 새로운 오브젝트를 만들어서 전달하고 있으므로 해당 상태를 사용하고 있는 모든 부분에서 리컨실레이션이 일어나는 것이다.
 
💡
오브젝트는 새로 생성될 지라도, 얕은 복사를 했으니까 값은 그대로잖아요? 레퍼런스도 기존 값이 복사됐을 테니까 참조값도 동일할테고요. 리렌더링 여부를 판단할 때 전달되는 프롭이 동일한지 아닌지를 검사하는데, 결국 같은 프롭이 전달될테니까 리렌더링은 안되는 거 아닌가요? 따라서 이렇게 쓰더라도 문제없는 거 아닌가요?
 
안돼ㅐㅐㅐㅐㅐㅐㅐㅐㅐㅐ