- Event Handler
function Button({ onClick, children }) {
return (
<button onClick={onClick}>
{children}
</button>
);
}
function PlayButton({ movieName }) {
function handlePlayClick() {
alert(`Playing ${movieName}!`);
}
return (
<Button onClick={handlePlayClick}>
Play "{movieName}"
</Button>
);
}
여기서 결국 button onClick에 PlayButton의 handlePlayClick 함수가 콜백 함수로 등록되는데, 여기서 제대로 된 movieName을 뱉을 수 있는 이유는, handlePlayClick 함수가 정의된 Closure 안에 movieName이 존재하기 때문임.
- Event propagation
- upwards로 전이됨.
- onScroll 빼고 모든 이벤트가 전달됨.
- e.stopPropagation()으로 부모로 전달되는 이벤트 고리를 끊을 수 있음.
- e.preventDefault()
- default browser behavior를 막는 것.
- 예를 들어 form submit하면 default browser behavior로 전체 새로고침이 되는데 이걸 막음.
- stopPropagation이랑 아예 다른 결의 함수임.
- state
- Component의 메모리. 현재의 상태.
- Local variables로 되지 않는 이유는, render 간에 이 메모리가 유지되지 않고, render를 trigger하지 않음.
- 따라서 state는 render 간에 데이터를 유지하고, re-render를 trigger해야 함.
- Hook
- React가 렌더링하는 동안에만 사용할 수 있는 특수한 function.
- Hook는 Component의 최상위 부분에서만 부를 수 있음.
- import하고 해당 module을 사용하는 것처럼, Hook을 'use'하고 기능을 사용한다고 이해하면 됨.
- render한다의 의미
- UI에 Component를 그린다.
- 사실은 Component 코드 자체를 실행하는 것.
- re-render는 최신화된 state, props를 가지고 Component 코드를 재실행하는 것을 의미.
- useState
- re-render trigger를 통해 Component가 재실행되면, useState가 이를 기억하고 있기 때문에 값을 초기화하는 대신 최신 state를 해당 상태에 넣어줌.
- 따로 쓰이는 state는 따로 정의하자.
- 함께 자주 쓰이는 state는 같이 정의하자.
- state는 각 객체마다 독립적으로 존재함. Component까리 공유하지 않는다.
- 같은 Component 틀로 만든 다른 객체는 state를 공유하지 않음.
- 각 Component에서 상태를 공유하는 방법은, 그 Component들의 부모 Component에서 상태를 관리하고, props로 넘겨주면 됨.
- 언제 render하냐?
- initial render
- state가 업데이트 된 경우. setState하면 render queue에 들어감.
- trigger -> render -> commit으로 진행됨.
- commit에서 실제 DOM이 변경됨.
- react는 render에서 변경된 부분만 캐치해서 DOM을 업데이트함.
- State를 사용할 때에는, 이미 가지고 있는 상태 변수가 변경되지 않고, 새 상태를 가진 컴포넌트가 다시 렌더링됨.
- 사실은 정적인 snapshot이다.
- 한 번 render된 컴포넌트 내부의 state는 snapshot처럼 불변임.
<button onClick={() => {
setNumber(number + 1);
setNumber(number + 1);
setNumber(number + 1);
}}>+3</button>
에서, state인 number는 snapshot처럼 정적이다. 여기서 number는 변하지 않고 고정된 값을 가짐.
- state update의 배치 처리
- setState가 불렸다고 update하지 않는다.
- setState 함수를 실행하지 않고, 일단 queue에 넣는다.
- event handler의 모든 code가 실행된 다음에 실행되도록 동작한다.
- 이유는, half-finished 상태로 UI render를 막기 위함.
- 일단 queue에 저장했다가, 다음 render 시에 useState를 만나면, 이 때 queue를 확인한 다음 render한다.
- 그러니까 state를 사용하기 직전에 업데이트 됨.
- 여러 이벤트에 대해서도 batch 처리 하진 않는다. 예를 들어, 각각의 클릭 이벤트는 개별로 처리됨.
- mutate
- 함수 밖에서 정의된 state를 hook 없이 변경하려 드는 것은 위험하다.
- 함수 안에서 새로 만든 변수는 변경해도 상관이 없다.
- 왜냐하면 누구도 그 변수를 참조하지 않기 때문에, 함수 밖 어디에도 영향을 주지 않기 때문.
- object setState
- 숫자, 문자열과 다르게 object는 저장 공간의 주소 값을 가짐.
- react의 최적화는 상태 변수 값이 아예 바뀌어야 변화를 감지하고 re-render함.
- re-render를 위해서는 주소 값 자체를 바꿔야 함. 따라서 상태 자체를 수정하는 것이 아니라, 새로운 객체를 만들고 할당해줘야 함.
- 만약 object 내부에 object가 있다면, 이 객체 또한 주소값을 가지기 때문에. 깊은 복사로 다뤄야 함.
출처
https://react.dev/learn/adding-interactivity