>웹 프론트엔드 >JS 튜토리얼 >새로운 React가 테이블에 가져온 것 - 명확한 이해를 얻으세요

새로운 React가 테이블에 가져온 것 - 명확한 이해를 얻으세요

Linda Hamilton
Linda Hamilton원래의
2024-11-24 13:16:15378검색

React 19는 2024년 4월 25일에 나왔습니다. JavaScript 세계는 너무 빨리 변하기 때문에 때로는 따라가는 것이 부담스러울 수 있습니다. 하지만 이러한 변화가 React 개발자로서의 삶을 더 쉽게 만들기 위한 것이라면 한 번 살펴볼 가치가 있습니다. 그렇죠? React는 이 생태계에서 매우 중요한 부분이므로 최신 정보를 지속적으로 업데이트하는 것이 필수입니다.

React 19의 가장 좋은 점은 작업을 더 단순하게 만드는 데 중점을 둔다는 것입니다. 업데이트는 React를 더 쉽게 학습하고 까다로운 설정을 처리하는 대신 생성에 더 많은 시간을 할애할 수 있도록 설계되었습니다. 새로운 기능 중 일부는 획기적인 변화를 가져올 수 있으며 작업 방식에 큰 변화를 가져올 수 있으므로 절대 놓치고 싶지 않을 것입니다.

항상 복잡한 말을 쓰지 않고 이해하기 쉽게 설명하려고 노력합니다. 이 글도 예외는 아닙니다. 제 목표는 여러분이 모든 것을 명확하게 이해할 수 있도록 하는 것입니다. React 19의 놀라운 업데이트를 함께 살펴보겠습니다!

React 19는 아직 안정적이지 않습니다. 현재는 React Canary라고 불립니다. 따라서 실제로 제작에 권장되는 것은 아니라는 점 참고해주세요.

리액트 컴파일러

React 애플리케이션을 최적화하기 위해 우리는 useMemo, useCallback 또는 memo와 같은 내장 메소드를 사용합니다. 이는 입력이 변경되지 않으면 React가 코드를 다시 컴파일하지 않도록 지시합니다. 그러나 메모 적용을 잊어버리면 React 리소스와 계산 능력이 낭비됩니다. 이를 해결하기 위해 React 19에서는 React Compiler를 도입했습니다. React의 새로운 컴파일러는 19번째 버전의 새 릴리스의 핵심입니다. 새로운 컴파일러는 백그라운드에서 코드를 최적화하므로 이러한 후크를 제거하고 아름답고 깔끔한 React 구성 요소를 작성하는 데 집중할 수 있습니다.

간단히 말하면, 성능 최적화를 위해 useMemo나 useCallback으로 함수를 래핑할 필요가 없으며, 컴포넌트가 다시 렌더링되는 것을 방지하기 위해 컴포넌트를 메모로 래핑할 필요도 없습니다.

작업(useTransition 후크)

말도 안 되는 얘기 좀 해보자?! React 19가 나오기 전에는 useTransition 후크가 거의 언급되지 않았다는 사실을 알고 계셨나요? 아니면 나만 그런 걸까? 글쎄요, 적어도 저는 특히 주니어 개발자들 사이에서 그런 점을 발견했습니다. 어쨌든, 이전 버전에서는 어떻게 작동했는지에 대한 아이디어를 제공하고 이제 이 기능이 왜 그렇게 중요한지 살펴보겠습니다.

useTransition은 startTransition 함수와 isPending 부울이라는 두 가지 요소가 있는 배열을 반환합니다. startTransition 함수 내에서 상태 업데이트를 래핑하여 전환(우선순위가 낮은 코드)으로 표시할 수 있습니다. 이는 다른 연속 작업이 완료된 후에 startTransition으로 래핑된 부분이 작동하기 시작한다는 의미입니다.

React 18에서 startTransition 함수는 비동기 함수를 직접 지원하지 않았습니다. startTransition은 업데이트를 낮은 우선순위로 표시하도록 설계되었지만 기본적으로 비동기 논리를 처리할 수 없었기 때문에 이는 제한 사항이었습니다.

