개요
useOptimistic
은 비동기 작업(예: 네트워크 요청) 중에 UI를 낙관적으로(optimistic) 업데이트할 수 있게 해주는 React Hook입니다. 사용자는 실제 작업이 끝나기 전에 결과를 미리 보는 것처럼 느낄 수 있습니다.
const [optimisticState, addOptimistic] = useOptimistic(state, updateFn);
Reference
useOptimistic(state, updateFn)
useOptimistic
은 비동기 액션이 진행되는 동안 임시로 다른 state를 보여줄 수 있게 해줍니다. state와 updateFn을 인자로 받아, 액션이 진행 중일 때는 updateFn의 결과를, 아닐 때는 원래 state를 반환합니다.
import { useOptimistic } from 'react';
function AppContainer() {
const [optimisticState, addOptimistic] = useOptimistic(
state,
(currentState, optimisticValue) => {
// optimisticValue를 반영한 새로운 state 반환
}
);
}
파라미터
state
: 기본 state 값. 액션이 없을 때 반환됩니다.updateFn(currentState, optimisticValue)
: 현재 state와 addOptimistic으로 전달된 optimisticValue를 받아, 낙관적 UI에 사용할 state를 반환하는 순수 함수입니다.
반환값
optimisticState
: 액션이 없을 때는 state, 액션이 진행 중일 때는 updateFn의 결과가 반환됩니다.addOptimistic
: 낙관적 업데이트를 트리거하는 함수. optimisticValue를 인자로 받아 updateFn을 실행합니다.
사용법
폼 등에서 낙관적 UI 업데이트
폼 전송 등에서 서버 응답을 기다리지 않고, 사용자가 입력한 값을 즉시 UI에 반영할 수 있습니다.
import { useOptimistic, useState, useRef, startTransition } from "react";
function Thread({ messages, sendMessageAction }) {
const formRef = useRef();
function formAction(formData) {
addOptimisticMessage(formData.get("message"));
formRef.current.reset();
startTransition(async () => {
await sendMessageAction(formData);
});
}
const [optimisticMessages, addOptimisticMessage] = useOptimistic(
messages,
(state, newMessage) => [
{ text: newMessage, sending: true },
...state,
]
);
return (
<>
<form action={formAction} ref={formRef}>
<input type="text" name="message" placeholder="Hello!" />
<button type="submit">Send</button>
</form>
{optimisticMessages.map((message, index) => (
<div key={index}>
{message.text}
{!!message.sending && <small> (Sending...)</small>}
</div>
))}
</>
);
}
주의사항 및 Caveats
- updateFn은 반드시 순수 함수여야 하며, 부수 효과(side effect)가 없어야 합니다.
- 낙관적 UI는 실제 결과와 다를 수 있으므로, 서버 응답이 오면 반드시 실제 결과로 state를 동기화해야 합니다.
- addOptimistic은 여러 번 호출될 수 있으며, 각 호출마다 updateFn이 실행됩니다.
반응형