오늘은 간단하게 본문부터!
복잡한 동작을 하는 함수가 실행되는 동안 유저에게 loading state 표기
button click -> handleClick 함수 -> loading State = true -> 유저에게 표기
const Component = () => {
const [loading, setLoading] = useState(false);
const handleClick = useCallback(() => {
setLoading(true);
/*
// 아주 아주 복잡한 과정 중!
function(){}
*/
setLoading(false);
} , [])
return (
<>
<button onClick={handleClick} />
{loading ? 'loading' : 'not-loading'}
</>
);
}
위 처럼 코드를 짜면 handleClick
을 눌렀을 때, loading은 true로 변하지만 그 뒤의 function이 같이 따라 붙으면서 랜더링 되는 UI가 너무 늦게 변하였다. (적어도 내 경우는 그러했다. 5000 x 3000의 image canvas로 변환 작업이었다.)
그래서 해결방법은,
state를 하나 더 넣어주는 것이었다.
useState + useEffect 콤보를 쓰자
const Component = () => {
const [loading, setLoading] = useState(false);
const [state, setStart] = useState(false);
const handleClick = useCallback(() => {
setLoading(true);
setStart(true);
} , [])
useEffect(() => {
if(start){
/*
// 아주 아주 복잡한 과정 중!
function(){}
*/
setLoading(false);
}
} ,[start])
return (
<>
<button onClick={handleClick} />
{loading ? 'loading' : 'not-loading'}
</>
);
}
start
의 값 변화에 따라 useEffect
를 실행하게 한 후, 복잡한 작업을 하는 함수를 useEffect
안에 넣어둔다.
이렇게하면 state변화에 따른 ui 변경이 훨 빠르게 된다.
react 18에서는 useTransition
이 추가되서 두 개의 state 변경에 대해 우선순위를 정할 수 있게 됫다.
[isPending, startTransition] = useTransition();
startTransition(() => {
// 복잡한 함수
})
이런식으로 써주면 된다. 하지만, 이렇게 쓸 경우 start 변경을 나누기 때문에 performance 이슈가 존재할 수 있다. (여러번 rendering)