React 19에서는 이 제한 사항이 해결되었습니다. 이제 startTransition은 비동기 기능을 지원합니다. 즉, 해당 업데이트를 전환으로 표시된 상태로 유지하면서 내부에서 비동기 작업(예: 데이터 가져오기)을 수행할 수 있습니다. 이러한 개선 사항을 통해 startTransition을 보다 유연하고 직관적으로 사용할 수 있으므로 기술적으로는 기존 기능이 개선되었음에도 불구하고 "새로운" 기능처럼 느껴집니다.

?
관례적으로 비동기 전환을 사용하는 기능을 "액션"이라고 합니다.

예를 들어 useState에서 보류 및 오류 상태를 처리할 수 있습니다.

// Before 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>
  );
}

React 19는 보류 상태, 오류, 양식 및 낙관적 업데이트를 자동으로 처리하기 위해 전환 시 비동기 함수 사용을 지원합니다. 예를 들어, useTransition을 사용하여 보류 상태를 처리할 수 있습니다.

// Using pending state from Actions
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의 반응성과 대화형을 유지할 수 있습니다.

<양식> 행위

React 팀은 함수를 액션으로 전달하는 지원을 추가했습니다.

export default function App() {
    const [name, setName] = useState(
        () => JSON.parse(localStorage.getItem("name")) || "Anonymous user"
    )

    async function formAction(formData){
        try {
            const newName = await updateNameInDB(formData.get("name"))
            setName(newName)
        }
    }

    return (
        <>
            <p className="username">
                Current user: <span>{name}</span>
            </p>
            <form action={formAction}>
                <input
                    type="text"
                    name="name"
                    required
                />
                <button type="submit">Update</button>
            </form>
        </>
    )
}

formAction 함수(무엇이든 이름을 지정할 수 있음)는 해당 매개변수 내에서 양식 데이터를 가져옵니다. 각 필드는 이름 속성으로 표시되므로 입력 이름을 지정할 때 주의해야 합니다. formData 매개변수는 실제로 기본 FormData 웹 API 개체입니다. mdn 웹문서에서 확인하실 수 있습니다. 또 다른 좋은 점은 React에서 처리하므로 event.preventDefault()를 적용할 필요가 없다는 것입니다.

양식 Action이 성공하면 React는 자동으로 양식을 재설정합니다. 하지만

수동으로 새로운 requestFormReset React DOM API를 호출할 수 있습니다.

새로운 후크: useActionState

?
React.useActionState는 이전에 Canary 릴리스에서 ReactDOM.useFormState라고 불렸지만 이름이 바뀌었고 더 이상 사용되지 않습니다.

useActionState는 구성 요소 상태, 보류 상태를 추적하고 양식이나 변형을 수행하려는 다른 위치에서 사용할 수 있는 래핑된 작업 기능을 제공합니다.

다음은 좀 더 자세히 설명하는 예입니다.

import { useActionState } from "react"
import { updateNameInDB } from "../api/user"

export default function App() {
    const [user, formAction, isPending] = useActionState(insertName, {
        name: "John Doe",
        error: null
    })

    async function insertName(prevState, formData){
        try {
            const response = await updateNameInDB(formData.get("name"))
            return {name: response.name}
        }catch(error){
            return {...prevState, error: error.error}
        }
    }

    return (
        <>
            {user?.name && (
                <p>



<p>How this hook works is described with reference to the example:</p>

<ol>
<li><p>The first argument of the useActionState hook is the "Action" function, which is defined here as insertName.</p></li>
<li><p>The second argument is the initial state, which is accessible through the first element of the result array. In this example, the initial state includes name and error, and the state is represented as user in the component.</p></li>
<li><p>The insertName function returns the updated state. If the operation is successful, it updates the name property. If an error occurs, it updates the error property while preserving the rest of the previous state.</p></li>
<li>
<p>The result of the useActionState hook is an array with three elements:</p>

<ul>
<li>The current state (user): Reflects the latest state of the data.</li>
<li>A dispatchable function (formAction): Triggers the action when called, as seen in the form element's action attribute.</li>
<li>A pending state (isPending): Tracks whether the action is currently in progress, useful for managing transitions or loading indicators.</li>
</ul>
</li>
</ol>

<h2>
  
  
  New Hook: useOptimistic
</h2>

<p>When it’s performing a data mutation and to show the final state right after the user instructs (could be a tap on a button) or you could say optimistically while the async request is underway, you need to use this hook. Here is a demonstration how you can do this:<br>
</p>

<pre class="brush:php;toolbar:false">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을 즉시 렌더링합니다. 업데이트가 완료되면 React는 currentName에 업데이트된 값을 삽입하거나 업데이트에 오류가 발생하면 자동으로 currentName 값으로 다시 전환합니다.

새로운 후크: useFormStatus

useFormStatus 후크는 양식 제출을 추적하는 데 도움이 됩니다. 잠깐 기다려요 ?! 비동기 전환을 추적하는 또 다른 후크입니까? 대답은 '예'와 '아니요' 둘 다입니다. useActionState 후크를 이미 배웠으므로 이것이 비동기 전환을 추적하기 위한 또 다른 후크라고 말할 수 있습니다. 그러나 useFormStatus는 어떤 작업도 발생시키지 않고 마지막 양식 제출의 상태 정보를 제공합니다.

// Before 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>
  );
}

글쎄, 여기서 주목해야 할 가장 중요한 점은 useFormStatus 후크가 실제로 React가 아닌 React-dom에서 나온다는 것입니다.

useFormStatus는 상위 의 상태를 읽습니다. 마치 양식이 컨텍스트 제공자인 것처럼 말입니다. 상태 정보를 얻으려면 제출 구성 요소가 내에서 렌더링되어야 합니다. 후크는 양식이 적극적으로 제출 중인지 알려주는 보류 속성과 같은 정보를 반환합니다.

위 예에서 제출은 이 정보를 사용하여 <버튼> 양식이 제출되는 동안 키를 누르세요.

새로운 API: 사용

사용하여 Promise를 읽을 수 있으며 React는 Promise가 해결될 때까지 구성 요소를 일시 중단합니다.

// Using pending state from Actions
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>
  );
}

