[React] useState와 const (리액트 라이프사이클)

공이·2023년 11월 4일
0

React

목록 보기
3/4
post-thumbnail

프로필 편집 기능을 구현하다가 컴포넌트 내에 선언된 useState와 일반 const 변수의 행동 차이를 유의미하게 관찰할 수 있게 되었다😶‍

useState로 선언된 상태 변수 user와 이를 참조하는 const로 선언된 변수 preUserIntroduction 간의 상호작용에서 예상치 못한 결과를 마주했다.

나는 이것이 깊은 복사(deep copy)/얕은 복사(shallow copy) 개념과 관련이 있는 것인줄 알았다. 마치 state 변수는 깊은 복사를 하는 것이고, const 변수는 얕은 복사를 하는 것인가 싶었다.

그러나 나의 리액트 컴포넌트 라이프사이클에 대한 이해 부족이었다.
결론적으로는 둘 다 얕은 복사를 하는 것이고, const 변수는 컴포넌트가 마운트 될 때마다 참조되는 값이 새로 갱신되는 것일 뿐이었다.

export const EditIntroduction = ({ navigation }) => {
  const [user, setUser] = useRecoilState(userState);
  const preUserIntroduction = user.introduction;

  const onPressConfirm = () => {
    navigation.navigate('EditProfile');
  };

  const onPressCancel = () => {
    setUser({ ...user, introduction: preUserIntroduction });
    navigation.navigate('EditProfile');
  };

  // 생략된 UI 렌더링 부분
};

위의 코드에서 나는 preUserIntroductionuser.introduction의 초기값을 그대로 유지하기를 바랐다.
그런데 사용자가 TextInput의 onChange를 통해 user.introduction을 변경하면 const preUserIntroduction도 업데이트되는 현상이 있었다. 그래서 취소 버튼을 통해 onPressCancel 함수가 호출되더라도 초기의 user 값이 아닌 onChange로 인해 변경된 user 값이 user 상태 변수에 반영되었다.

export const EditIntroduction = ({ navigation }) => {
  const [user, setUser] = useRecoilState(userState);
  const [preUserIntroduction, setPreUserIntroduction] = useState[user.introduction];

  const onPressConfirm = () => {
    navigation.navigate('EditProfile');
  };

  const onPressCancel = () => {
    setUser({ ...user, introduction: preUserIntroduction });
    navigation.navigate('EditProfile');
  };

  // 생략된 UI 렌더링 부분
};

반면 preUserIntroductionuseState로 관리했을 때는 TextInput의 onChange를 통해 user.introduction을 변경하더라도 preUserIntroduction이 초기값을 잘 유지했다. 그래서 onPressCancel 함수가 호출되면 user 상태 변수에 초기의 user 값이 잘 반영되었다.

리액트의 렌더링 메커니즘에 따라const 변수는 컴포넌트의 렌더링마다 새로운 값으로 초기화된다. 컴포넌트의 상태가 변경되어 재렌더링이 발생하면, const 변수는 새로운 상태 값으로 갱신된다.
반면, useState로 선언된 상태는 컴포넌트가 재렌더링 되어도 이전 상태를 유지하며, 오직 설정된 업데이트 함수를 통해서만 변경될 수 있다. 그래서 마치 깊은 복사를 하는 것처럼 보였던 것이다.

const와 state 변수의 차이를 이번에 제대로 알게 되었다!

0개의 댓글