리액트 앱의 일반적인 사용 사례는 데이터 변형(Mutation)을 수행한 다음 이에 대한 응답으로 상태를 업데이트하는 것이다. 예를 들어 사용자가 이름을 변경하기 위해 양식을 제출하면 API 요청을 한 다음 응답을 처리한다. 예전에는 보류(pending) 상태, 오류, 낙관적 업데이트 및 순차적 요청을 수동으로 처리해야 했다.
예를 들어 다음에서 보류 및 에러 상태를 처리할 수 있다.
// 액션 전 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> ); }
// 액션 전 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에서는 보류 상태, 에러, 양식(form) 및 낙관적 업데이트를 자동으로 처리하기 위해 전환(transitions)에서 비동기 함수를 사용하는 지원을 추가하고 있다.
예를 들어 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> ); }
// 액션에서 보류 상태 사용 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
hook을 지원하므로 요청이 제출되는 동안 사용자에게 즉각적인 피드백을 표시할 수 있다.<form>
요소는 이제 action
및 formAction
props에 함수 전달을 지원한다. props에 함수를 전달하면 action
기본적으로 Actions가 사용되며 제출 후 자동으로 양식이 재설정된다.액션을 기반으로 리액트 19에서는 낙관적 업데이트를 관리하기 위한 useOptimistic
과 Actions의 일반적인 사례를 처리하기 위한 새로운 후크 React.useActionState
을 도입했다.
양식을 자동으로 관리하고 양식의 작업에 대한 일반적인 사례를 지원하는 useFormStatus
를 react-dom
에 추가하고 있다.
React 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> ); }
// <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> ); }
다음 섹션에서는 React 19의 새로운 액션기능을 각각 분석하겠다.
useActionState
액션의 일반적인 경우를 더 쉽게 만들기 위해 useActionState
새 hook을 추가했다.
const [error, submitAction, isPending] = useActionState( async (previousState, newName) => { const error = await updateName(newName); if (error) { // 액션 결과는 모두 반환할 수 있다. // 여기서는 오류만 반환한다. return error; } // 여기서는 성공했을 때를 다룬다. return null; }, null, );
const [error, submitAction, isPending] = useActionState( async (previousState, newName) => { const error = await updateName(newName); if (error) { // 액션 결과는 모두 반환할 수 있다. // 여기서는 오류만 반환한다. return error; } // 여기서는 성공했을 때를 다룬다. return null; }, null, );
useActionState
는 함수("액션")를 받아들이고 호출할 래핑된 액션을 반환한다. 이는 액션이 구성되기 때문에 작동한다. 래핑된 액션이 호출되면 useActionState
는 Action의 마지막 결과를 data
로 반환하고, 액션의 보류 상태를 pending
로 반환한다.
자세한 내용은 에 대한 문서를 참조하세요 useActionState
.
<form>
액션 액션은 react-dom
을 위해 리액트 19의 새로운 <form>
기능과도 통합되었다.
액션을 사용하여 양식을 자동으로 제출하기 위해 함수를 <form>
, <input>
, <button>
요소의 action
및 formAction
props로 전달하는 지원을 추가했다.
<form action={actionFunction}>
<form action={actionFunction}>
<form>
작업이 성공하면 리액트는 제어되지 않은 컴포넌트의 양식을 자동으로 재설정한다.
<form>
을 수동으로 재설정해야 하는 경우, 새 requestFormReset
React DOM API를 호출할 수 있다
자세한 내용은 react-dom
의 <form>
, <input>
및 <button>
에 대한 설명서를 참조하십시오.
useFormStatus
디자인 시스템에서는 일반적으로 컴포넌트에 props를 드릴 다운하지 않고 컴포넌트가 포함된 <form>
에 대한 정보에 액세스해야 하는 디자인 컴포넌트를 만든다. 이것은 Context
를 통해서 실행할 수 있지만, 일반적인 케이스를 간단하게 하기 위해서, 새로운 훅 useFormStatus
를 추가했다.
import {useFormStatus} from 'react-dom'; function DesignButton() { const {pending} = useFormStatus(); return <button type="submit" disabled={pending} /> }
import {useFormStatus} from 'react-dom'; function DesignButton() { const {pending} = useFormStatus(); return <button type="submit" disabled={pending} /> }
useFormStatus
는 양식이 컨텍스트 공급자인 것처럼 부모 <form>
의 상태를 읽는다.
자세한 내용은 react-dom
에 대한 문서를 참조해라. useFormStatus
.
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> ); }
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
hook은 updateName
요청이 진행되는 동안 optimisticName
을 즉시 렌더링한다. 업데이트가 완료되거나 오류가 발생하면 리액트는 자동으로 currentName
값으로 돌아갑니다.
자세한 내용은 useOptimistic
문서를 참조하십시오.
use
리액트 19에서는 렌더링에서 리소스를 읽는 새로운 API use
를 도입했다.
예를 들어, use
를 사용하여 Promise를 읽을 수 있으며 Promise가 해결될 때까지 리액트가 일시 중지된다.
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}) { // `use`가 Comments를 일시 중지 할 때, // 이 Suspense boundary가 보여질 것이다. return ( <Suspense fallback={<div>Loading...</div>}> <Comments commentsPromise={commentsPromise} /> </Suspense> ) }
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}) { // `use`가 Comments를 일시 중지 할 때, // 이 Suspense boundary가 보여질 것이다. return ( <Suspense fallback={<div>Loading...</div>}> <Comments commentsPromise={commentsPromise} /> </Suspense> ) }
use
를 사용해 컨텍스트를 읽어들일 수도 있고, 조기 반환 후와 같은 조건부 컨텍스트를 읽을 수 있다.
import {use} from 'react'; import ThemeContext from './ThemeContext' function Heading({children}) { if (children == null) { return null; } // 조기 반환 때문에 useContext에서는 작동하지 않습니다. const theme = use(ThemeContext); return ( <h1 style={{color: theme.color}}> {children} </h1> ); }
import {use} from 'react'; import ThemeContext from './ThemeContext' function Heading({children}) { if (children == null) { return null; } // 조기 반환 때문에 useContext에서는 작동하지 않습니다. const theme = use(ThemeContext); return ( <h1 style={{color: theme.color}}> {children} </h1> ); }
use
API는 hooks와 마찬가지로 렌더링에서만 호출할 수 있다. hooks와 달리 use
는 조건부로 호출할 수 있다. 향후 사용에 따라 렌더링에서 리소스를 소비하는 더 많은 방법을 지원할 예정이다.
자세한 내용은 use
문서를 참조하십시오.
서버 컴포넌트는 번들 전에 클라이언트 응용 프로그램이나 SSR 서버와는 별도의 환경에서 컴포넌트를 미리 렌더링할 수 있는 새로운 옵션이다. 이 또 다른 환경은 React Server Components의 "서버"입니다. 서버 컴포넌트는 CI 서버에서 빌드할 때 한 번 실행하거나 웹 서버를 사용하여 요청별로 실행할 수 있다.
React 19에는 Canary 채널에 포함된 모든 React Server Components 기능이 포함되어 있다. 이는 서버 컴포넌트와 함께 제공되는 라이브러리가 풀스택 리액트 아키텍처를 지원하는 프레임워크에서 사용할 수 있도록 리액트 서버 export condition이 있는 피어 종속성으로 리액트 19를 대상으로 할 수 있음을 의미한다.
서버 액션을 사용하면 클라이언트 컴포넌트가 서버에서 실행되는 비동기 기능을 호출할 수 있다.
서버 액션이 "use server"
지시문에 정의되어 있으면 프레임워크는 자동으로 서버 함수에 대한 참조를 만들고 해당 참조를 클라이언트 컴포넌트에 전달합니다. 함수가 클라이언트에서 호출되면 리액트는 서버에 요청을 보내 함수를 실행하고 결과를 반환한다.
서버 액션은 서버 컴포넌트에서 생성되어 클라이언트 컴포넌트에 props로 전달되거나 클라이언트 컴포넌트에서 가져와 사용할 수 있다.
ref
React 19부터 이제 함수 컴포넌트에 대한 prop으로 ref에 액세스할 수 있다.
function MyInput({placeholder, ref}) { return <input placeholder={placeholder} ref={ref} /> } //... <MyInput ref={ref} />
function MyInput({placeholder, ref}) { return <input placeholder={placeholder} ref={ref} /> } //... <MyInput ref={ref} />
새로운 함수 컴포넌트에는 forwardRef
가 필요 없게 되어, 새로운 ref
prop 를 사용하도록 컴포넌트를 자동적으로 갱신하는 codemod를 공개할 예정이다. 향후 버전에서는 forwardRef
가 더 이상 사용되지 않으며 삭제될 예정이다.
react-dom
에서 하이드레이션 오류에 대한 오류 보고도 개선되었다. 예를 들어 불일치에 대한 정보 없이 DEV에 여러 오류를 기록하는 대신 다음을 수행한다.
이제 불일치 차이가 포함된 단일 메시지를 기록한다.
<Context>
React 19에서는 <Context.Provider>
대신 공급자로서 <Context>
를 렌더링할 수 있다.
const ThemeContext = createContext(''); function App({children}) { return ( <ThemeContext value="dark"> {children} </ThemeContext> ); }
const ThemeContext = createContext(''); function App({children}) { return ( <ThemeContext value="dark"> {children} </ThemeContext> ); }
새로운 컨텍스트 공급자가 <Context>
를 사용할 수 있으며 기존 공급자를 변환하기 위해 codemod를 게시할 예정이다. 향후 버전에서는 <Context.Provider>
가 더 이상 사용되지 않는다.
이제 ref
콜백에서 정리 함수 반환을 지원한다 .
<input ref={(ref) => { // ref // 새기능: 재설정할 정리 함수를 반환한다. // 요소가 DOM에서 제거될 때 ref return () => { // ref cleanup }; }} />
<input ref={(ref) => { // ref // 새기능: 재설정할 정리 함수를 반환한다. // 요소가 DOM에서 제거될 때 ref return () => { // ref cleanup }; }} />
컴포넌트가 언마운트되면, 리액트는 ref
콜백에서 반환된 정리 함수를 호출합니다. 이는 DOM refs, 클래스 컴포넌트에 대한 refs 및 useImperativeHandle
에서 작동한다.
참조 정리 함수의 도입으로 인해, ref
콜백에서 다른 항목을 반환하는 것은 이제 타입스크립트에서 거부된다. 수정 방법은 일반적으로 암시적 반환 사용을 중지하는 것이다.
예를 들면 다음과 같습니다.
- <div ref={current => (instance = current)} /> + <div ref={current => {instance = current}} />
- <div ref={current => (instance = current)} /> + <div ref={current => {instance = current}} />
원래의 코드는 HTMLDivElement
의 인스턴스를 돌려주고 있어, 타입스크립트는 이것이 클린 업 함수여야 하는지, 아니면 클린 업 함수를 돌려주고 싶지 않은지 모른다.
no-implicit-ref-callback-return
을 사용하여 이 패턴을 codemod할 수 있다.
useDeferredValue
초기 값 useDeferredValue
에 initialValue
옵션을 추가했다.
function Search({deferredValue}) { // On initial render the value is ''. // Then a re-render is scheduled with the deferredValue. const value = useDeferredValue(deferredValue, ''); return ( <Results query={value} /> ); }
function Search({deferredValue}) { // On initial render the value is ''. // Then a re-render is scheduled with the deferredValue. const value = useDeferredValue(deferredValue, ''); return ( <Results query={value} /> ); }
InitialValue
가 제공되면 useDeferredValue
는 컴포넌트의 초기 렌더링 값으로 반환하고, 반환된 deferredValue
를 사용하여 백그라운드에서 리렌더링을 예약한다.
자세한 내용은 [useDeferredValue](https://react.dev/reference/react/useDeferredValue)
를 참조하십시오.
HTML에서는 <title>
, <link>
, <meta>
와 같은 문서 메타데이터 태그가 문서의 <head>
섹션에 배치되도록 예약되어 있다. 리액트는 앱에 적합한 메타데이터를 결정하는 컴포넌트가 <head>
를 렌더링하는 곳에서 매우 멀거나 리액트가 <head>
를 전혀 렌더링하지 않을 수 있다. 이전에는 이러한 요소를 effect에 수동으로 삽입하거나 react-helmet
와 같은 라이브러리로 삽입해야 했으며 서버가 리액트 응용 프로그램을 렌더링 할 때 신중한 처리가 필요했다.
React 19에서는 컴포넌트의 문서 메타데이터 태그를 네이티브로 렌더링할 수 있는 지원을 추가한다.
function BlogPost({post}) { return ( <article> <h1>{post.title}</h1> <title>{post.title}</title> <meta name="author" content="Josh" /> <link rel="author" href="https://twitter.com/joshcstory/" /> <meta name="keywords" content={post.keywords} /> <p> Eee equals em-see-squared... </p> </article> ); }
function BlogPost({post}) { return ( <article> <h1>{post.title}</h1> <title>{post.title}</title> <meta name="author" content="Josh" /> <link rel="author" href="https://twitter.com/joshcstory/" /> <meta name="keywords" content={post.keywords} /> <p> Eee equals em-see-squared... </p> </article> ); }
React가 이 컴포넌트를 렌더링하면, <title>
<link>
및 <meta>
태그가 인식되고, 문서의 <head>
섹션에 자동으로 호이스트됩니다. 이러한 메타데이터 태그를 기본적으로 지원하면 클라이언트 전용 앱, 스트리밍 SSR 및 서버 컴포넌트에서 안정적으로 작동할 수 있다.
자세한 내용은 <title>
, [<link>
](https://react.dev/reference/react-dom/components/link`, and <meta>
문서를 참조해라.
스타일시트는 외부 링크(<link rel="stylesheet" href="...">
)와 인라인(<style>...</style>
) 모두에서 스타일 우선 순위 규칙이므로 DOM 내부에 조심스럽게 배치해야한다. 컴포넌트 내에서 구성 가능하게 만드는 스타일 시트 기능을 구축하기가 어렵기 때문에 사용자는 종종 스타일에 의존 할 수 있는 컴포넌트에서 멀리 떨어진 곳에서 모든 스타일을 로드하거나, 이 복잡성을 캡슐화할 스타일 라이브러리를 사용한다.
리액트 19는 이러한 복잡성을 해결하고 스타일시트를 지원하며 클라이언트에서 동시 렌더링과 서버에서 스트리밍 렌더링에 더욱 깊은 통합을 제공한다. 리액트가 스타일 시트 우선 순위 (precedence
)를 지정하면 DOM에서 스타일 시트 삽입 순서가 관리되고 스타일 규칙에 의존하는 내용이 표시되기 전에 스타일 시트(외부의 경우)를 로드하는 것을 보장한다.
function ComponentOne() { return ( <Suspense fallback="loading..."> <link rel="stylesheet" href="foo" precedence="default" /> <link rel="stylesheet" href="bar" precedence="high" /> <article class="foo-class bar-class"> {...} </article> </Suspense> ) } function ComponentTwo() { return ( <div> <p>{...}</p> <link rel="stylesheet" href="baz" precedence="default" /> <-- will be inserted between foo & bar </div> ) }
function ComponentOne() { return ( <Suspense fallback="loading..."> <link rel="stylesheet" href="foo" precedence="default" /> <link rel="stylesheet" href="bar" precedence="high" /> <article class="foo-class bar-class"> {...} </article> </Suspense> ) } function ComponentTwo() { return ( <div> <p>{...}</p> <link rel="stylesheet" href="baz" precedence="default" /> <-- will be inserted between foo & bar </div> ) }
서버 측 렌더링 중에 리액트는 <head>
에 스타일 시트를 포함한다. 이렇게 하면 브라우저가 로드될 때까지 그려지지 않는다. 이미 스트리밍을 시작한 후 스타일 시트가 발견되면 리액트는 스타일 시트에 의존하는 서스펜스 경계의 내용을 게시하기 전에 스타일 시트가 클라이언트의 <head>
에 삽입되었는지 확인한다.
클라이언트측 렌더링 중에 리액트는 렌더링을 커밋하기 전에 새로 렌더링된 스타일시트가 로드될 때까지 기다린다. 이 컴포넌트를 응용 프로그램의 여러 위치에서 렌더링하는 경우 리액트는 스타일시트를 문서에 한 번만 포함한다.
function App() { return <> <ComponentOne /> ... <ComponentOne /> // DOM에서 중복된 스타일시트 링크로 연결되지 않는다. </> }
function App() { return <> <ComponentOne /> ... <ComponentOne /> // DOM에서 중복된 스타일시트 링크로 연결되지 않는다. </> }
스타일시트를 수동으로 로드하는 데 익숙한 사용자에게는 스타일시트에 의존하는 컴포넌트와 함께 스타일시트를 찾을 수 있는 기회가 되며, 보다 적절한 로컬 추론이 가능하며 실제로 의존하는 스타일시트만 로드하는 것이 더 쉽다.
스타일 라이브러리 및 번들러와 스타일 통합을 통해 이 새로운 기능을 채택할 수 있으므로 자체 스타일시트를 직접 렌더링하지 않고도 이 기능을 사용하도록 도구를 업그레이드하여 이점을 누릴 수 있다.
자세한 내용은 <link>
및 <style>
문서를 참조하십시오.
HTML에서 일반 스크립트(<script src="...">
)와 지연 스크립트(<script defer=""src="...">
)는 문서 순서로 로드되므로 컴포넌트 트리의 깊은 곳에서 이러한 종류의 스크립트를 렌더링하기가 어렵다. 그러나 비동기 스크립트(<script async=""src="...">
)는 임의의 순서로 로드된다.
React 19는 비동기 스크립트 지원을 향상시켜 스크립트 인스턴스의 재배치 및 중복 제거를 관리하지 않고 컴포넌트 트리의 아무 곳이나 실제로 스크립트에 의존하는 컴포넌트 내에서 비동기 스크립트를 렌더링 할 수 있도록 한다.
function MyComponent() { return ( <div> <script async={true} src="..." /> Hello World </div> ) } function App() { <html> <body> <MyComponent> ... <MyComponent> // DOM에서 중복된 스크립트로 연결되지 않는다. </body> </html> }
function MyComponent() { return ( <div> <script async={true} src="..." /> Hello World </div> ) } function App() { <html> <body> <MyComponent> ... <MyComponent> // DOM에서 중복된 스크립트로 연결되지 않는다. </body> </html> }
모든 렌더링 환경에서 비동기 스크립트는 중복 제거되므로, 여러 다른 컴포넌트에 의해 렌더링되는 경우에도 리액트는 스크립트를 한 번만 로드하고 실행한다.
서버 사이드 렌더링에서 비동기 스크립트는 <head>
에 포함되며 스타일시트, 글꼴, 이미지 미리 로드 등의 페인트를 차단하는 더 중요한 리소스 뒤에 우선 순위가 지정된다.
자세한 내용은 [<script>](https://react.dev/reference/react-dom/components/script)
문서를 참조하십시오.
문서 초기 로드 및 클라이언트 측 업데이트 중에 가능한 한 빨리 로드해야 하는 리소스를 브라우저에 알리면 페이지 성능에 극적인 영향을 줄 수 있다.
리액트 19에는 브라우저 리소스를 로드하고 사전 로드할 수 있는 많은 새로운 API가 포함되어 있어 비효율적인 리소스 로드로 인해 방해받지 않는 뛰어난 경험을 최대한 쉽게 구축할 수 있다.
import { prefetchDNS, preconnect, preload, preinit } from 'react-dom' function MyComponent() { preinit('https://.../path/to/some/script.js', {as: 'script' }) // loads and executes this script eagerly preload('https://.../path/to/font.woff', { as: 'font' }) // preloads this font preload('https://.../path/to/stylesheet.css', { as: 'style' }) // preloads this stylesheet prefetchDNS('https://...') // when you may not actually request anything from this host preconnect('https://...') // when you will request something but aren't sure what }
import { prefetchDNS, preconnect, preload, preinit } from 'react-dom' function MyComponent() { preinit('https://.../path/to/some/script.js', {as: 'script' }) // loads and executes this script eagerly preload('https://.../path/to/font.woff', { as: 'font' }) // preloads this font preload('https://.../path/to/stylesheet.css', { as: 'style' }) // preloads this stylesheet prefetchDNS('https://...') // when you may not actually request anything from this host preconnect('https://...') // when you will request something but aren't sure what }
<!-- the above would result in the following DOM/HTML --> <html> <head> <!-- links/scripts are prioritized by their utility to early loading, not call order --> <link rel="prefetch-dns" href="https://..."> <link rel="preconnect" href="https://..."> <link rel="preload" as="font" href="https://.../path/to/font.woff"> <link rel="preload" as="style" href="https://.../path/to/stylesheet.css"> <script async="" src="https://.../path/to/some/script.js"></script> </head> <body> ... </body> </html>
<!-- the above would result in the following DOM/HTML --> <html> <head> <!-- links/scripts are prioritized by their utility to early loading, not call order --> <link rel="prefetch-dns" href="https://..."> <link rel="preconnect" href="https://..."> <link rel="preload" as="font" href="https://.../path/to/font.woff"> <link rel="preload" as="style" href="https://.../path/to/stylesheet.css"> <script async="" src="https://.../path/to/some/script.js"></script> </head> <body> ... </body> </html>
이러한 API를 사용하면 글꼴과 같은 추가 리소스 검색을 스타일시트 로드에서 이동하여 첫 페이지 로드를 최적화할 수 있다. 또한 예상되는 탐색에 사용되는 리소스 목록을 프리페치하고 클릭 또는 호버 시 해당 리소스를 적극적으로 미리 로드하여 클라이언트 업데이트를 가속화할 수 있다.
자세한 내용은 Resource Preloading APIs를 참조하십시오.
타사 스크립트 및 브라우저 확장을 고려하여 하이드레이션을 개선했다.
하이드레이션 중에 클라이언트에서 렌더링되는 요소가 서버에서 HTML에서 찾은 요소와 일치하지 않으면 리액트는 콘텐츠를 수정하기 위해 클라이언트를 강제로 다시 렌더링한다. 이전에는 요소가 타사 스크립트 또는 브라우저 확장으로 삽입된 경우 불일치 오류가 발생하여 클라이언트가 렌더링되었다.
React 19에서는 <head>
및 <body>
의 예기치 않은 태그를 건너뛰고 불일치 오류를 방지한다. 관련이 없는 하이드레이션 불일치로 인해 리액트가 전체 문서를 다시 렌더링해야 하는 경우 타사 스크립트나 브라우저 확장에 의해 삽입된 스타일시트가 그대로 유지된다.
리액트 19의 오류 처리를 개선하여 중복을 제거하고 catch된 오류와 catch되지 않은 오류를 처리하는 옵션을 제공했다. 예를 들어 렌더링에서 오류 경계(Error Boundary)에 의해 catch된 오류가 있는 경우 이전에는 리액트가 오류를 두 번 던졌습니다 (첫 번째는 원래 오류이고 다른 하나는 자동 복구가 실패한 경우). 발생한 위치에 대한 정보로 console.error를 호출한다.
그 결과 발견된 각 오류에 대해 세 가지 오류가 발생했다.
리액트 19에서는 모든 에러 정보를 포함한 단일 오류로 로그한다.
또한 onRecoverableError
를 보완하는 두 가지 새로운 루트 옵션을 추가했다.
onCaughtError
: 리액트가 오류 경계에서 오류를 잡을 때 호출된다.onUncaughtError
: 에러는 던져졌고 에러 경계에 의해 포착되지 않았던 경우에 호출된다.onRecoverableError
: 오류가 발생하면 호출되어 자동으로 복구된다.자세한 내용과 예제는 [createRoot](https://react.dev/reference/react-dom/client/createRoot)
and [hydrateRoot](https://react.dev/reference/react-dom/client/hydrateRoot)
설명서를 참조해라.
React 19는 사용자 지정 요소에 대한 완벽한 지원을 추가하여 Custom Elements Everywhere의 모든 테스트를 통과한다.
과거 버전에서는 리액트가 인식할 수 없는 props를 properties
이 아닌 attributes
으로 처리했기 때문에 리액트에서 사용자 지정 요소를 사용하기가 어려웠다. 리액트 19에서는 다음 전략을 통해 클라이언트 및 SSR에서 작동하는 속성에 대한 지원을 추가했다.
string
, number
과 같은 같은 원시 값이거나 값이 true
인 경우, attributes
로서 렌더링된다. 객체
, 심볼
, 함수
등과 같은 비 원시값 또는 값이 false인 경우 props는 생략된다.properties
로 할당되고, 그렇지 않으면 attributes
으로 할당된다.# Contact : jyw966@naver.com
Copyright © doromo. All Rights Reserved.