위의 예는 사용 API의 사용 사례를 보여줍니다. 'Comments'는 'commentsPromise'라는 약속을 소비하는 구성 요소입니다. Promise는 구성 요소를 일시 중지하는 새로운 사용 API에 의해 사용됩니다. 그런데 Suspense fallback으로 컴포넌트를 래핑해야 합니다.

사용 API에는 주의해야 할 제한 사항이 있습니다. 제한 사항은 구성 요소가 포함된 사용 API가 다시 렌더링될 때마다 성능 저하로 이어지는 또 다른 약속을 생성한다는 것입니다. 따라서 기본적으로 캐싱 메커니즘이 없습니다. 다음은 출시 블로그의 주의 사항입니다.

What New React Has Brought to The Table - Get Clear Understanding

API를 사용하면 컨텍스트에서도 데이터를 읽을 수 있습니다. 예를 들어 컨텍스트 값을 읽으려면 간단히 컨텍스트를 use()에 전달하면 이 함수는 구성 요소 트리를 순회하여 가장 가까운 컨텍스트 공급자를 찾습니다.

컨텍스트를 읽는 useContext() 후크와 달리 use() 함수는 구성 요소의 조건 및 루프 내에서 사용할 수 있습니다!

export default function App() {
    const [name, setName] = useState(
        () => JSON.parse(localStorage.getItem("name")) || "Anonymous user"
    )

    async function formAction(formData){
        try {
            const newName = await updateNameInDB(formData.get("name"))
            setName(newName)
        }
    }

    return (
        <>
            <p className="username">
                Current user: <span>{name}</span>
            </p>
            <form action={formAction}>
                <input
                    type="text"
                    name="name"
                    required
                />
                <button type="submit">Update</button>
            </form>
        </>
    )
}

소품으로 ref (forwardRef 없음)

React 19에서는 다른 prop과 마찬가지로 ref를 전달할 수 있으며 이로 인해 전달이 중단됩니다. 이렇게 하면 구성 요소 코드가 간소화되고 참조 처리가 쉬워집니다. ?

import { useActionState } from "react"
import { updateNameInDB } from "../api/user"

