useState함수에 값을 전달하면 초기값으로 지정할 수 있다.
const [state, setState] = useState(initialState);
초기값을 계산해서 넣는 경우 콜백을 사용하면 좋다.
const [state, setState] = useState(() => { // 초기값을 계산 return initialState; });
하지만 아래 코드에는 문제점이 있다.
savedValues 라는 값은 처음 렌더링 한 번만 계산하면 되는데,
매 렌더링 때마다 불필요하게 getSavedValues 함수를 실행해서
저장된 값을 가져온다function ReviewForm() { const savedValues = getSavedValues(); // ReviewForm을 렌더링할 때마다 실행됨 const [values, setValues] = useState(savedValues); // ... }
이렇게 콜백 형태로 초깃값을 지정해주면
처음 렌더링 할 때 한 번만 콜백을 실행해서 초깃값을 만들고,
그 이후로는 콜백을 실행하지 않기 때문에
getSavedValues를 불필요하게 실행하지 않는다.function ReviewForm() { const [values, setValues] = useState(() => { const savedValues = getSavedValues(); // 처음 렌더링할 때만 실행됨 return savedValues }); // ... }
단, 이때 주의할 점은 이 콜백 함수가 리턴할 때까지 리액트가 렌더링하지 않고 기다린다는 점이다..
콜백 함수의 실행이 오래 걸릴 수록 초기 렌더링이 늦어진다는 점에 주의.
Setter 함수에다가 값을 전달하면, 해당하는 값으로 변경
const [state, setState] = useState(0); const handleAddClick = () => { setState(state + 1); }주의할 점은
배열이나 객체 같은 참조형은 반드시 새로운 값을 만들어서 전달해야 한다는 것
const [state, setState] = useState({ count: 0 });
const handleAddClick = () => {
state.count += 1; // 참조형 변수의 프로퍼티를 수정
setState(state); // 참조형이기 때문에 변수의 값(레퍼런스)는 변하지 않음
}
const [state, setState] = useState({ count: 0 });
const handleAddClick = () => {
setState({ ...state, count: state.count + 1 }); // 새로운 객체 생성
}
만약 이전 State 값을 참조하면서 State를 변경하는 경우,
비동기 함수에서 State를 변경하게 되면
최신 값이 아닌 State 값을 참조하는 문제가 있었다.이럴 때는 콜백을 사용해서 처리할 수 있었다.
파라미터로 올바른 State 값을 가져와서 사용할 수 있다.
이전 State 값으로 새로운 State를 만드는 경우엔
항상 콜백 형태를 사용하는 습관을 들이는 것이 좋다.setState((prevState) => { // 다음 State 값을 계산 return nextState; });
const [count, setCount] = useState(0);
const handleAddClick = async () => {
await addCount();
setCount((prevCount) => prevCount + 1);
}