React19 useOptimistic Hook

2025. 3. 3. 17:00·⭐FE

🧩`useOptimistic`

`useOptimistic` 는 낙관적(optimistically)으로 UI를 업데이트 할 수 있도록 하는 React Hook 이다. 

  const [optimisticState, addOptimistic] = useOptimistic(state, updateFn);

🧩레퍼런스

`useOptimistic(state, updateFn)`

`useOptimistic`은 aysnc action 이 진행되는 동안 다른 state를 보여준다. 이 말을 예시를 들어 설명하면 이렇다. 만약 우리가 인스타그램을 하다가 좋아요 버튼을 클릭한다고 가정하면 유저가 그 게시물에대해 좋아요를 했다는 정보를 서버에 저장하기 위해서 서버에 http request를 하고 서버에서 해당 작업을 완료한 뒤 서버에서는 response 200 code를 클라이언트로 준다. 방금말한 일련의 과정이 끝난 뒤 좋아요 버튼이 눌린상태의 ui를 업데이트하기 보단 이 과정을 기다리는 것 없이 즉시 좋아요 버튼이 눌리도록 처리한다는 이야기이다. 아래와 같이 사용할 수 있다.

import { useOptimistic } from 'react';

function AppContainer() {
  const [optimisticState, addOptimistic] = useOptimistic(
    state,
    // updateFn
    (currentState, optimisticValue) => {
      // merge and return new state
      // with optimistic value
    }
  );
}

➕매개변수

  • state: 작업이 대기 중이지 않을 시 초기에 반환될 값이다.
  • updateFn(currentState, optimisticValue): 현재 상태와 addOptimistic에 전달된 낙관적인 값을 이용하는 함수로, 결과적으로 낙관적인 상태를 return 한다.

➕반환값

  • optimisticState: 결과적인 낙관적인 상태이다. 작업이 대기 중이지 않을 때는 state와 동일하며, 그렇지 않은 경우 updateFn에서 반환되는 값과 동일하다. ( 이 말은 즉 action이 진행중일 동안만 state와 다르다는 이야기이다.) 
  • addOptimistic: addOptimistic는 낙관적인 업데이트가 있을 때 호출하는 dispatch 함수이다. 어떠한 타입의 optimisticValue 라는 하나의 인자를 취하며, state 와 optimisticValue로 updateFn을 호출한다.

➕주의사항

  • useOptimistic의 리턴값으로 나온 hook은 transition이나 form action 안에서만 사용할 수 있다 ( 중요 )
  • useOptimistic이 Optimistic value를 버리고 실제 state값으로 덮어쓰는 작업은 form action이나 transition이 종료된 시점이다. 그 전까지는 state가 업데이트 되면 실행된 computeUpdatedState를 새로운 state로 가지고 모두 재실행된다.

🧩사용법

하단 예시는 공식홈페이지에 올라온 예시이다. (실제 코드의 동작을 보고싶으면 https://codesandbox.io/p/sandbox/tk7ks9 를 참고)

import { useOptimistic, useState, useRef } from "react";
import { deliverMessage } from "./actions.js";

function Thread({ messages, sendMessage }) {
  const formRef = useRef();
  async function formAction(formData) {
    addOptimisticMessage(formData.get("message"));
    formRef.current.reset();
    await sendMessage(formData);
  }
  const [optimisticMessages, addOptimisticMessage] = useOptimistic(
    messages,
    (state, newMessage) => [
      ...state,
      {
        text: newMessage,
        sending: true
      }
    ]
  );

  return (
    <>
      {optimisticMessages.map((message, index) => (
        <div key={index}>
          {message.text}
          {!!message.sending && <small> (Sending...)</small>}
        </div>
      ))}
      <form action={formAction} ref={formRef}>
        <input type="text" name="message" placeholder="Hello!" />
        <button type="submit">Send</button>
      </form>
    </>
  );
}

export default function App() {
  const [messages, setMessages] = useState([
    { text: "Hello there!", sending: false, key: 1 }
  ]);
  async function sendMessage(formData) {
    const sentMessage = await deliverMessage(formData.get("message"));
    setMessages((messages) => [...messages, { text: sentMessage }]);
  }
  return <Thread messages={messages} sendMessage={sendMessage} />;
}
export async function deliverMessage(message) {
  await new Promise((res) => setTimeout(res, 1000));
  return message;
}

위 코드는 아래와 같이 동작한다. 

  • 첫로드시 화면은 1번과 같이 보여진다.
  • input창에 '입력값' 이라고 입력하고 send 버튼 클릭 시 formAction이 이루어진다. formAction이 1초가 넘게 걸리도록 만들었지만 send 버튼을 누르면 바로 화면에 반영된다. ( 입력값(Sending ..) ). 이는 optimisticMessage를 이용하여 화면을 렌더링하였기 때문이다. 
  • formAction내부 `await sendMessage(formData)` 가 실행되고 formAction이 끝나면서  optimisticMessage 와 state는 값이 일치된다. 

🧩느낀점

낙관적 업데이트를 구현하기 위해서는 개발자가 실제로 state를 이용해 custom hook을 만들거나 react-query를 이용하는 등 외부 라이브러리를 이용하던지 해야됐었는데 이제는 그럴필요가 없을 것 같다. 실제로 사용해보니 매우 편리하였다. 별개로 공홈에 나온 페이지를 단순히 읽기보단 이해한 내용을 바탕으로 직접 코드로 동작구현을 통해 이해하는게 사용법 이해가 훨씬 잘 될 것이다. 

✅참고

https://react.dev/reference/react/useOptimistic

 

useOptimistic – React

The library for web and native user interfaces

react.dev

 

'⭐FE' 카테고리의 다른 글

LRU ( Least Recently Used ) 알고리즘 구현해보기  (0) 2025.03.29
Stacking Context ( 쌓임 맥락 )  (0) 2025.03.29
React19 useFormStauts Hook  (0) 2025.02.26
React19 useActionState Hook 활용 예시  (0) 2025.02.23
React Server Component  (0) 2025.02.17
'⭐FE' 카테고리의 다른 글
  • LRU ( Least Recently Used ) 알고리즘 구현해보기
  • Stacking Context ( 쌓임 맥락 )
  • React19 useFormStauts Hook
  • React19 useActionState Hook 활용 예시
devWarrior
devWarrior
  • devWarrior
    devWarrior
    devWarrior
  • 전체
    오늘
    어제
    • 🧩Dev (263)
      • ⭐FE (34)
      • 🔒Algorithm (155)
      • ➕Etc. (11)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
    • 글쓰기
    • 관리
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    js
    프론트엔드
    node.js
    FE
    코테
    백준
    알고리즘
    자스
    DFS
    골드5
    nodejs
    실버2
    javascript
    실버3
    오블완
    실버1
    그리디
    티스토리챌린지
    Lv2
    구현
    BFS
    react
    leetcode
    자바스크립트
    코딩테스트
    프로그래머스
    dp
    Easy
    실버4
    Algorithm
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
devWarrior
React19 useOptimistic Hook
상단으로

티스토리툴바