리액트의 상태가 불변하다는 것 = 기존 상태(state) 값을 직접 바꾸지 않음
상태 값을 변경해야 한다면 깊은 복사 후 변경하여 할당
리액트의 state는 객체 형태이다. 객체의 경우 참조형 자료이므로, 단순히 값만 변경할 경우 계속 같은 참조 주소를 가지고 있는 것이다.
리액트는 state가 변경될 때 리렌더링 된다. 리액트 입장에서 상태의 변경 기준은 '참조 값의 변경'이다.
아무리 값을 변경하더라도 참조 값이 같다면, 리액트는 state의 변경을 인식할 수 없고 리렌더링 되지 않는다.
또한 값을 직접적으로 변경하게 되면, 기존 값이 변경되므로 비교 대상이 사라지게 된다. 따라서 state가 변경되었는지 알 길이 없다.
🧚 state는 일반 변수와는 다르게 값이 변하면 렌더링이 일어난다. setState는 state를 변경시켜주는 함수이다.
클래스형 컴포넌트의 경우 render() 메서드를 통해 상태 변경을 감지할 수 있다. 상태 변경이 감지되면 필요한 부분만 업데이트할 수 있다.
함수형 컴포넌트는 말 그대로 컴포넌트를 리턴하는 '함수'다. 따라서 렌더링된다는 건 함수를 다시 호출한다는 말과 같다. (렌더링 = 함수 호출) 따라서 함수형 컴포넌트의 경우 상태 관리를 위해서 함수의 상태를 기억하는 어떤 장치가 필요하다. 이 때 사용하는 메서드가 바로 useState Hook이다.
useState는 자바스크립트 특징 중 하나인 '클로저'를 통해 함수의 기본 state 값을 기억한다. 기본 state와 변경된 state를 비교해주는 함수가 바로 useState이다.
우선 이해하기 쉽도록 간단한 useState 함수를 직접 만들어보자.
// 우리가 평소에 사용하는 useState 형태
const [state, setState] = useState(initialValue);
// state 값을 변경할 때
setState(변경값);
// useState 함수를 직접 만들어보자.
const useState = (initialValue) => {
// 처음: 기본 값을 파라미터로 받아서 변수에 저장
// state변경시: setState 함수에 의해 새로운 값이 기본 값에 담긴다.
let 기본값 = initialValue;
// 기본값을 리턴하는 함수 생성
// 기본값이 setState 함수에 의해 변경되었다면 변경 값 리턴
const state = () => 기본값;
// 내부 scope
const setState = (변경값) => {
// 클로저를 통해 기본값에 접근 가능
// 변경값이 파라미터를 통해 들어오면 기본값에 넣는다.
기본값 = 변경값;
}
return [state, setState];
}