불변성이라는 건 값이나 상태를 변경할 수 없다는 것을 의미한다.
= readonly, 읽기 전용이라고 생각하자.
리액트의 state는 JavaScript 값을 보유할 수 있다.
const [x, setX] = useState(0);
setX(5);
x state가 0에서 5로 변경되었지만 숫자 자체는 변경되지 않았다.
그렇다면 객체는 어떨까?
const [position, setPosition] = useState({ x: 0, y: 0 });
position.x = 5;
이런식으로 객체 자체의 내용을 변경하는 것은 가능하다.
하지만 React state 객체는 Number, Boolean, String 과 같이 불변인 것처럼 취급해야 한다.
객체나 배열과 같은 참조 타입의 상태는 직접 mutate하는 대신 항상 replace 해야 한다.
즉, 배열 내부에 항목을 다시 할당하거나 배열을 변형하는 메서드를 사용해서는 안된다.
이렇게 외부에 존재하는 원본 데이터를 직접 수정하지 않고, 원본 데이터의 복사본을 만들어서 값을 사용하며 불변성을 지켜줌으로써 side-effect도 방지할 수 있다.
따라서 Object 나 Array 의 원본 속성이나 값을 직접 바꾸게 되면 React에서 상태가 바뀌었다고 파악하지 못하기 때문에 불변성을 지키는 업데이트가 필요하다.
이렇게 얕은 비교를 통해 새로운 값이라고 판단되어 부모 컴포넌트가 re-rendering 하게 되면, 자식 컴포넌트도 함께 re-rendering 된다.
혹은 props이 객체, 배열 또는 함수인 경우 컴포넌트가 re-rendering 된다.
이런 방지하기 위해서 props를 단순화 하거나 부모 컴포넌트에서 props를 memoization 해서 성능을 최적화할 수 있다.
reactjs | memo - React
push
, splice
등의 원본데이터를 변경하는 메서드를 사용하지 말고, concat
, filter
, map
, slice
등을 사용한다.이 부분도 자세히 나와있어서 가져왔다.
reactjs | Updating Objects in State - React
결론적으로 디버깅을 쉽게하고, 어플리케이션을 최적화하며, 더 간단하게 구현하기 위해 state를 변형하는 것이 권장되지 않는다고 한다.
filter,
map
, slice
를 사용하자.push
, splice
등의 원본데이터를 변경하는 함수를 사용하지 말자.