axios로 열심히 state를 가져와 업데이트해 view를 보여주고 있는 일상이었다. async붙여가며 비동기/동기 맛좀 보고 있었는데 '리액트를 다루는 기술'에서 새로운 사실을 알았다.... 사실 비동기/동기랑 상관 없는 최적화 작업이었지만... 다음과 같다.
const onToggle = useCallback(
(id) => {
setTodos(
todos.map((a) => {
return a.id === id ? { ...a, checked: !a.checked } : a;
}),
);
},
[todos],
);
본 책에 나온 할 일 목록 프로젝트인데, 그 중 체크여부에 따라 todo의 check를 true/false로 바꿔주는 onToggle함수이다. useCallback의 두번째 파라미터로 todos로 넣어 todos가 바뀔 때만 함수를 재생성하게해 두었다. 하지만 어쩔 수 없이 todos가 몇천개가 있다면 마찬가지로 이 함수또한 계속 생성될 것이다. 이 때 필요한 것이 함수형 업데이트 이다.
const onToggle = useCallback(
(id) => {
setTodos((todos) => {
return todos.map((a) => {
return a.id === id ? { ...a, checked: !a.checked } : a;
});
});
},
[],
);
콜백함수를 넣어주면 된다. 사실 콜백함수를 넣는다는 것 자체가 그 안에서 비동기로 상태를 바꾼다는 것 같은데... 확실히 이를 역이용해서 동기적으로 state가 업데이트 된 후 원하는 무언가를 할 수 있다.(batch를 무시한다.)
const [num, setNum] = useState(1)
const plus =()=> {
setNum(num + 1)
setNum(num + 1)
}
아아.. 이것은 비동기라는 것이다... num은 2가 나오지...
하지만 함수형 업데이트로 바꿔보자
const [num, setNum] = useState(1)
const plus =()=> {
setNum(prev => prev+ 1)
setNum(prev => prev+ 1)
}
예상하다시피 3이 나오게 된다.. 앞으로 비동기 통신과 state를 좀 더 효율적으로 다룰 수 있을것 같은 느낌이 든다.