Skip to main content

리액트에서 불변성이 필요한 이유

불변성

메모리 영역의 값을 변경할 수 없는 것

리액트의 불변성을 지켜야하는 이유는 다음과 같습니다.

  1. 효율적인 상태업데이트(얕은 비교 수행)

리액트는 상태비교 시, 얕은 비교를 수행(이전 참조값과 현재 참조값만 비교)(객체의 모든 부분을 비교하는 것이 아님)

=> 따라서 계산 리소스 줄여줌

const App = () => {
const [state, setState] = useState({});

const handleClick = (key, value) => {
// 얕은 비교를 수행
setState({
...state,
[key]: value,
});
};

return <div onClick={() => handleClick(key, value)}>{state}</div>;
};

원시타입은 바로 값을 setState에 넣어줘도 되지만,

참조타입인 객체의 경우, 새로운 객체나 배열을 생성한 후 값을 넣어야합니다.

// 원시타입const [number, setNumber] = useState(0)
setState(3)

// 참조타입const [person, setPerson] = useState({ name: '', age: 30 })
setState({...person, name: 'pyo'})

spread operator, map, filter, slice, reduce 메소드들을 활용

  1. 원본데이터를 바꾸지 않아서 => 사이드이펙트 사전 방지, 프로그래밍 구조 단순하게 유지가능

참고: 클래스 컴포넌트와 함수형 컴포넌트의 불변성을 지키는 방법

count 값이 3초 뒤 변경되더라도, 해당 값을 컴포넌트의 인스턴스 변수인 this.state.count에 유지

따라서 render 메소드에서는 this.state.count를 참조할 때, 값이 초기화하지 않고 변경된 값인 1이 출력

class Example extends React.Component {
state = { count: 0 };

componentDidMount() {
// 3초 후 count 값 변경
setTimeout(() => {
this.setState({ count: 1 });
}, 3000);
}

render() {
console.log("render count:", this.state.count);
return <div>{this.state.count}</div>;
}
}

만약 함수형 컴포넌트에서 상태의 초기화를 방지하고, 함수형 컴포넌트 내부에서 유지할 수 있게 해주는 useState 같은 훅을 사용하지 않는다면

count 변수를 직접 수정하고, handleClick이 실행될 때마다 count 변수가 다시 0으로 초기화되므로

아무리 handleClick을 실행시켜도 count는 항상 1입니다.

import React from "react";

function Counter(props) {
let count = 0;

function handleClick() {
count++;
console.log(count);
}

return (
<div>
<p>Count: {count}</p>
<button onClick={handleClick}>Increment</button>
</div>
);
}

export default Counter;

참고

리액트 불변성이란 무엇이고, 왜 지켜야 할까?