Props
React에서 설명하는 Props
“props” (props는 속성을 나타내는 데이터입니다) 객체 인자를 받은 후 React 엘리먼트를 반환하므로 유효한 React 컴포넌트입니다. 이러한 컴포넌트는 JavaScript 함수이기 때문에 말 그대로 “함수 컴포넌트”라고 호칭합니다.
리액트에서 props를 속성을 나타내는 데이터라고 표현한다.
Props는 read-only 이다.
- Props를 전달해보자
- Props를 수정해보자.
- 해당 코드를 실행하면 멋지게
분명 let name = "John"; 수정 가능한 let으로 선언 했지만, 자식 컴포넌트(객체)에서 수정접근시 read only라 수정할 수 없다는 에러가 발생한다.
😒 왜 그럴까?
이유는 ReactElement 를 생성할때 props와 element 를 freeze해버리기 때문이다.
개인적으론, 무분별한 getter , setter를 지양하는 입장에서 너무나도 당연해 보인다.
부모 컴포넌트(객체)가 전달한 속성을 자식 컴포넌트(객체)가 수정하는 것은 불안전한 코드이다.
그렇다면 리액트는 왜 수정불가로 하는걸까?
변경의 주체는 오직 하나. (Immutable)
장점
- 동작이 예측가능하다.
- 변경의 주체가 하나로 모이게 된다면, 해당 객체에서만 변경을 감지하면 되기 때문에 변경을 감지하기 용이하다.
변경을 어디서든 허용했을때
- 데이터가 어디서든지 변경가능 하다면, 디버깅을 하거나 변경을 했을때 관찰해야하는 영역이 점차 늘어나기 때문에 예측가능하기 힘들어진다.
- 리액트가 관리하고 있는데, 어딘가에서 변경가능하다면 리액트입장에서는 Props를 신뢰할수 없을 것이다.
순수함수 처럼 동작하도록 하라.
모든 React 컴포넌트는 자신의 props를 다룰 때 반드시 순수 함수처럼 동작해야 합니다. (링크)
순수함수란?
- 외부의 값을 변경하지 않고, 부수효과 없이 주어진 인자로 항상 같은 값을 리턴하는 함수
불순한 함수
- 외부의 값을 수정하고 있다. 실무에서 수백줄의 코드가 하나의 파일로 되어있는 경우가 허다하다. 수백줄의 코드에서 값을 중구난방으로 수정하고 있는 코드를 수정해야 한다고 상상해보라. 그 코드를 수정했다한들 문제가 없을꺼라 확신 하기 힘들 것이다.
순수 함수
- 자신의 영역 주어진 인자로 외부영향 없이 하나의 책임만 수행하고 리턴하자.
정리
- props는 read only이다.
- 불변성을 유지함으로써 최적화 호율, 변경감지 용이성 등의 장점을 가진다.
- props를 다룰때 순수함수 처럼 동작하도록 하라.
React State
수정 할 수 있는 상태
부모에게 전달받은 상태(Props)는 수정 할 수 없다.
자신이 만든 상태(State) 는 수정할 수 있다.
Props는 전달받는 상태(내가 만들지 않은 상태)이라고 한다면, State는 컴포넌트(객체)가 직접 만드는 상태라고 할 수 있다.
내가 만드는 상태니까 내가 수정가능하다.
사실은 수정이 아니라 새로운 객체를 만드는것이다.
상태를 변경해보자
예시코드
화면
“let 이름 변경” 버튼을 클릭하더라도 이름이 변경 되지 않을것이다.
😒 왜 그럴까?
왜냐하면, 리액트가 모르기 때문이다.
리액트가 알 수 있도록 이벤트에 등록해주는 Hook을 사용해야한다.
상태변화를 알려주는 useState를 사용하자.
useState를 사용하면 어떻게 변경을 감지해서 리렌더링 하는걸까?
- useState Hook 함수를 실행하면 리액트 이벤트로 등록이 되기 때문이다.
리액트가 관리하는 dispatch 함수를 리턴받는다.
🤩 결국, useState가 반환하는 두번째 인자는 리액트가 등록한 event dispatch 함수이기 때문에 변경 감지시 렌더링 프로세스를 수행하는 것이다.
useState 변경 두가지 방식
값을 전달하는 방식
- count 를 증가시켜보자.
const StateCounter = () => {
const [count, setCount] = useState(0);
return (
Count: {count}
<button> { setCount(count + 1) setCount(count + 1) setCount(count + 1) setCount(count + 1) }}>+1</button>
)
}
+1 버튼을 클릭하면, count를 4번 증가시키는것 같지만 결과는 count가 0이 었다면 1의 결과를 반환한다.
dispatchSetState 호출을 디버깅하보면, 해당 호출 **시점**에 넘겨준 값을 업데이트 객체에 넣는 것을 알 수 있다.
함수 scope영역이 끝나기 전까지는 count는 업데이트 되지 않는 것이다.
() => {
setCount(count + 1)
setCount(count + 1)
setCount(count + 1)
setCount(count + 1)
}
결국 setCount(count + 1) 호출시점에 count 에 할당되어 있는 값을 동일하게 주는것이다.
함수를 전달하는 방식
함수 형태로 전달하자.
{
setCount((prevCount) => prevCount + 1)
setCount((prevCount) => prevCount + 1)
setCount((prevCount) => prevCount + 1)
setCount((prevCount) => prevCount + 1)
}
callback 형태 인자를 전달할때의 결과값은 0 이 아니라 4로 변경되는것을 확인할 수 있다.
dispatchSetState 메소드를 분석해 보았을때, 콜백 형태의 함수를 전달하면, 리액트 메모리상에 있는 state를 접근해서 업데이트 하는듯하다.
정리
- 컴포넌트(객체)에서 변하는 것을 State라고 한다.
- 리턴 받은 Dispatch 함수로 State를 변경 할 수 있다.
- State를 재할당 하는것이 아니다. 새로운 상태를 만들어서 다시 주는것이다.
- 변경 감지를 위해서는 리액트가 알 수 있도록 Hook을 통해서 이벤트로 등록해줘야 한다.
참고
'프로그래밍 > React' 카테고리의 다른 글
Golang Slice(슬라이스) 동작원리와 사용법 (0) | 2024.07.31 |
---|---|
React Virtual DOM (0) | 2024.07.29 |
React Composition (0) | 2024.07.29 |
React Function and Class Components (0) | 2024.07.29 |