Skip to content

Latest commit

 

History

History
229 lines (182 loc) · 7.97 KB

2주차_심미진_개인.md

File metadata and controls

229 lines (182 loc) · 7.97 KB

개인주제

React 19에서 상태의 개념과 동작원리가 변하는가?

액션(Actions)

리액트 애플리케이션에서는 데이터를 변경하고 이에 대한 응답을 기반으로 상태를 업데이트하는 것이 일반적인 사례

- e.g 사용자가 이름을 변경하기 위해 양식(form)을 제출하면, API 요청을 보낸 다음 응답을 처리
이전 : 대기 상태(pending state), 에러, 낙관적 업데이트, 순차적 요청을 직접 처리하는 방식

e.g useState로 대기와 에러 상태 다루기 가능

// 액션(Actions)이 등장 전
function UpdateName({}) {
  const [name, setName] = useState("");
  const [error, setError] = useState(null);
  const [isPending, setIsPending] = useState(false);

  const handleSubmit = async () => {
    setIsPending(true);
    const error = await updateName(name);
    setIsPending(false);
    if (error) {
      setError(error);
      return;
    }
    redirect("/path");
  };

  return (
    <div>
      <input value={name} onChange={(event) => setName(event.target.value)} />
      <button onClick={handleSubmit} disabled={isPending}>
        Update
      </button>
      {error && <p>{error}</p>}
    </div>
  );
}

리액트 19에서는 트랜지션에서 비동기 함수를 사용하여 대기 상태, 에러, 양식, 낙관적 업데이트를 자동으로 처리하는 기능이 추가됨 아래와 같이 useTransition을 사용하여 대기 상태를 다룸

// 액션에서 대기 상태 사용하기
function UpdateName({}) {
  const [name, setName] = useState("");
  const [error, setError] = useState(null);
  const [isPending, startTransition] = useTransition();

  const handleSubmit = () => {
    startTransition(async () => {
      const error = await updateName(name);
      if (error) {
        setError(error);
        return;
      }
      redirect("/path");
    });
  };

  return (
    <div>
      <input value={name} onChange={(event) => setName(event.target.value)} />
      <button onClick={handleSubmit} disabled={isPending}>
        Update
      </button>
      {error && <p>{error}</p>}
    </div>
  );
}

비동기 트랜지션은 isPending 값을 즉시 true로 설정하며 비동기 요청을 보내고, 트랜지션이 수행되면 isPending을 false로 전환 - 이러한 방식은 데이터가 변경되는 동안에도 현재 UI의 반응성 및 상호작용을 유지 가능.

참고

컨벤션에 따라 비동기 트랜지션을 사용하는 함수는 "액션(Actions)"라고 부름

액션은 데이터 제출을 자동으로 관리함

  • 대기 상태: 액션은 요청이 시작될 때 함께 시작하며, 최종 상태 업데이트가 커밋되면 자동으로 재설정되는 대기 상태를 제공
  • 낙관적 업데이트: 액션은 새로운 훅인 useOptimistic을 지원, 사용자들이 요청을 제출했을 때 즉각적인 응답을 제공 가능
  • 에러 처리: 액션은 에러 처리 기능을 제공하므로 요청이 실패했을 때 에러 바운더리를 표시 가능 또한 낙관적 업데이트로 수정된 값을 자동으로 원래의 값으로 복구 가능
  • 양식(form): <form> 요소에 action과 formAction 프로퍼티에 함수를 전달 가능, action 프로퍼티에 함수를 전달하면 기본적으로 액션을 사용하고 제출 후에 자동으로 양식을 재설정

  • 액션을 기반으로 구축된 리액트 19는 낙관적 업데이트의 처리를 위한 useOptimistic, 액션의 일반적인 사용을 다루기 위한 새로운 훅 React.useActionstate을 도입

  • react-dom에서는 양식을 자동으로 관리하는 form 액션, 양식에서 액션을 지원하는 useFormStatus 추가하고 있습니다.

  • 리액트 19에서는 위의 예시를 아래와 같이 단순하게 작성 가능

