const [state, setState] = useState(초기값);
// 기본 업데이트
// 3번 호출 했으니 +3이 될거같지만...
// 1씩 증가되는걸 확인할 수 있다.
setNumber(number + 1);
setNumber(number + 1);
setNumber(number + 1);
// 함수형 업데이트
// 하지만 함수형 업데이트를 사용하면 내가 생각했던 +3이 되는걸 확인할 수 있다.
setNumber((prevState) => prevState + 1);
setNumber((prevState) => prevState + 1);
setNumber((prevState) => prevState + 1);
일반 업데이트 방식은 버튼을 클릭했을 때 setNumber가 각각 실행되는게 아니라
배치(batch)처리 한다. 즉, onClick을 했을 때 setNumber라는 함수를 세번 호출하지만
리액트는 그 호출을 하나로 모아 최종적으로 한번만 실행한다.
반면에 함수형 업데이트는 세번을 동시에 호출하면, 그 호출을 모아 순차적으로 각각 한번씩 실행 시킨다.
리액트는 성능을 위해 setState()를 다일 업데이트로 한꺼번에 처리할 수 있습니다.
불필요한 리렌더링을 방지하기 위해 리액트 성능을 위해 한꺼번에 state를 업데이트 한다.
useEffect(() => {
console.log("hello useEffect!");
});
useEffect는 속한 컴포넌트가 화면에 렌더링이 될 때 실행된다. 이런 useEffect의 특징 때문에 의도치 않은 동작을 경험한다.
import { useEffect, useState } from "react";
function UseEffect() {
const [value, setValue] = useState("");
useEffect(() => {
console.log("hello useEffect");
});
return (
<div>
<input
type="text"
value={value}
onChange={(e) => setValue(e.target.value)}
/>
</div>
);
}
export default UseEffect;
input 태그에 어떤 값을 입력할 때 마다 이 컴포넌트는 리렌더링이 된다.
리렌더링 될 때마다 useEffect가 실행되는 문제가 있다.
위 코드의 흐름
- input에 값을 입력한다.
- value, 즉 state가 변경된다.
- state가 변경되었기 때문에, App 컴포넌트가 리렌더링 된다.
- 리렌더링이 되었기 때문에 useEffect가 다시 실행된다.
- 1번 → 5번 과정이 계속 순환환다.
useEffect에는 의존성 배열이라는 것이 있다.
의존성 배열은 "이 배열에 값을 너으면 그 값이 바뀔 때만 useEffect를 실행한다라는 것이다."
useEffect(() => {}, [의존성배열]);
useEffect(() => {
console.log(`hello useEffect`);
}, []);
렌더링 될 때 딱 한번만 실행된다.
useEffect(() => {
console.log(`hello useEffect: ${value}`);
}, [value]);
의존성 배열에 있는 state가 변경될 때 마다 실행된다.
컴포넌트가 사라졌을 때 무언가를 실행할 때 사용한다. 이 과정을 클린 업(clean up)이라고 표현한다.
useEffect(() => {
console.log(`hello useEffect`);
return () => {
console.log("여기가 바로 클린 업");
};
}, []);
const div = document.querySelector("div");
const p = document.querySelector("p");
react에서는 DOM 객체를 선택하기 위해 useRef를 사용하면 된다.
const ref = useRef("초기값");
console.log(ref); //{current: '초기값'}
ref.current = "변경값";
console.log("변경값");
설정된 ref 값은 컴포넌트가 계속해서 렌더링 되어도 unmount 전까지 값을 유지한다.
import { useEffect, useRef } from "react";
function UseRef() {
const idRef = useRef(null);
useEffect(() => {
idRef.current.focus();
}, []);
return (
<>
<div>
아이디: <input type="text" ref={idRef} />
</div>
<div>
비밀번호: <input type="password" />
</div>
</>
);
}
export default UseRef;
부모 -> 자식 -> 그자식 -> 그자식의 자식
이렇게 깊어지면서 prop drilling 현상이 일어난다.