export default function App() {
    const [user, formAction, isPending] = useActionState(insertName, {
        name: "John Doe",
        error: null
    })

    async function insertName(prevState, formData){
        try {
            const response = await updateNameInDB(formData.get("name"))
            return {name: response.name}
        }catch(error){
            return {...prevState, error: error.error}
        }
    }

    return (
        <>
            {user?.name && (
                <p>



<p>How this hook works is described with reference to the example:</p>

<ol>
<li><p>The first argument of the useActionState hook is the "Action" function, which is defined here as insertName.</p></li>
<li><p>The second argument is the initial state, which is accessible through the first element of the result array. In this example, the initial state includes name and error, and the state is represented as user in the component.</p></li>
<li><p>The insertName function returns the updated state. If the operation is successful, it updates the name property. If an error occurs, it updates the error property while preserving the rest of the previous state.</p></li>
<li>
<p>The result of the useActionState hook is an array with three elements:</p>

<ul>
<li>The current state (user): Reflects the latest state of the data.</li>
<li>A dispatchable function (formAction): Triggers the action when called, as seen in the form element's action attribute.</li>
<li>A pending state (isPending): Tracks whether the action is currently in progress, useful for managing transitions or loading indicators.</li>
</ul>
</li>
</ol>

<h2>
  
  
  New Hook: useOptimistic
</h2>

<p>When it’s performing a data mutation and to show the final state right after the user instructs (could be a tap on a button) or you could say optimistically while the async request is underway, you need to use this hook. Here is a demonstration how you can do this:<br>
</p>

<pre class="brush:php;toolbar:false">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>
  );
}

React 팀은 향후 버전에서 ForwardRef를 더 이상 사용하지 않기로 결정했습니다.

반응 서버 구성 요소

그런데, RSC(React Server Components)는 서버측 렌더링을 지원하는 React 기능이지만 Next.js와 같은 프레임워크는 RSC를 수용하여 작업 흐름에 원활하게 통합했습니다. 생태계에 처음 오신 분이라면 메커니즘 연구에 뛰어들기 전에 이 점을 명확히 하세요.

React 서버 구성 요소는 서버에서 실행

되는 상태 비저장 React 구성 요소를 생성할 수 있도록 하는 React 19에 도입된 새로운 기능입니다.

React 서버 구성요소는 웹 서버에서 실행될 수 있으므로 API와 상호작용하지 않고도 데이터 레이어에 액세스하는 데 사용할 수 있습니다!

// Before 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>
  );
}

이를 사용하면 API 엔드포인트를 노출하거나 추가 클라이언트 측 가져오기 로직을 ​​사용하여 데이터를 구성 요소에 직접 로드할 필요가 없습니다. 모든 데이터 처리는 서버에서 이루어집니다.

서버 구성 요소는 브라우저가 아닌 서버에서 실행된다는 점을 명심하세요. 결과적으로 useState와 같은 기존 React 구성 요소 API를 사용할 수 없습니다. React 서버 구성 요소 설정에 상호 작용 기능을 도입하려면 상호 작용 처리를 위해 서버 구성 요소를 보완하는 클라이언트 구성 요소를 활용해야 합니다.

React 서버 구성 요소로 작업할 때 "클라이언트 사용"은 구성 요소가 클라이언트 구성 요소임을 의미합니다. 즉, 상태를 관리하고, 사용자 상호 작용을 처리하고, 브라우저별 API를 사용할 수 있다는 의미입니다. 이 지시어는 React 프레임워크와 번들러에게 이 구성 요소를 상태 비저장이고 서버에서 실행되는 서버 구성 요소와 다르게 처리하도록 명시적으로 지시합니다.

// Using pending state from Actions
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>
  );
}

반면에는 React 서버 구성 요소가 기본값이므로 서버 구성 요소 파일 상단에 "서버 사용"을 명시하지 않습니다. 대신 "서버 사용"은 클라이언트 구성요소에서 호출할 수 있는 서버측 기능을 표시하는 데에만 사용해야 합니다.

export default function App() {
    const [name, setName] = useState(
        () => JSON.parse(localStorage.getItem("name")) || "Anonymous user"
    )

    async function formAction(formData){
        try {
            const newName = await updateNameInDB(formData.get("name"))
            setName(newName)
        }
    }

    return (
        <>
            <p className="username">
                Current user: <span>{name}</span>
            </p>
            <form action={formAction}>
                <input
                    type="text"
                    name="name"
                    required
                />
                <button type="submit">Update</button>
            </form>
        </>
    )
}

이 예를 보면 잘 알 수 있을 것 같습니다.

결론

React 19는 여전히 React Canary라고 불립니다. 따라서 이를 프로덕션에 사용하는 것은 좋은 생각이 아닙니다. 하지만 React 19로 미래를 포용하고 개발 경험을 더욱 원활하고 즐겁게 만드세요.

위 내용은 새로운 React가 테이블에 가져온 것 - 명확한 이해를 얻으세요의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.