// <form> 액션과 useActionState 사용
function ChangeName({ name, setName }) {
  const [error, submitAction, isPending] = useActionState(
    async (previousState, formData) => {
      const error = await updateName(formData.get("name"));
      if (error) {
        return error;
      }
      redirect("/path");
      return null;
    },
    null
  );

  return (
    <form action={submitAction}>
      <input type="text" name="name" />
      <button type="submit" disabled={isPending}>
        Update
      </button>
      {error && <p>{error}</p>}
    </form>
  );
}

+새로운 훅: useActionState

액션의 일반적인 경우를 더 쉽게 처리하기 위해 useActionState 훅을 추가

const [error, submitAction, isPending] = useActionState(
  async (previousState, newName) => {
    const error = await updateName(newName);
    if (error) {
      // 액션의 어떤 결과든 반환할 수 있습니다.
      // 이 예제에서는 에러만 반환합니다.
      return error;
    }

    // 요청이 성공한 경우
    return null;
  },
  null
);
  • useActionState는 함수("액션")를 받아 호출할 래핑된 액션을 반환.
    • 이는 각 액션이 조합되므로 가능, 래핑된 액션이 호출되면 useActionState는 액션의 마지막 결과를 data로, 액션의 대기 상태를 pending으로 반환합니다.

리액트 DOM 새로운 훅: useFormStatus

디자인 시스템에서 컴포넌트가 속한 <form>에 대한 정보를 접근해야 할 때가 많은데, 컴포넌트에 프로퍼티를 드릴링하지 않고 접근하려면 컨텍스트를 사용할 수도 있지만 이를 좀 더 쉽게 다루도록 useFormStatus 훅을 새롭게 추가

import { useFormStatus } from "react-dom";

function DesignButton() {
  const { pending } = useFormStatus();
  return <button type="submit" disabled={pending} />;
}

useFormStatus 훅은 컨텍스트 프로바이더처럼 부모의 <form>의 상태를 읽습니다.

새로운 훅: useOptimistic

데이터 변경을 수행할 때 비동기 요청이 진행되는 동안 최종 상태를 낙관적으로 표시하는 것도 흔한 UI 패턴. 리액트 19에서 이를 쉽게 처리하는 useOptimistic 훅이 추가됨

function ChangeName({ currentName, onUpdateName }) {
  const [optimisticName, setOptimisticName] = useOptimistic(currentName);

  const submitAction = async (formData) => {
    const newName = formData.get("name");
    setOptimisticName(newName);
    const updatedName = await updateName(newName);
    onUpdateName(updatedName);
  };

  return (
    <form action={submitAction}>
      <p>Your name is: {optimisticName}</p>
      <p>
        <label>Change Name:</label>
        <input
          type="text"
          name="name"
          disabled={currentName !== optimisticName}
        />
      </p>
    </form>
  );
}
  • useOptimistic 훅은 updateName 요청이 진행되면 optimisticName 값을 바로 보여줌
    • 업데이트가 종료되거나 실패하면 리액트는 자동으로 currentName 값으로 다시 전환됨

새로운 훅: use

리액트 19에서는 렌더링에서 리소스를 읽는 새로운 API인 use를 도입.

e.g use로 프로미스를 읽는 경우, 프로미스가 해결(resolve)될 때까지 리액트는 일시 중단됨

import { use } from "react";

function Comments({ commentsPromise }) {
  // `use`는 프로미스가 해결될 때까지 일시 중단됩니다.
  const comments = use(commentsPromise);
  return comments.map((comment) => <p key={comment.id}>{comment}</p>);
}

function Page({ commentsPromise }) {
  // Comments에서 `use`가 일시 중단되면,
  // 이 컴포넌트의 서스펜스 바운더리가 보여집니다.
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <Comments commentsPromise={commentsPromise} />
    </Suspense>
  );
}